Bagaimana saya bisa memformat DateTime yang dapat dibatalkan dengan ToString ()?

226

Bagaimana saya bisa mengubah DateTime dt2 yang dapat dibatalkan menjadi string yang diformat?

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:

tidak ada kelebihan untuk metode ToString membutuhkan satu argumen

Edward Tanguay
sumber
3
Halo, maukah Anda meninjau jawaban yang diterima dan saat ini? Jawaban hari ini yang lebih relevan mungkin lebih benar.
iuliu.net

Jawaban:

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

EDIT: Seperti yang dinyatakan dalam komentar lain, periksa apakah ada nilai yang bukan nol.

Pembaruan: seperti yang direkomendasikan dalam komentar, metode ekstensi:

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

Dan mulai dari C # 6, Anda dapat menggunakan operator kondisional nol untuk menyederhanakan kode lebih. Ekspresi di bawah ini akan mengembalikan nol jika DateTime?nol.

dt2?.ToString("yyyy-MM-dd hh:mm:ss")
Blake Pettersson
sumber
26
Ini sepertinya meminta saya metode perpanjangan.
David Glenn
42
.Nilai adalah kuncinya
stuartdotnet
@ Bersihkan bukan bahwa tugasnya tidak sepele ... stackoverflow.com/a/44683673/5043056
Sinjai
3
Apakah Anda siap untuk ini ... dt? .ToString ("dd / MMM / yyyy") ?? "" Keuntungan luar biasa dari C # 6
Tom McDonough
Kesalahan CS0029: Tidak dapat secara implisit mengonversi tipe 'string' ke 'System.DateTime?' (CS0029). .Net Core 2.0
Oracular Man
80

Coba ini untuk ukuran:

Objek dateTime aktual yang ingin Anda format adalah di properti dt.Value, dan bukan pada objek dt2 itu sendiri.

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

Kalian semua lebih dari rekayasa ini dan membuatnya jauh lebih rumit daripada yang sebenarnya. Yang penting, berhenti menggunakan ToString dan mulai menggunakan pemformatan string seperti string. Kesesuaian atau metode yang mendukung pemformatan string seperti Console.WriteLine. Inilah solusi yang disukai untuk pertanyaan ini. Ini juga yang paling aman.

Memperbarui:

Saya memperbarui contoh dengan metode terkini dari kompiler C # hari ini. operator bersyarat & interpolasi string

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

Output: (Saya menempatkan tanda kutip tunggal di dalamnya sehingga Anda dapat melihat bahwa ia kembali sebagai string kosong ketika nol)

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

'2019-04-09 08:01:39'
''
John C
sumber
30

Seperti yang dinyatakan orang lain, Anda perlu memeriksa nol sebelum memohon ToString tetapi untuk menghindari pengulangan, Anda dapat membuat metode ekstensi yang melakukan itu, seperti:

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

}

Yang bisa dipanggil seperti:

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'
David Glenn
sumber
28

C # 6.0 bayi:

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

iuliu.net
sumber
2
Saya akan menyarankan versi berikut ini sehingga jawaban ini setara dengan jawaban yang diterima yang ada untuk C # 6.0. Console.WriteLine(dt2?.ToString("yyyy-MM-dd hh:mm:ss" ?? "n/a");
Can Bud
15

Masalah dengan merumuskan jawaban untuk pertanyaan ini adalah bahwa Anda tidak menentukan output yang diinginkan ketika datable nullable tidak memiliki nilai. Kode berikut akan menampilkan DateTime.MinValuedalam kasus seperti itu, dan tidak seperti jawaban yang saat ini diterima, tidak akan memberikan pengecualian.

dt2.GetValueOrDefault().ToString(format);
Matt Howells
sumber
7

Melihat bahwa Anda benar-benar ingin memberikan format saya sarankan untuk menambahkan antarmuka IFormattable ke metode ekstensi Smalls seperti itu, sehingga Anda tidak memiliki penggabungan format string yang buruk.

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   
}
ElmarG
sumber
6

Bagaimana dengan sesuatu yang semudah ini:

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

Anda dapat menggunakan dt2.Value.ToString("format"), tetapi tentu saja itu mengharuskan dt2! = Null, dan itu meniadakan penggunaan tipe nullable di tempat pertama.

Ada beberapa solusi di sini, tetapi pertanyaan besarnya adalah: Bagaimana Anda ingin memformat nulltanggal?

Henk Holterman
sumber
5

Ini pendekatan yang lebih umum. Ini akan memungkinkan Anda untuk memformat tipe nilai nullable apa pun. Saya telah memasukkan metode kedua untuk memungkinkan mengganti nilai string default alih-alih menggunakan nilai default untuk tipe nilai.

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;
    }
}
Schmalls
sumber
4

Jawaban tersingkat

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

Tes

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: 
drobertson
sumber
4

Bahkan solusi yang lebih baik di C # 6.0:

DateTime? birthdate;

birthdate?.ToString("dd/MM/yyyy");
Mohammed Noureldin
sumber
4

Sintaks RAZOR:

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

Saya pikir Anda harus menggunakan GetValueOrDefault-Methode. Perilaku dengan ToString ("yy ...") tidak ditentukan jika turunannya null.

dt2.GetValueOrDefault().ToString("yyy...");
martin
sumber
1
Perilaku dengan ToString ( "yy ...") adalah didefinisikan jika contoh adalah null, karena GetValueOrDefault () akan kembali DateTime.MinValue
Lucas
2

Ini jawaban Blake yang luar biasa sebagai metode ekstensi. Tambahkan ini ke proyek Anda dan panggilan dalam pertanyaan akan berfungsi seperti yang diharapkan.
Artinya digunakan seperti MyNullableDateTime.ToString("dd/MM/yyyy"), dengan output yang sama dengan MyDateTime.ToString("dd/MM/yyyy"), kecuali bahwa nilainya akan menjadi "N/A"jika DateTime adalah nol.

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

IFormattable juga menyertakan penyedia format yang dapat digunakan, memungkinkan kedua format IFormatProvider menjadi nol di 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);
    }
}

menggunakan bersama dengan parameter bernama yang dapat Anda lakukan:

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

Dalam versi dotnet yang lama, Anda mendapatkan banyak kelebihan

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

Saya suka opsi ini:

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

Ekstensi generik sederhana

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;
    }
}
Andzej Maciusovic
sumber
-2

Mungkin itu adalah jawaban yang terlambat tetapi dapat membantu orang lain.

Sederhana adalah:

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

atau cukup gunakan format apa saja daripada "d".

Terbaik

Waleed
sumber
1
Ini akan kesalahan ketika nullabledatevariable.Value adalah nol.
John C
-2

Anda dapat menggunakan garis sederhana:

dt2.ToString("d MMM yyyy") ?? ""
Daniel Heo
sumber