【问题标题】:Create a NodaTime LocalDate representing "today"创建一个表示“今天”的 NodaTime LocalDate
【发布时间】:2015-01-09 03:30:56
【问题描述】:

创建表示“今天”的 LocalDate 实例的推荐方法是什么。我原以为 LocalDate 类中有一个静态的“Now”或“Today”属性,但没有。我目前的方法是使用 DateTime.Now:

var now = DateTime.Now;
LocalDate today = new LocalDate(now.Year, now.Month, now.Day);

有没有更好的办法?

【问题讨论】:

    标签: c# .net nodatime


    【解决方案1】:

    首先要认识到,当您说“今天”时,世界不同地区的不同人的答案可能会有所不同。因此,为了获取当前的本地日期,您必须记住时区。

    当您从 IClock 实现(例如系统时钟)调用 Now 时,Noda Time 通过为您提供 Instant 来正确地对此进行建模。瞬间是通用的,因此您只需将其转换为某个时区即可获取该时区的本地日期。

    // get the current time from the system clock
    Instant now = SystemClock.Instance.Now;
    
    // get a time zone
    DateTimeZone tz = DateTimeZoneProviders.Tzdb["Asia/Tokyo"];
    
    // use now and tz to get "today"
    LocalDate today = now.InZone(tz).Date;
    

    这是最少的代码。当然,如果你想使用计算机的本地时区(就像你对DateTime.Now 所做的那样),你可以这样获取:

    DateTimeZone tz = DateTimeZoneProviders.Tzdb.GetSystemDefault();
    

    要真正正确地实现它,您应该从IClock 接口调用.Now,这样您就可以用假时钟替换系统时钟来进行单元测试。

    这是 Noda Time 如何故意不向您隐瞒事情的一个很好的例子。当您致电DateTime.Now 时,这一切仍在幕后进行,但您只是看不到它。 You can read more about Noda Time's design philosophy in the user guide.

    【讨论】:

      【解决方案2】:

      Matt 的回答是 Noda Time 1.x.

      在 Noda Time 2.0 中,我引入了 ZonedClock,它基本上是 IClockDateTimeZone 的组合。由于您可能多次希望当前时间处于同一时区,因此您可以注入它(我假设您正在使用依赖注入)并保留它,然后使用它。例如:

      class SomeClass
      {
          private readonly ZonedClock clock;
      
          internal SomeClass(ZonedClock clock)
          { 
              this.clock = clock;
          }
      
          internal void DoSomethingWithDate()
          {
              LocalDate today = clock.GetCurrentDate();
              ...
          }
      }
      

      您通常会通过采用IClock 并使用其中一种新的扩展方法来提供ZonedClock,例如

      var clock = SystemClock.Instance;
      var zoned = clock.InUtc();
      // Or...
      var zoned = clock.InZone(DateTimeZoneProviders.Tzdb["Europe/London"];
      // Or...
      var zoned = clock.InTzdbSystemDefaultZone();
      // Or...
      var zoned = clock.InBclSystemDefaultZone();
      

      请注意,您的 1.x 代码无论如何都无法在 2.x 中工作 - 我正在从 IClock 中删除 Now 属性,因为它确实不应该是一个属性(考虑到它的变化方式) -现在是GetCurrentInstant() 方法。;

      【讨论】:

      • 我喜欢它。 2.0 一直看起来更好!
      • 使用 DI 时ZonedClock 应该注册多长时间?
      • @Oskar:我真的不知道如何回答这个问题。你总是想要同一个时钟吗?你总是想要同一个时区吗?使用这些问题的答案来推动您的选择。
      • 我总是想要同一个时区。使用同一个时钟有什么缺点吗?
      • @Oskar:几乎可以肯定不是 - 但你是这里所有上下文的人。野田时间方面没有什么特别的。
      【解决方案3】:

      Jon 的回答是正确的,但我认为将它们放在一起会很有帮助。对于 NodaTime 2.x:

      SystemClock.Instance.InTzdbSystemDefaultZone().GetCurrentLocalDateTime().Date
      

      【讨论】:

        【解决方案4】:

        帕特里克的回答是正确的。
        但是,您可能希望为当前用户的时区而不是系统的时区获取 Now。 对于 NodaTime 3.x:

        //Tz is a DateTimeZone object, constructed from current user's preferred timezone ID
        SystemClock.Instance.InZone(Tz).GetCurrentZonedDateTime();
        

        您也可以根据您的用例使用GetCurrentLocalDateTimeGetCurrentOffsetDateTime

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2020-05-07
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-03-07
          • 2020-04-03
          • 1970-01-01
          相关资源
          最近更新 更多