Як я можу відформатувати нульовий DateTime за допомогою ToString ()?


226

Як я можу перетворити нульовий DateTime dt2 у відформатований рядок?

DateTime dt = DateTime.Now;
Console.WriteLine(dt.ToString("yyyy-MM-dd hh:mm:ss")); //works

DateTime? dt2 = DateTime.Now;
Console.WriteLine(dt2.ToString("yyyy-MM-dd hh:mm:ss")); //gives following error:

відсутність перевантаження методу ToString бере один аргумент


3
Здрастуйте, чи не проти переглядати прийняті та поточні відповіді? Більш відповідна щоденна відповідь може бути правильнішою.
iuliu.net

Відповіді:


335
Console.WriteLine(dt2 != null ? dt2.Value.ToString("yyyy-MM-dd hh:mm:ss") : "n/a"); 

EDIT: Як зазначено в інших коментарях, перевірте, чи не існує нульового значення.

Оновлення: як рекомендовано в коментарях, метод розширення:

public static string ToString(this DateTime? dt, string format)
    => dt == null ? "n/a" : ((DateTime)dt).ToString(format);

А починаючи з C # 6, ви можете використовувати нульовий умовний оператор, щоб ще більше спростити код. Вираз, наведений нижче, поверне null, якщо DateTime?null.

dt2?.ToString("yyyy-MM-dd hh:mm:ss")

26
Це схоже на те, що він просить мене для розширення.
Девід Гленн

42
.Валюта - ключ
stuartdotnet

@David НЕ то, що завдання не тривіальна ... stackoverflow.com/a/44683673/5043056
Sinjai

3
Ви готові до цього ... dt? .ToString ("dd / MMM / yyyy") ?? "" Великі переваги C # 6
Том МакДонаф

Помилка CS0029: Неможливо неявно перетворити тип 'string' у 'System.DateTime?' (CS0029). .Net Core 2.0
Oracular Man

80

Спробуйте це для розміру:

Фактичний об'єкт dateTime, який ви бажаєте відформатувати, знаходиться у властивості dt.Value, а не в самому об'єкті dt2.

DateTime? dt2 = DateTime.Now;
 Console.WriteLine(dt2.HasValue ? dt2.Value.ToString("yyyy-MM-dd hh:mm:ss") : "[N/A]");

36

Ви, хлопці, все це над інженером, і це зробити складніше, ніж є насправді. Важливо, перестаньте використовувати ToString і почніть використовувати форматування рядків, як string.Format або методи, що підтримують форматування рядків, як Console.WriteLine. Ось кращий варіант вирішення цього питання. Це також найбезпечніше.

Оновлення:

Я оновлюю приклади сучасними методами сьогоднішнього компілятора C #. умовні оператори та рядкова інтерполяція

DateTime? dt1 = DateTime.Now;
DateTime? dt2 = null;

Console.WriteLine("'{0:yyyy-MM-dd hh:mm:ss}'", dt1);
Console.WriteLine("'{0:yyyy-MM-dd hh:mm:ss}'", dt2);
// New C# 6 conditional operators (makes using .ToString safer if you must use it)
// https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/operators/null-conditional-operators
Console.WriteLine(dt1?.ToString("yyyy-MM-dd hh:mm:ss"));
Console.WriteLine(dt2?.ToString("yyyy-MM-dd hh:mm:ss"));
// New C# 6 string interpolation
// https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/tokens/interpolated
Console.WriteLine($"'{dt1:yyyy-MM-dd hh:mm:ss}'");
Console.WriteLine($"'{dt2:yyyy-MM-dd hh:mm:ss}'");

Вихід: (я поміщаю в нього окремі лапки, щоб ви могли бачити, що він повертається як порожній рядок, коли null)

'2019-04-09 08:01:39'
''
2019-04-09 08:01:39

'2019-04-09 08:01:39'
''

30

Як заявили інші, вам потрібно перевірити наявність нуля перед тим, як викликати ToString, але щоб уникнути повторення, ви можете створити метод розширення, який це робить, щось на кшталт:

public static class DateTimeExtensions {

  public static string ToStringOrDefault(this DateTime? source, string format, string defaultValue) {
    if (source != null) {
      return source.Value.ToString(format);
    }
    else {
      return String.IsNullOrEmpty(defaultValue) ?  String.Empty : defaultValue;
    }
  }

  public static string ToStringOrDefault(this DateTime? source, string format) {
       return ToStringOrDefault(source, format, null);
  }

}

До яких можна викликати:

DateTime? dt = DateTime.Now;
dt.ToStringOrDefault("yyyy-MM-dd hh:mm:ss");  
dt.ToStringOrDefault("yyyy-MM-dd hh:mm:ss", "n/a");
dt = null;
dt.ToStringOrDefault("yyyy-MM-dd hh:mm:ss", "n/a")  //outputs 'n/a'

28

C # 6.0 дитини:

dt2?.ToString("dd/MM/yyyy");


