仅在C#中的日期类型 - 为什么没有日期类型?

Car*_*ngo 95 c# datetime date

在我们的C#项目中,我们需要在没有时间的情况下表示日期.我知道DateTime的存在,但它也包含了一天中的时间.我想明确指出某些变量和方法参数是基于日期的.因此我不能使用该DateTime.Date属性

解决这个问题的标准方法是什么?当然,我不是第一个遇到这个?为什么DateC#中没有课?

有没有人有一个很好的实现使用结构和可能在DateTime上的一些扩展方法,并可能实现一些运算符,如==和<,>?

Mat*_*int 42

请允许我为此经典问题添加更新:

  • Jon Skeet的Noda Time库现在非常成熟,并且只有一个名为date的类型LocalDate.(在这种情况下,本地只对某人而言是本地的,不一定是运行代码的计算机的本地.)

  • 名为date-only的类型Date是通过corefxlab项目向.NET Core添加的建议.您将在System.Time包中找到它,以及TimeOfDay类型和现有类型的几种扩展方法.

我已经研究过这个问题了,所以我也会分享几个这些类型必要性的原因:

  1. 仅日期和午夜日期值之间存在逻辑差异.

    • 并非每个当地日在每个时区都有午夜.示例:巴西的春季夏令时转换将时钟从11:59:59移动到01:00:00.

    • 日期时间总是指一天中的特定时间,而仅日期可以指日期的开始,一天的结束或一天的整个范围.

  2. 如果未仔细观察时区,则将时间附加到日期可能会导致日期从一个环境传递到另一个环境时更改日期.这通常发生在JavaScript(其Date对象实际上是日期+时间)中,但在.NET中也很容易发生,或者在JavaScript和.NET之间传递数据时在序列化中发生.

  3. DateTime使用XML或JSON(和其他)序列化将始终包括时间,即使它不重要.这非常令人困惑,特别是考虑到出生日期和周年纪念日等时间无关紧要的问题.

  4. 在架构上,它DateTime是一个DDD 值对象,但它在几个方面违反了单一责任原则:

    • 它被设计为日期+时间类型,但通常仅用于日期(忽略时间)或仅用于时间(忽略日期).(TimeSpan也经常用于时间,但那是另一个话题.)

    • DateTimeKind附加到.Kind属性的值将单个类型拆分为三个类型.该Unspecified类型实际上是结构的原始意图,应该以这种方式使用.该Utc种与UTC专门对准值,Local那种对齐与环境的本地时区的价值.

      有一个单独的标志的问题是,每次你消耗a DateTime,你应该检查.Kind以决定采取什么行为.框架方法都是这样做的,但其他人经常忘记.这确实是一个SRP违规,因为该类型现在有两个不同的原因需要改变(价值和种类).

    • 这两个导致API编译的用法,但通常是荒谬的,或者由副作用引起奇怪的边缘情况.考虑:

      // nonsensical, caused by mixing types
      DateTime dt = DateTime.Today - TimeSpan.FromHours(3);  // when on today??
      
      // strange edge cases, caused by impact of Kind
      var london = TimeZoneInfo.FindSystemTimeZoneById("GMT Standard Time");
      var paris = TimeZoneInfo.FindSystemTimeZoneById("Romance Standard Time");
      var dt = new DateTime(2016, 3, 27, 2, 0, 0);  // unspecified kind
      var delta = paris.GetUtcOffset(dt) - london.GetUtcOffset(dt);  // side effect!
      Console.WriteLine(delta.TotalHours); // 0, when should be 1 !!!
      
      Run Code Online (Sandbox Code Playgroud)

总之,虽然a DateTime 只能用于日期,但只有当每个使用它的地方都非常小心地忽略时间时才应该这样做,并且也非常小心不要尝试转换为UTC或其他时区.

  • 如果只有`System.Time.Date`最终会出现在.NET框架中:/ (2认同)

Rob*_*ean 17

我怀疑没有专门的纯Date类,因为你已经有了DateTime它可以处理它.有Date会导致重复和混乱.

