Значення "null" DateTime


273

Я багато шукав, але не зміг знайти рішення. Як ви маєте справу з DateTime, який повинен містити неініціалізовані значення (еквівалентні нулю)? У мене є клас, який може мати значення властивості DateTime чи ні. Я думав ініціалізувати власника власності на DateTime.MinValue, який потім можна було легко перевірити. Я думаю, це досить поширене питання, як це зробити?

Відповіді:


420

Для звичайних DateTimes, якщо ви їх взагалі не ініціалізуєте, вони відповідатимуть DateTime.MinValue, оскільки це тип значення, а не тип посилання.

Ви також можете використовувати зведений DateTime, наприклад:

DateTime? MyNullableDate;

Або довша форма:

Nullable<DateTime> MyNullableDate;

І, нарешті, є вбудований спосіб посилатися на типовий стандарт будь-якого типу. Це повертається nullдля референтних типів, але для нашого прикладу DateTime воно буде таким же, як DateTime.MinValue:

default(DateTime)

або, в останніх версіях C #,

default

8
Це дуже допоможе, якщо ви подасте приклад того, як ним користуватися. Як призначити DateTime у базі даних, яка могла б бути DBNull, для зведеного DateTime?
kirk.burleson

9
Це також добре , щоб відзначити , що , коли ви робите їх ініціалізації і з нулем, вони призначені , DateTime.MinValueа також
Джефф Lafay

2
@ kirk.burleson, це виглядає як окреме запитання.
CompuChip

вам потрібно MyNullableDate=date; буде встановити його, MyDate = MyNullableDate.Value;прочитати з нього та if(MyNullableDate.HasValue)перевірити, чи він недійсний
satibel

Щоб трохи уточнити відповідь "нарешті" - за замовчуванням Nullable <DateTime> (DateTime?) Є нульовим, оскільки Nullable <T> створює тип посилання.
ryanwebjackson

88

Якщо ви використовуєте .NET 2.0 (або новішу версію), ви можете використовувати тип нульового:

DateTime? dt = null;

або

Nullable<DateTime> dt = null;

потім пізніше:

dt = new DateTime();

І ви можете перевірити значення за допомогою:

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

Або ви можете використовувати його так:

DateTime dt2 = dt ?? DateTime.MinValue;

Більше ви можете прочитати тут:
http://msdn.microsoft.com/en-us/library/b3h38hb0.aspx


1
Ви можете використовувати зведені типи навіть у попередніх версіях .NET, не потрібно 3.0.
stephenbayer

1
Він увійшов до .NET 2.0, правда? ? Синтаксис був доданий до VB.NET в 3.5, але він є в C # з 2.0 я вважаю.
Девід Мохундро

1
Зменшувані типи доступні в .Net 2.0. C # має стенографію? позначення від 2.0. Тільки VB.Net не мав стенограми? в 2.0, але ви можете використовувати Nullable (Of DateTime)
Mendelt

Для останнього фрагмента я б сказав DateTime dt2 = dt ?? DateTime.MinValue;
Джоел Куехорн

Я б використав dt.GetValueOrDefault()- це найефективніший варіант.
CompuChip

37

Дата, час? MyDateTime {get; set;}

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

1
Це допомогло мені виявити проходження просто nullне працює. Це має бути (DateTime?)null.
Інфініті Фрактали

33

Наступний спосіб працює також

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

Зверніть увагу, що власність PublishDate має бути DateTime?



8

Варто зазначити, що, хоча DateTimeзмінної не може бути null, її все ж можна порівняти nullбез помилки компілятора:

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

6

Ви можете використовувати нульовий клас.

DateTime? date = new DateTime?();

Напевно, варто зауважити, що це призведе до іншої поведінки, ніж інстанціювання ненульового DateTime. Як згадувалося раніше, new DateTime()це ефективно дасть вам, DateTime.Minтоді як new DateTime?()приведе до нуля.
Vitoc

6

Ви можете використовувати для цього нульовий DateTime.

Nullable<DateTime> myDateTime;

або те саме, що написано так:

DateTime? myDateTime;

6

Ви можете встановити DateTime на Nullable. За замовчуванням DateTime не зводиться до нуля. Ви можете звести його нанівець двома способами. Використовуєте знак питання після типу DateTime? myTime або використовуючи загальний стиль Nullable.

DateTime? nullDate = null;

або

DateTime? nullDate;

5

Я завжди встановлюю час на це DateTime.MinValue. Таким чином я не отримую NullErrorException і можу порівняти його з датою, яку я знаю, що не встановлено.


8
Це означає, що ви не можете сказати різницю між "мені дійсно потрібен DateTime тут" і "Це необов'язково" - Nullable <DateTime> - набагато краще рішення, IMO.
Джон Скіт

