Làm cách nào tôi có thể định dạng một DateTime nullable với ToString ()?


226

Làm cách nào tôi có thể chuyển đổi DateTime dt2 nullable thành một chuỗi được định dạng?

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:

không quá tải cho phương thức ToString mất một đối số


3
Xin chào, bạn có phiền khi xem lại các câu trả lời được chấp nhận và hiện tại không? Một câu trả lời phù hợp hơn trong ngày có thể đúng hơn.
iuliu.net

Câu trả lời:


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

EDIT: Như đã nêu trong các bình luận khác, hãy kiểm tra xem có giá trị khác không.

Cập nhật: như được đề xuất trong các ý kiến, phương pháp mở rộng:

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

Và bắt đầu từ C # 6, bạn có thể sử dụng toán tử có điều kiện null để đơn giản hóa mã hơn nữa. Biểu thức dưới đây sẽ trả về null nếu DateTime?là null.

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

26
Điều này có vẻ như nó đang cầu xin một phương pháp mở rộng cho tôi.
David Glenn

42
.Value là chìa khóa
stuartdotnet

@David không phải là nhiệm vụ không tầm thường ... stackoverflow.com/a/44683673/5043056
Sinjai

3
Bạn đã sẵn sàng cho điều này ... dt? .ToString ("dd / MMM / yyyy") ?? "" Những lợi thế tuyệt vời của C # 6
Tom McDonough

Lỗi CS0029: Không thể chuyển đổi hoàn toàn loại 'chuỗi' thành 'System.DateTime?' (CS0029). .Net Core 2.0
Người đàn ông ngoạn mục

80

Hãy thử điều này cho kích thước:

Đối tượng dateTime thực tế mà bạn muốn định dạng nằm trong thuộc tính dt.Value chứ không phải trên chính đối tượng dt2.

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

36

Các bạn đã quá kỹ thuật này và làm cho nó phức tạp hơn thực tế. Điều quan trọng, hãy ngừng sử dụng ToString và bắt đầu sử dụng định dạng chuỗi như chuỗi.Format hoặc các phương thức hỗ trợ định dạng chuỗi như Console.WriteLine. Đây là giải pháp ưa thích cho câu hỏi này. Đây cũng là an toàn nhất.

Cập nhật:

Tôi cập nhật các ví dụ với các phương pháp cập nhật của trình biên dịch C # ngày nay. toán tử điều kiện & nội suy chuỗi

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}'");

Đầu ra: (Tôi đặt các trích dẫn đơn trong đó để bạn có thể thấy rằng nó trở lại dưới dạng một chuỗi trống khi null)

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

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

30

Như những người khác đã tuyên bố, bạn cần kiểm tra null trước khi gọi ToString nhưng để tránh lặp lại chính mình, bạn có thể tạo một phương thức mở rộng thực hiện điều đó, đại loại như:

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);
  }

}

Mà có thể được gọi như:

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

Em bé C # 6.0:

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


2
Tôi sẽ đề xuất phiên bản sau để câu trả lời này tương đương với câu trả lời được chấp nhận hiện có cho C # 6.0. Console.WriteLine(dt2?.ToString("yyyy-MM-dd hh:mm:ss" ?? "n/a");
Có thể Bud

15

Vấn đề với việc đưa ra câu trả lời cho câu hỏi này là bạn không chỉ định đầu ra mong muốn khi datetime nullable không có giá trị. Đoạn mã sau sẽ xuất ra DateTime.MinValuetrong trường hợp như vậy và không giống như câu trả lời hiện được chấp nhận, sẽ không đưa ra một ngoại lệ.

dt2.GetValueOrDefault().ToString(format);

7

Thấy rằng bạn thực sự muốn cung cấp định dạng mà tôi đề xuất để thêm giao diện IFormattable vào phương thức tiện ích mở rộng Smalls như vậy, theo cách đó bạn không có cách nối định dạng chuỗi khó chịu.

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

Bạn có thể sử dụng dt2.Value.ToString("format"), nhưng tất nhiên điều đó đòi hỏi dt2! = Null và điều đó phủ nhận việc sử dụng loại nullable ở vị trí đầu tiên.

Có một số giải pháp ở đây, nhưng câu hỏi lớn là: Bạn muốn định dạng một nullngày như thế nào?


5

Đây là một cách tiếp cận chung hơn. Điều này sẽ cho phép bạn định dạng chuỗi bất kỳ loại giá trị nullable. Tôi đã bao gồm phương thức thứ hai để cho phép ghi đè giá trị chuỗi mặc định thay vì sử dụng giá trị mặc định cho loại giá trị.

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

Câu trả lời ngắn nhất

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

Xét nghiệm

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

Thậm chí là một giải pháp tốt hơn trong C # 6.0:

DateTime? birthdate;

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

4

Cú pháp RAZOR:

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

2

Tôi nghĩ rằng bạn phải sử dụng GetValueOrDefault-Methode. Hành vi với ToString ("yy ...") không được xác định nếu thể hiện là null.

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

1
Hành vi với ToString ("yy ...") được xác định nếu trường hợp là null, vì GetValueOrDefault () sẽ trả về DateTime.MinValue
Lucas

2

Đây là câu trả lời tuyệt vời của Blake như một phương pháp mở rộng. Thêm điều này vào dự án của bạn và các cuộc gọi trong câu hỏi sẽ hoạt động như mong đợi.
Có nghĩa là nó được sử dụng như thế MyNullableDateTime.ToString("dd/MM/yyyy"), với cùng một đầu ra MyDateTime.ToString("dd/MM/yyyy"), ngoại trừ giá trị đó sẽ là "N/A"nếu DateTime là null.

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

1

IFormattable cũng bao gồm một nhà cung cấp định dạng có thể được sử dụng, nó cho phép cả định dạng của IFormatProvider đều rỗng trong dotnet 4.0, điều này sẽ là

/// <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);
    }
}

sử dụng cùng với các tham số được đặt tên bạn có thể làm:

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

Trong các phiên bản cũ hơn của dotnet, bạn sẽ nhận được rất nhiều quá tải

/// <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

Tôi thích tùy chọn này:

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

0

Tiện ích mở rộng chung đơn giản

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

Có thể đó là một câu trả lời muộn nhưng có thể giúp đỡ bất cứ ai khác.

Đơn giản là:

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

hoặc chỉ sử dụng bất kỳ định dạng nào thay vì "d".

Tốt


1
Điều này sẽ báo lỗi khi nullablesatevariable.Value là null.
John C

-2

bạn có thể sử dụng dòng đơn giản:

dt2.ToString("d MMM yyyy") ?? ""
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.