Nilai DateTime "null"


273

Saya sudah banyak mencari tetapi tidak dapat menemukan solusi. Bagaimana Anda menangani DateTime yang seharusnya dapat mengandung nilai yang tidak diinisialisasi (setara dengan nol)? Saya memiliki kelas yang mungkin memiliki nilai properti DateTime yang ditetapkan atau tidak. Saya berpikir untuk menginisialisasi pemegang properti menjadi DateTime.MinValue, yang kemudian dapat dengan mudah diperiksa. Saya kira ini adalah pertanyaan yang cukup umum, bagaimana Anda melakukannya?

Jawaban:


420

Untuk DateTimes normal, jika Anda tidak menginisialisasi sama sekali maka mereka akan cocok DateTime.MinValue, karena ini adalah tipe nilai daripada tipe referensi.

Anda juga dapat menggunakan DateTime yang dapat dibatalkan, seperti ini:

DateTime? MyNullableDate;

Atau bentuk yang lebih panjang:

Nullable<DateTime> MyNullableDate;

Dan, akhirnya, ada cara yang dibangun untuk referensi default jenis apa pun. Ini mengembalikan nulluntuk jenis referensi, tetapi untuk contoh DateTime kami akan kembali sama dengan DateTime.MinValue:

default(DateTime)

atau, dalam versi C # yang lebih baru,

default

8
Akan sangat membantu jika Anda memberikan contoh cara menggunakannya. Bagaimana Anda menetapkan DateTime dalam database, yang bisa menjadi DBNull, ke DateTime yang dapat dibatalkan?
kirk.burleson

9
Ini juga baik untuk dicatat bahwa ketika Anda menginisialisasi mereka dan dengan nol, mereka ditugaskan DateTime.MinValuejuga
Jeff LaFay

2
@ kirk.burleson yang terlihat seperti pertanyaan terpisah.
CompuChip

Anda harus MyNullableDate=date; mengaturnya, MyDate = MyNullableDate.Value;untuk membacanya, dan if(MyNullableDate.HasValue)untuk memeriksa apakah itu nol
satibel

Untuk memperjelas jawaban "akhirnya" sedikit - default Nullable <DateTime> (DateTime?) Adalah nol, karena Nullable <T> menciptakan tipe referensi.
ryanwebjackson

88

Jika Anda menggunakan .NET 2.0 (atau lebih baru), Anda dapat menggunakan jenis nullable:

DateTime? dt = null;

atau

Nullable<DateTime> dt = null;

lalu nanti:

dt = new DateTime();

Dan Anda dapat memeriksa nilainya dengan:

if (dt.HasValue)
{
  // Do something with dt.Value
}

Atau Anda dapat menggunakannya seperti:

DateTime dt2 = dt ?? DateTime.MinValue;

Anda dapat membaca lebih lanjut di sini:
http://msdn.microsoft.com/en-us/library/b3h38hb0.aspx


1
Anda dapat menggunakan tipe yang dapat dibatalkan bahkan dalam versi .NET yang lebih lama, tidak perlu untuk 3.0.
stephenbayer

1
Itu datang. NET 2.0 kan? Itu? sintaks telah ditambahkan ke VB.NET di 3.5, tetapi sudah di C # sejak 2.0 saya percaya.
David Mohundro

1
Jenis Nullable tersedia di .Net 2.0. C # punya steno? notasi dari 2.0. Hanya VB.Net yang tidak memiliki tulisan cepat? di 2.0 tetapi Anda bisa menggunakan Nullable (Of DateTime)
Mendelt

Untuk cuplikan terakhir, saya akan mengatakan DateTime dt2 = dt ?? DateTime.MinValue;
Joel Coehoorn

Saya akan menggunakan dt.GetValueOrDefault()- ini adalah opsi yang paling efisien.
CompuChip

37

Tanggal Waktu? MyDateTime {get; set;}

MyDateTime = (dr["f1"] == DBNull.Value) ? (DateTime?)null : ((DateTime)dr["f1"]);

1
Ini membantu saya menemukan kematian nulltidak berhasil. Itu perlu (DateTime?)null.
Inphinite Phractals

33

Cara mengikuti juga berfungsi

myClass.PublishDate = toPublish ? DateTime.Now : (DateTime?)null;

Harap perhatikan bahwa properti PublishDate harus DateTime?



8

Perlu ditunjukkan bahwa, sementara DateTimevariabel tidak bisa null, itu masih dapat dibandingkan dengan nulltanpa kesalahan kompiler:

