创建一个代表 "today" 的 NodaTime LocalDate

Create a NodaTime LocalDate representing "today"

创建表示 "today" 的 LocalDate 实例的推荐方法是什么。我期待 LocalDate 类中有一个静态 "Now" 或 "Today" 属性,但没有。我目前的做法是使用 DateTime.Now:

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

有没有更好的方法?

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

Noda Time 通过在您从 IClock 实现(例如系统时钟)调用 Now 时为您提供 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.

马特的回答在野田时代 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() 方法。;

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

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

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

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

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