【问题标题】:DateTime "null" value日期时间“空”值
【发布时间】:2010-09-18 07:34:01
【问题描述】:

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

【问题讨论】:

    标签: c# datetime null


    【解决方案1】:

    对于普通的 DateTimes,如果您根本不初始化它们,那么它们将匹配 DateTime.MinValue,因为它是值类型而不是引用类型。

    您还可以使用可为空的 DateTime,如下所示:

    DateTime? MyNullableDate;
    

    或更长的形式:

    Nullable<DateTime> MyNullableDate;
    

    最后,还有一种内置方式可以引用任何类型的默认值。对于引用类型,这将返回 null,但对于我们的 DateTime 示例,它将返回与 DateTime.MinValue 相同的值:

    default(DateTime)
    

    或者,在 C# 的更新版本中,

    default
    

    【讨论】:

    • 如果您提供一个如何使用它的示例,将会有很大帮助。如何将数据库中的 DateTime(可能是 DBNull)分配给可为空的 DateTime?
    • 还需要注意的是,当您初始化它们并使用 null 时,它们也会被分配 DateTime.MinValue
    • @kirk.burleson 这看起来像是一个单独的问题。
    • 你需要MyNullableDate=date; 来设置它,MyDate = MyNullableDate.Value; 来读取它,if(MyNullableDate.HasValue) 来检查它是否为空
    • 澄清一下答案的“终于”——Nullable (DateTime?) 的默认值为 null,因为 Nullable 创建了一个引用类型。
    【解决方案2】:

    我会考虑使用nullable types

    DateTime? myDate 而不是DateTime myDate

    【讨论】:

      【解决方案3】:

      如果您使用的是 .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

      【讨论】:

      • 即使在早期版本的 .NET 中也可以使用可为空的类型,不需要 3.0。
      • 它来自 .NET 2.0 对吗?这 ?语法是在 3.5 中添加到 VB.NET 中的,但我相信自 2.0 以来它一直在 C# 中。
      • Nullable 类型在 .Net 2.0 中可用。 C#有简写吗?从 2.0 开始的符号。只有VB.Net没有速记?在 2.0 中,但您可以使用 Nullable(Of DateTime)
      • 对于最后一个 sn-p,我会说 DateTime dt2 = dt ??日期时间.MinValue;
      • 我会使用dt.GetValueOrDefault()——这是最有效的选择。
      【解决方案4】:

      您可以使用可为空的类。

      DateTime? date = new DateTime?();
      

      【讨论】:

      • 可能值得注意的是,这将给您带来与实例化不可为空的DateTime 不同的行为。如前所述,new DateTime() 将有效地为您提供 DateTime.Minnew DateTime?() 将导致 null。
      【解决方案5】:

      您可以为此使用可为空的 DateTime。

      Nullable<DateTime> myDateTime;
      

      或者同样的写法:

      DateTime? myDateTime;
      

      【讨论】:

        【解决方案6】:

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

        【讨论】:

        • 这意味着你无法区分“我在这里真的需要一个 DateTime”和“它是可选的” - Nullable 是一个更好的解决方案,IMO。
        • ?我真的不明白你的评论。是的,我知道当 DateTime 离现实如此遥远时,就像它是空的一样......
        • 方便,但我将 DateTime.MinValue 视为一个值,而不是特殊情况。它只会导致问题发生。我会选择 Nullable
        • 我想你错过了我的回答,Spoulson 写了一些东西,我正在回答。关于公众成员,这不一样,你知道的。它就像 String.Empty 或 null。您可以两者都做,并不是因为 String.Empty 比 null 错误更好。什么。
        • 我支持 Daok。它可能不是“按书本”的方法,但它比获取 NullReferenceException 或处理繁琐的 Nullable 类型要好。此外,有多少应用程序实际上需要参考公元 1 月 1 日这一日期?
        【解决方案7】:

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

        DateTime? nullDate = null;
        

        DateTime? nullDate;
        

        【讨论】:

          【解决方案8】:

          日期时间?我的日期时间{get;set;}

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

          【讨论】:

          • 这帮助我发现仅仅通过null 是行不通的。必须是(DateTime?)null
          【解决方案9】:

          如果您有时期望为 null,则可以使用以下内容:

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

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

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

          【讨论】:

            【解决方案10】:

            值得指出的是,虽然DateTime 变量不能是null,但它仍然可以与null 进行比较而不会出现编译器错误:

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

            【讨论】:

              【解决方案11】:

              请注意 - 当使用 Nullable 时,它​​显然不再是“纯”日期时间对象,因此您无法直接访问 DateTime 成员。我会试着解释一下。

              通过使用 Nullable 您基本上将 DateTime 包装在一个可以为空的容器(感谢泛型)中 - 显然它的目的。这个容器有它自己的属性,你可以调用这些属性来访问前面提到的 DateTime 对象;使用正确的属性后(在本例中为 Nullable.Value),您就可以访问标准的 DateTime 成员、属性等。

              所以 - 现在想到了访问 DateTime 对象的最佳方式的问题。有几种方法,1 号是 FAR 最好的,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 的使用可能值得一提。如果您不同意,请见谅。

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

              【讨论】:

                【解决方案12】:

                虽然大家都已经给出了答案,但我还是提一下一种可以很容易地将日期时间传递给函数的方法

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

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

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

                【讨论】:

                  【解决方案13】:

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

                  • 如果您的变量没有值,请为其分配一个最小日期/时间值。您也可以指定最大日期/时间值 - 无论哪种方式适合您。在检查日期/时间值时,请确保您在整个站点范围内保持一致。决定使用minmax 并坚持下去。

                  • 将您的日期/时间变量标记为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# 程序员专家了 :)

                  【讨论】:

                    【解决方案14】:

                    以下方法也可以

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

                    请注意属性 PublishDate 应该是 DateTime?

                    【讨论】:

                      【解决方案15】:

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

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

                      【讨论】:

                        猜你喜欢
                        • 1970-01-01
                        • 2011-08-22
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        • 2022-12-09
                        • 1970-01-01
                        • 1970-01-01
                        相关资源
                        最近更新 更多