? Я дійсно не отримую вашого коментаря. Так, я знаю, коли DateTime настільки далекий від реальності, як якщо б він був нульовим ...
Патрік Дежардінс

2
Це зручно, але я розглядаю DateTime.MinValue як значення, а не особливу умову. Це може призвести лише до проблем вниз. Я б пішов з Nullable <DateTime>.
подружжя

3
Я думаю, ти щось пропустив у моїй відповіді, Спаульсон щось написав, а я відповідав. Щодо громадських членів, ну це не те саме, і ви це знаєте. це як String.Empty або null. Ви можете робити і те, і інше, тому що String.Empty краще, щоб null був неправильним. Що ніколи.
Патрік Дежардінс

1
Я з Даоком на цьому. Це може бути не підходом "від книги", але це краще, ніж отримати NullReferenceException або мати справу з громіздким типом Nullable. Окрім того, скільки там додатків, яким насправді потрібно вказати дату 1 січня 1 року нашої ери?
Рішення компанії Jacobs Data Solutions

4

Зауважте лише, що при використанні Nullable його, очевидно, більше не є "чистим" об'єктом дати, тому що ви не можете отримати доступ безпосередньо до членів DateTime безпосередньо. Я спробую пояснити.

Використовуючи Nullable <> ви в основному загортаєте DateTime у контейнер (дякую дженерики), який є нульовим - очевидно, його призначення. Цей контейнер має власні властивості, до яких можна зателефонувати, що забезпечить доступ до вищезазначеного об'єкта DateTime; після використання правильної властивості - у цьому випадку Nullable.Value - ви отримаєте доступ до стандартних членів DateTime, властивостей тощо.

Отже - зараз на думку приходить питання про найкращий спосіб отримати доступ до об’єкта DateTime. Є декілька способів, число 1 - найкраще, а 2 - "чувак чому".

  1. Використовуючи властивість Nullable.Value,

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

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

  2. Перетворення об'єкта, що зводиться на облік, у дату часу за допомогою Convert.ToDateTime (),

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

Хоча ця відповідь добре задокументована на даний момент, я вважаю, що використання Nullable, ймовірно, варто було опублікувати. Вибачте, якщо ви не згодні.

edit: Видалено третій варіант, оскільки він був трохи надто конкретним та залежним від регістра.


2

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

[ПОМИЛКА: не вдається конвертувати system.datetime? до system.datetime]

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

Тепер ви можете пропустити dte всередині функції без проблем.


1

Якщо ви іноді очікуєте, що це недійсне, ви можете використовувати щось подібне:

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

У вашому сховищі використовуйте нульовий час дати.

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

1

У мене була така ж проблема, як мені довелося надати Null як параметр DateTime під час виконання тесту одиниці для Throw ArgumentNullException. У моєму випадку вона працювала за допомогою наступної опції:

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

0

Враховуючи характер типу даних про дату / час, він не може містити nullзначення, тобто він повинен містити значення, він не може бути порожнім або нічого не містити. Якщо ви позначаєте змінну дати / часу як nullableтоді, ви можете лише призначити нульове значення. Тож те, що ти шукаєш, - це одна з двох речей (їх може бути більше, але я можу думати лише про дві):

  • Призначте мінімальну величину дати / часу для вашої змінної, якщо у вас немає для неї значення. Ви також можете призначити максимальне значення дати / часу - залежно від способу. Просто переконайтеся, що ви відповідаєте загально на сайті під час перевірки значень дати / часу. Вирішіть із використання minабо maxдотримуйтесь його.

  • Позначте змінну дати / часу як nullable. Таким чином ви можете встановити змінну дати / часу, nullякщо у вас немає змінної.

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

Мій сценарій полягає в тому, що у мене є BlogPostклас. У ньому багато різних полів / властивостей, але для цього прикладу я вибрав лише два. DatePublishedце коли публікація була опублікована на веб-сайті та має містити значення дати / часу. DateModifiedце коли публікація змінена, тому вона не повинна містити значення, але може містити значення.

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

     public DateTime DatePublished { get; set; }
}

Використання ADO.NETдля отримання даних з бази даних (призначити DateTime.MinValueнемає значення):

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

Ви можете досягти мого другого пункту, позначивши DateModifiedполе як nullable. Тепер ви можете встановити його, nullякщо для нього немає значення:

public DateTime? DateModified { get; set; }

Використовуючи ADO.NETдля отримання даних з бази даних, це буде виглядати трохи інакше, як це було зроблено вище (призначення nullзамість DateTime.MinValue):

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

Я сподіваюся, що це допоможе усунути будь-яку плутанину. Зважаючи на те, що моя відповідь приблизно через 8 років, ви, напевно, зараз експерт на програмі C # :)

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