2
Я б запропонував наступну версію, щоб ця відповідь була еквівалентною існуючій прийнятій відповіді на C # 6.0. Console.WriteLine(dt2?.ToString("yyyy-MM-dd hh:mm:ss" ?? "n/a");
Може Буд

15

Проблема при формулюванні відповіді на це питання полягає в тому, що ви не вказуєте бажаний вихід, коли нульовий час часу не має значення. Наступний код виведе DateTime.MinValueв такому випадку, і на відміну від прийнятої відповіді, не викидає винятку.

dt2.GetValueOrDefault().ToString(format);

7

Зважаючи на те, що ви насправді хочете надати формат, я б запропонував додати інтерфейс IFormattable до методу розширення Smalls, наприклад, таким чином, у вас немає неприємного стику шрифтового формату.

public static string ToString<T>(this T? variable, string format, string nullValue = null)
where T: struct, IFormattable
{
  return (variable.HasValue) 
         ? variable.Value.ToString(format, null) 
         : nullValue;          //variable was null so return this value instead   
}


5

Ви можете використовувати dt2.Value.ToString("format"), але звичайно, що вимагає, що dt2! = Null, і це в першу чергу заперечує використання нульового типу.

Тут є кілька рішень, але головне питання: як ви хочете відформатувати nullпобачення?


5

Ось більш загальний підхід. Це дозволить вам відформатувати рядок будь-якого типу нульового значення. Я включив другий метод, щоб дозволити переосмислення значення рядка за замовчуванням замість використання значення за замовчуванням для типу значення.

public static class ExtensionMethods
{
    public static string ToString<T>(this Nullable<T> nullable, string format) where T : struct
    {
        return String.Format("{0:" + format + "}", nullable.GetValueOrDefault());
    }

    public static string ToString<T>(this Nullable<T> nullable, string format, string defaultValue) where T : struct
    {
        if (nullable.HasValue) {
            return String.Format("{0:" + format + "}", nullable.Value);
        }

        return defaultValue;
    }
}

4

Найкоротша відповідь

$"{dt:yyyy-MM-dd hh:mm:ss}"

Тести

DateTime dt1 = DateTime.Now;
Console.Write("Test 1: ");
Console.WriteLine($"{dt1:yyyy-MM-dd hh:mm:ss}"); //works

DateTime? dt2 = DateTime.Now;
Console.Write("Test 2: ");
Console.WriteLine($"{dt2:yyyy-MM-dd hh:mm:ss}"); //Works

DateTime? dt3 = null;
Console.Write("Test 3: ");
Console.WriteLine($"{dt3:yyyy-MM-dd hh:mm:ss}"); //Works - Returns empty string

Output
Test 1: 2017-08-03 12:38:57
Test 2: 2017-08-03 12:38:57
Test 3: 


4

Синтаксис RAZOR:

@(myNullableDateTime?.ToString("yyyy-MM-dd") ?? String.Empty)

2

Я думаю, що вам доведеться використовувати GetValueOrDefault-Methode. Поведінка з ToString ("yy ...") не визначається, якщо примірник є нульовим.

dt2.GetValueOrDefault().ToString("yyy...");

1
Поведінка з ToString ( «уу ...») буде визначена , якщо екземпляр є недійсним, так як GetValueOrDefault () поверне DateTime.MinValue
Lucas

2

Ось чудова відповідь Блейка як метод розширення. Додайте це до свого проекту, і дзвінки у питанні спрацюють, як очікувалося.
Значить, він використовується як MyNullableDateTime.ToString("dd/MM/yyyy"), з тим же результатом MyDateTime.ToString("dd/MM/yyyy"), що і виняток, за винятком того, що значення буде, "N/A"якщо DateTime є нульовим.

public static string ToString(this DateTime? date, string format)
{
    return date != null ? date.Value.ToString(format) : "N/A";
}

1

IFormattable також включає провайдера формату, який можна використовувати, він дозволяє обом форматом IFormatProvider бути нульовим у dotnet 4.0, це було б

/// <summary>
/// Extentionclass for a nullable structs
/// </summary>
public static class NullableStructExtensions {

    /// <summary>
    /// Formats a nullable struct
    /// </summary>
    /// <param name="source"></param>
    /// <param name="format">The format string 
    /// If <c>null</c> use the default format defined for the type of the IFormattable implementation.</param>
    /// <param name="provider">The format provider 
    /// If <c>null</c> the default provider is used</param>
    /// <param name="defaultValue">The string to show when the source is <c>null</c>. 
    /// If <c>null</c> an empty string is returned</param>
    /// <returns>The formatted string or the default value if the source is <c>null</c></returns>
    public static string ToString<T>(this T? source, string format = null, 
                                     IFormatProvider provider = null, 
                                     string defaultValue = null) 
                                     where T : struct, IFormattable {
        return source.HasValue
                   ? source.Value.ToString(format, provider)
                   : (String.IsNullOrEmpty(defaultValue) ? String.Empty : defaultValue);
    }
}

