创建一个 NodaTime 的 LocalDate,表示“今天”。

30

如何创建一个代表“今天”的LocalDate实例是推荐的方式?我原本期望在LocalDate类中有一个静态的"Now"或"Today"属性,但实际上却没有。我目前的方法是使用DateTime.Now:

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

有更好的方法吗?

5个回答

30
请注意,当您说“今天”时,不同地区的不同人可能会有不同的答案。因此,为了获得当前本地日期,您必须有一个特定的时区。
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时,所有这些仍然在幕后进行,但您只是看不到它。 您可以在用户指南中阅读有关Noda Time设计哲学的更多信息

25

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()方法。

1
我喜欢它。2.0看起来越来越好! - Matt Johnson-Pint
1
当使用 DI 时,ZonedClock 应该注册为什么生命周期? - Oskar
1
@Oskar:我真的不知道该怎么回答。你总是想要相同的时钟吗?你总是想要相同的时区吗?使用这些问题的答案来驱动你的选择。 - Jon Skeet
1
我总是想要相同的时区。使用相同的时钟有什么不利之处吗? - Oskar
2
@Oskar:几乎可以确定不会有,但是你是具备所有上下文的人。从Noda Time方面来看,没有什么特别的事情发生。 - Jon Skeet

8

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

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

1
LocalDate today = DateTime.Now.ToLocalDateTime().Date;

1
帕特里克的回答是正确的。
但是,您可能希望获取当前用户时区的Now,而不是系统时区。 对于NodaTime 3.x:
//Tz is a DateTimeZone object, constructed from current user's preferred timezone ID
SystemClock.Instance.InZone(Tz).GetCurrentZonedDateTime();

你也可以根据使用情况使用GetCurrentLocalDateTimeGetCurrentOffsetDateTime


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接