DateTime“空”值


273

我一直在搜索很多,但是找不到解决方案。您如何处理应该能够包含未初始化值(等于null)的DateTime?我有一个可能设置了DateTime属性值的类。我正在考虑将属性持有者初始化为DateTime.MinValue,然后可以轻松地对其进行检查。我想这是一个很常见的问题,您该怎么做?

Answers:


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?)的默认值为null,因为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/zh-cn/library/b3h38hb0.aspx


1
您甚至可以在.NET的早期版本中使用可为null的类型,而不需要3.0。
stephenbayer's

1
它来自.NET 2.0,对吗??语法是在3.5中添加到VB.NET中的,但我认为从2.0起它就已经在C#中使用。
David Mohundro

1
.Net 2.0中提供了可空类型。C#有速记吗?从2.0开始的符号。只有VB.Net没有速记吗?在2.0中,但您可以使用Nullable(Of DateTime)
Mendelt's

对于最后一个代码段,我会说DateTime dt2 = dt ?? DateTime.MinValue;
Joel Coehoorn

我会用dt.GetValueOrDefault()-这是最有效的选择。
CompuChip

37

约会时间?MyDateTime {get; set;}

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

1
这帮助我发现过关是null行不通的。它必须是(DateTime?)null
Inphinite分数

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?();

可能值得一提的是,与实例化non-nullable相比,这将为您提供不同的行为DateTime。如前所述,new DateTime()将有效地给您,DateTime.Minnew DateTime?()将导致null。
Vitoc


6

您可以将DateTime设置为Nullable。默认情况下,DateTime不可为空。您可以通过两种方法使它可为空。在类型DateTime之后使用问号?myTime或使用通用样式Nullable。

DateTime? nullDate = null;

要么

DateTime? nullDate;

5

我总是把时间定为DateTime.MinValue。这样,我不会收到任何NullErrorException异常,并且可以将其与我知道未设置的日期进行比较。


8
这意味着您无法分辨“我这里确实需要一个DateTime”和“它是可选的”之间的区别-IMO,Nullable <DateTime>是一个更好的解决方案。
乔恩·斯基特

?我真的没有收到您的评论。是的,我知道DateTime距离现实如此遥远,就好像它是否为空一样……
Patrick Desjardins,

2
这很方便,但是我将DateTime.MinValue视为一个值,而不是特殊情况。这只会导致问题。我会选择Nullable <DateTime>。
spoulson

3
我想您想念我的答案,Spoulson写了些东西,而我正在回答。关于公众成员,那是不一样的,你知道的。就像String.Empty或null。您可以两者都做,不是因为String.Empty最好使null是错误的。随你。
Patrick Desjardins,

1
我和Daok在一起。它可能不是“按书预定”的方法,但是它比获得NullReferenceException或处理笨重的Nullable类型要好。此外,实际上有多少申请需要参考公元1月1日这一日期?
Jacobs Data Solutions 2010年

4

请注意-使用Nullable时,它显然不再是“纯”日期时间对象,因此,您不能直接访问DateTime成员。我会尽力解释。

通过使用Nullable <>,您基本上是将DateTime包装在一个可以为空的容器中(感谢泛型),这显然是其目的。这个容器有自己的属性,您可以调用该属性来访问上述DateTime对象。使用正确的属性(在本例中为Nullable.Value)之后,您便可以访问标准的DateTime成员,属性等。

因此,现在就想到了访问DateTime对象的最佳方法的问题。有几种方法,第一是FAR最好的,第二是“花花公子为什么”。

  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的用法可能值得一提。抱歉,如果您不同意。

编辑:删除了第三个选项,因为它有点过分具体且取决于大小写。


2

尽管每个人都已经给了您答案,但我将介绍一种可以轻松将日期时间传递给函数的方法

[错误:无法转换system.datetime?到system.datetime]

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

现在,您可以在函数内部传递dte了,而不会出现任何问题。


1

如果有时会期望为null,则可以使用如下所示的内容:

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

在您的存储库中,使用可为空的日期时间。

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

1

我遇到了同样的问题,即在对Throws ArgumentNullException执行单元测试时必须将Null作为DateTime的参数。在我的情况下,使用以下选项可以正常工作:

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

0

给定日期/时间数据类型的性质,它不能包含null值,即它需要包含一个值,不能为空或不包含任何值。如果将日期/时间变量标记为,nullable则只能为其分配空值。因此,您想要做的是两件事之一(可能还有更多,但我只能想到两件事):

  • 如果您没有变量,请为其指定一个最小日期/时间值。您也可以指定最大日期/时间值-哪种方式都适合您。检查日期/时间值时,只需确保您在整个站点范围内保持一致即可。确定使用minor max并坚持使用。

  • 将您的日期/时间变量标记为nullable。这样,您可以将日期/时间变量设置为null无变量。

让我用一个例子说明我的第一点。该DateTime变量的类型不能设置为null,它需要一个值,在这种情况下,我将其设置为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#专家:)

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.