如果您想要标准方法,请查看DateTime.Date属性,该属性仅提供a的日期部分,DateTime时间值设置为午夜12:00:00(00:00:00).

  • 专用Date类的一大优势是它不会受到时区和夏令时复杂性的影响. (55认同)
  • 不得不考虑UTC以及与时区有关的任何事情只是浪费精力,因为单独的Date类可以很容易地避免它.而且我没有看到Date和DateTime之间有任何混淆. (6认同)
  • @DimitriC.我不同意 - 你可以使用DateTime和UTC,你不会遇到解释的问题,再加上DateTime,即使你只想要日期,你仍然可以做数学涉及时间(即如果我减去20 x 2小时给我日期从今天开始). (3认同)
  • 同意C#真的应该有一个Date类.时区转换不仅是潜艇漏洞的持续来源,而且在处理基于工作日而不是基于时间的事情时,这简直是痛苦的. (3认同)
  • @RobertMacLean:考虑“如果我从今天减去 20 x 2 小时的日期”是没有意义的。在这个例子中,您认为今天是“今天午夜”吗?“今天中午”?等等。这个问题没有很好地表述。如果您的意思是“今天午夜”,那么您已经在使用 DateTime,而不是 Date。为了减少时间,您需要一个小时,而不是一天。 (2认同)

MVC*_*CDS 11

我已经通过电子邮件发送了refsrcfeedback@microsoft.com,这就是他们的答案

马科斯,这不是一个问这样的问题的好地方.试试http://stackoverflow.com 简短的回答是你需要一个模型来表示一个时间点,而DateTime这样做,它是实践中最有用的场景.人类使用两个概念(日期和时间)来标记时间点的事实是任意的,对于分离是没有用的.

只有在有保证的地方才能脱离,不要仅仅为了盲目做事而做事.可以这样想:你有什么问题可以通过将DateTime分成日期和时间来解决?你现在没有什么问题?提示:如果您查看.NET框架中的DateTime用法:http://referencesource.microsoft.com/#mscorlib/system/datetime.cs#df6b1eba7461813b#references 您将看到大多数都是从方法返回的.如果我们没有像DateTime这样的单一概念,则必须使用out参数或Tuples来返回一对Date和Time.

HTH,Kirill Osenkov

在我的电子邮件中,我质疑是否是因为DateTime使用TimeZoneInfo来获取机器的时间 - 现在是正确的.所以我说这是因为它太耦合了,他们向我说话.

  • 也许 MS 可以全力以赴并实现一个 `SpaceTime` 类!嘿,根据爱因斯坦的说法,空间和时间是紧密耦合的,所以我们也不应该区分它们,对吧?(!!!!!!!!!!!) 我对 C# 有点陌生,但我不得不说,这是一个来自 VB.NET 的雷区,简单地说,就是`date`、`Today()`、 `now` 等。没有`DateTime` 前缀垃圾,没有乱七八糟的。(而且这些分号和这种区分大小写的方式确实令人讨厌!现在就开枪打我!) (2认同)
  • 他们自己的SQL Server具有`Date`类型,并且结果必须为`Date`类型-如果它是`Date`类型的结果,则期望它是没有时间的字符串。例如,Delphi也将Date作为DateTime,但是typeinfo对于Date和DateTime是不同的。 (2认同)
  • Kirill Osenkov 正在回答“为什么不将日期和时间类*与*日期时间类分开?”的问题。*实际* Q是“为什么不*也*有单独的日期和时间类?”。我明白日期和时间应该被耦合到一个类中,因为 *date-time* 概念的许多用例都是授予的。但是,可能至少有与 *date* 概念的有效用例一样多的情况。当然,*时间*概念也有许多有效的用例。 (2认同)

Cla*_*lay 10

当你需要一个简单的日期而不用担心时间部分,时区,本地和utc等时,我创建了一个简单的Date结构.

https://github.com/claycephus/csharp-date


Mat*_*int 9

System.DateOnlySystem.TimeOnly types were recently added to .NET 6, and are available in the daily builds.

它们包含在 .NET 6 Preview 4 版本中。

https://github.com/dotnet/runtime/issues/49036

它们位于 .NET 源代码中:

我在这里写了关于他们的博客。

  • 是时候了,如果可以的话 (6认同)