DateTime date;
...
if(date == null) // <-- will never be 'true'
  ...

6

Anda bisa menggunakan kelas nullable.

DateTime? date = new DateTime?();

Mungkin patut dicatat bahwa ini akan memberi Anda perilaku yang berbeda dari membuat yang tidak dapat dibatalkan DateTime. Seperti yang disebutkan sebelumnya, new DateTime()akan secara efektif memberi Anda DateTime.Minsedangkan new DateTime?()akan menghasilkan nol.
Vitoc

6

Anda dapat menggunakan DateTime yang dapat dibatalkan untuk ini.

Nullable<DateTime> myDateTime;

atau hal yang sama tertulis seperti ini:

DateTime? myDateTime;

6

Anda dapat mengatur DateTime ke Nullable. Secara default DateTime tidak dapat dibatalkan. Anda dapat membuatnya nullable dalam beberapa cara. Menggunakan tanda tanya setelah jenis DateTime? myTime atau menggunakan gaya generik Nullable.

DateTime? nullDate = null;

atau

DateTime? nullDate;

5

Saya selalu mengatur waktu untuk DateTime.MinValue. Dengan cara ini saya tidak mendapatkan NullErrorException dan saya bisa membandingkannya dengan tanggal yang saya tahu tidak disetel.


8
Itu berarti Anda tidak dapat membedakan antara "Saya benar-benar membutuhkan DateTime di sini" dan "Ini opsional" - Nullable <DateTime> adalah solusi yang jauh lebih baik, IMO.
Jon Skeet

? Saya benar-benar tidak mendapatkan komentar Anda. Ya saya tahu ketika DateTime jauh dari kenyataan adalah seperti jika itu nol ...
Patrick Desjardins

2
Memang nyaman, tapi saya melihat DateTime.MinValue sebagai nilai, bukan kondisi kasus khusus. Itu hanya dapat menyebabkan masalah di telepon. Saya akan menggunakan Nullable <DateTime>.
spoulson

3
Saya pikir Anda melewatkan sesuatu tentang jawaban saya, Spoulson menulis sesuatu dan saya menjawab. Tentang anggota publik, baik itu tidak sama dan Anda tahu itu. itu seperti String.Empty atau null. Anda dapat melakukan keduanya, bukan karena String.Empty lebih baik dari nol yang salah. Masa bodo.
Patrick Desjardins

1
Saya dengan Daok dalam hal ini. Ini mungkin bukan pendekatan "oleh buku" tetapi lebih baik daripada mendapatkan NullReferenceException atau berurusan dengan tipe Nullable yang rumit. Selain itu, berapa banyak aplikasi di luar sana yang sebenarnya perlu referensi tanggal 1 Januari 1 M?
Jacobs Data Solutions

4

Hanya diperingatkan - Saat menggunakan Nullable itu jelas tidak lagi objek datetime 'murni', karena itu Anda tidak dapat mengakses anggota DateTime secara langsung. Saya akan coba jelaskan.

Dengan menggunakan Nullable <> Anda pada dasarnya membungkus DateTime dalam sebuah wadah (terima kasih obat generik) yang dapat dibatalkan - jelas tujuannya. Wadah ini memiliki properti sendiri yang dapat Anda panggil yang akan memberikan akses ke objek DateTime yang disebutkan di atas; setelah menggunakan properti yang benar - dalam hal ini Nullable.Value - Anda kemudian memiliki akses ke anggota DateTime standar, properti, dll.

Jadi - sekarang masalah muncul di pikiran tentang cara terbaik untuk mengakses objek DateTime. Ada beberapa cara, nomor 1 adalah JAUH yang terbaik dan 2 adalah "Bung mengapa".

  1. Menggunakan properti Nullable.Value,

    DateTime date = myNullableObject.Value.ToUniversalTime(); //Works

    DateTime date = myNullableObject.ToUniversalTime(); //Not a datetime object, fails

  2. Mengonversi objek yang dapat dibatalkan ke datetime menggunakan Convert.ToDateTime (),

    DateTime date = Convert.ToDateTime(myNullableObject).ToUniversalTime(); //works but why...

Meskipun jawabannya didokumentasikan dengan baik pada saat ini, saya percaya penggunaan Nullable mungkin layak untuk dikirim. Maaf jika Anda tidak setuju.

sunting: Menghapus opsi ketiga karena agak terlalu spesifik dan tergantung kasus.


2