використовуючи разом з названими параметрами, ви можете:

dt2.ToString (defaultValue: "n / a");

У старих версіях dotnet ви отримуєте багато перевантажень

/// <summary>
/// Extentionclass for a nullable structs
/// </summary>
public static class NullableStructExtensions {

    /// <summary>
    /// Formats a nullable struct
    /// </summary>
    /// <param name="source"></param>
    /// <param name="format">The format string 
    /// If <c>null</c> use the default format defined for the type of the IFormattable implementation.</param>
    /// <param name="provider">The format provider 
    /// If <c>null</c> the default provider is used</param>
    /// <param name="defaultValue">The string to show when the source is <c>null</c>. 
    /// If <c>null</c> an empty string is returned</param>
    /// <returns>The formatted string or the default value if the source is <c>null</c></returns>
    public static string ToString<T>(this T? source, string format, 
                                     IFormatProvider provider, string defaultValue) 
                                     where T : struct, IFormattable {
        return source.HasValue
                   ? source.Value.ToString(format, provider)
                   : (String.IsNullOrEmpty(defaultValue) ? String.Empty : defaultValue);
    }

    /// <summary>
    /// Formats a nullable struct
    /// </summary>
    /// <param name="source"></param>
    /// <param name="format">The format string 
    /// If <c>null</c> use the default format defined for the type of the IFormattable implementation.</param>
    /// <param name="defaultValue">The string to show when the source is null. If <c>null</c> an empty string is returned</param>
    /// <returns>The formatted string or the default value if the source is <c>null</c></returns>
    public static string ToString<T>(this T? source, string format, string defaultValue) 
                                     where T : struct, IFormattable {
        return ToString(source, format, null, defaultValue);
    }

    /// <summary>
    /// Formats a nullable struct
    /// </summary>
    /// <param name="source"></param>
    /// <param name="format">The format string 
    /// If <c>null</c> use the default format defined for the type of the IFormattable implementation.</param>
    /// <param name="provider">The format provider (if <c>null</c> the default provider is used)</param>
    /// <returns>The formatted string or an empty string if the source is <c>null</c></returns>
    public static string ToString<T>(this T? source, string format, IFormatProvider provider)
                                     where T : struct, IFormattable {
        return ToString(source, format, provider, null);
    }

    /// <summary>
    /// Formats a nullable struct or returns an empty string
    /// </summary>
    /// <param name="source"></param>
    /// <param name="format">The format string 
    /// If <c>null</c> use the default format defined for the type of the IFormattable implementation.</param>
    /// <returns>The formatted string or an empty string if the source is null</returns>
    public static string ToString<T>(this T? source, string format)
                                     where T : struct, IFormattable {
        return ToString(source, format, null, null);
    }

    /// <summary>
    /// Formats a nullable struct
    /// </summary>
    /// <param name="source"></param>
    /// <param name="provider">The format provider (if <c>null</c> the default provider is used)</param>
    /// <param name="defaultValue">The string to show when the source is <c>null</c>. If <c>null</c> an empty string is returned</param>
    /// <returns>The formatted string or the default value if the source is <c>null</c></returns>
    public static string ToString<T>(this T? source, IFormatProvider provider, string defaultValue)
                                     where T : struct, IFormattable {
        return ToString(source, null, provider, defaultValue);
    }

    /// <summary>
    /// Formats a nullable struct or returns an empty string
    /// </summary>
    /// <param name="source"></param>
    /// <param name="provider">The format provider (if <c>null</c> the default provider is used)</param>
    /// <returns>The formatted string or an empty string if the source is <c>null</c></returns>
    public static string ToString<T>(this T? source, IFormatProvider provider)
                                     where T : struct, IFormattable {
        return ToString(source, null, provider, null);
    }

    /// <summary>
    /// Formats a nullable struct or returns an empty string
    /// </summary>
    /// <param name="source"></param>
    /// <returns>The formatted string or an empty string if the source is <c>null</c></returns>
    public static string ToString<T>(this T? source) 
                                     where T : struct, IFormattable {
        return ToString(source, null, null, null);
    }
}

1

Мені подобається такий варіант:

Console.WriteLine(dt2?.ToString("yyyy-MM-dd hh:mm:ss") ?? "n/a");

0

Прості родові розширення

public static class Extensions
{

    /// <summary>
    /// Generic method for format nullable values
    /// </summary>
    /// <returns>Formated value or defaultValue</returns>
    public static string ToString<T>(this Nullable<T> nullable, string format, string defaultValue = null) where T : struct
    {
        if (nullable.HasValue)
        {
            return String.Format("{0:" + format + "}", nullable.Value);
        }

        return defaultValue;
    }
}

-2

Можливо, це пізня відповідь, але може допомогти будь-кому іншому.

Просто:

nullabledatevariable.Value.Date.ToString("d")

або просто використовувати будь-який формат, а не "d".

Найкраще


1
Це стане помилкою, коли nullabledatevariable.Value є нульовим.
Джон C

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.