Как я могу отформатировать обнуляемый DateTime с ToString ()? - PullRequest
203 голосов
/ 02 декабря 2009

Как я могу преобразовать обнуляемый 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 один аргумент

Ответы [ 20 ]

292 голосов
/ 02 декабря 2009
Console.WriteLine(dt2 != null ? dt2.Value.ToString("yyyy-MM-dd hh:mm:ss") : "n/a"); 

РЕДАКТИРОВАТЬ: Как указано в других комментариях, проверьте, что есть ненулевое значение.

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

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

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

dt2?.ToString("yyyy-MM-dd hh:mm:ss")
78 голосов
/ 02 декабря 2009

Примерьте размер:

Фактический объект dateTime, который вы хотите отформатировать, находится в свойстве dt.Value, а не в самом объекте dt2.

DateTime? dt2 = DateTime.Now;
 Console.WriteLine(dt2.HasValue ? dt2.Value.ToString("yyyy-MM-dd hh:mm:ss") : "[N/A]");
32 голосов
/ 22 января 2014

Вы, ребята, перестали проектировать все это и усложняли его, чем на самом деле. Важная вещь, прекратите использовать 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}'");

Вывод: (я поместил в него одинарные кавычки, чтобы вы могли видеть, что он возвращается как пустая строка, когда ноль)

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

'2019-04-09 08:01:39'
''
30 голосов
/ 02 декабря 2009

Как уже говорили другие, перед вызовом ToString вам нужно проверить на null, но чтобы избежать повторения, вы можете создать метод расширения, который делает это, например:

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'
24 голосов
/ 29 января 2016

C # 6.0 ребенок:

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

14 голосов
/ 02 декабря 2009

Проблема с формулировкой ответа на этот вопрос заключается в том, что вы не указываете желаемый результат, когда обнуляемая дата и время не имеют значения. Следующий код выведет DateTime.MinValue в таком случае и, в отличие от принятого в настоящее время ответа, не выдаст исключение.

dt2.GetValueOrDefault().ToString(format);
7 голосов
/ 31 августа 2011

Видя, что вы действительно хотите предоставить формат, я бы предложил добавить интерфейс 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 голосов
/ 02 декабря 2009

Вы можете использовать dt2.Value.ToString("format"), но, конечно, для этого требуется, чтобы dt2! = Null, и это в первую очередь сводит на нет использование nullable-типа.

Здесь есть несколько решений, но главный вопрос: как вы хотите отформатировать null дату?

5 голосов
/ 26 мая 2010

Вот более общий подход. Это позволит вам отформатировать любой тип значения, допускающий значение NULL. Я включил второй метод, позволяющий переопределить строковое значение по умолчанию вместо использования значения по умолчанию для типа значения.

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;
    }
}
5 голосов
/ 09 июня 2017

Как насчет чего-то такого простого:

String.Format("{0:dd/MM/yyyy}", d2)
...