Meskipun semua orang telah memberi Anda jawabannya, saya akan menyebutkan cara yang membuatnya mudah untuk melewatkan waktu ke fungsi

[KESALAHAN: tidak bisa mengonversi system.datetime? ke system.datetime]

DateTime? dt = null;
DateTime dte = Convert.ToDateTime(dt);

Sekarang Anda dapat melewati dte di dalam fungsi tanpa masalah.


1

Jika Anda, kadang-kadang, mengharapkan null Anda dapat menggunakan sesuatu seperti ini:

var orderResults = Repository.GetOrders(id, (DateTime?)model.DateFrom, (DateTime?)model.DateTo)

Dalam repositori Anda, gunakan datetime yang tidak dapat digunakan.

public Orders[] GetOrders(string id, DateTime? dateFrom, DateTime? dateTo){...}

1

Saya memiliki masalah yang sama seperti saya harus memberikan Null sebagai parameter untuk DateTime saat melakukan tes Unit untuk Melempar ArgumentNullException. Ini bekerja dalam kasus saya menggunakan opsi berikut:

Assert.Throws<ArgumentNullException>(()=>sut.StartingDate = DateTime.Parse(null));

0

Mengingat sifat tipe data tanggal / waktu itu tidak dapat berisi nullnilai, yaitu perlu mengandung nilai, itu tidak boleh kosong atau tidak mengandung apa pun. Jika Anda menandai variabel tanggal / waktu nullablemaka Anda hanya dapat menetapkan nilai nol untuknya. Jadi yang ingin Anda lakukan adalah salah satu dari dua hal (mungkin ada lebih banyak tetapi saya hanya bisa memikirkan dua):

  • Tetapkan nilai tanggal / waktu minimum untuk variabel Anda jika Anda tidak memiliki nilai untuk itu. Anda dapat menetapkan nilai tanggal / waktu maksimum juga - mana yang cocok untuk Anda. Pastikan bahwa Anda konsisten di seluruh situs saat memeriksa nilai tanggal / waktu Anda. Putuskan untuk menggunakan minatau maxdan tetap menggunakannya.

  • Tandai variabel tanggal / waktu Anda sebagai nullable. Dengan cara ini Anda dapat mengatur variabel tanggal / waktu nullAnda jika Anda tidak memiliki variabel untuk itu.

Biarkan saya menunjukkan poin pertama saya menggunakan contoh. The DateTimejenis variabel tidak dapat diatur untuk null, perlu nilai, dalam hal ini saya akan set ke DateTime's nilai minimum jika tidak ada nilai.

Skenario saya adalah saya memiliki BlogPostkelas. Ini memiliki banyak bidang / properti yang berbeda tetapi saya memilih hanya menggunakan dua untuk contoh ini. DatePublishedadalah ketika posting dipublikasikan ke situs web dan harus mengandung nilai tanggal / waktu. DateModifiedadalah ketika sebuah posting diubah, sehingga tidak harus mengandung nilai, tetapi dapat mengandung nilai.

public class BlogPost : Entity
{
     public DateTime DateModified { get; set; }

     public DateTime DatePublished { get; set; }
}

Menggunakan ADO.NETuntuk mendapatkan data dari database (menetapkan DateTime.MinValueapakah tidak ada nilai):

BlogPost blogPost = new BlogPost();
blogPost.DateModified = sqlDataReader.IsDBNull(0) ? DateTime.MinValue : sqlDataReader.GetFieldValue<DateTime>(0);
blogPost.DatePublished = sqlDataReader.GetFieldValue<DateTime>(1);

Anda dapat mencapai poin kedua saya dengan menandai DateModifiedbidang sebagai nullable. Sekarang Anda dapat mengaturnya nulljika tidak ada nilai untuk itu:

public DateTime? DateModified { get; set; }

Menggunakan ADO.NETuntuk mendapatkan data dari database, itu akan terlihat sedikit berbeda dengan cara itu dilakukan di atas ( nullbukan penugasan DateTime.MinValue):

BlogPost blogPost = new BlogPost();
blogPost.DateModified = sqlDataReader.IsDBNull(0) ? (DateTime?)null : sqlDataReader.GetFieldValue<DateTime>(0);
blogPost.DatePublished = sqlDataReader.GetFieldValue<DateTime>(1);

Saya harap ini membantu menjernihkan kebingungan. Mengingat bahwa tanggapan saya sekitar 8 tahun kemudian, Anda mungkin seorang programmer C # yang ahli sekarang :)

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.