【发布时间】: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);
有没有更好的办法?
【问题讨论】:
创建表示“今天”的 LocalDate 实例的推荐方法是什么。我原以为 LocalDate 类中有一个静态的“Now”或“Today”属性,但没有。我目前的方法是使用 DateTime.Now:
var now = DateTime.Now;
LocalDate today = new LocalDate(now.Year, now.Month, now.Day);
有没有更好的办法?
【问题讨论】:
首先要认识到,当您说“今天”时,世界不同地区的不同人的答案可能会有所不同。因此,为了获取当前的本地日期,您必须记住时区。
当您从 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.
【讨论】:
Matt 的回答是 Noda Time 1.x.
在 Noda Time 2.0 中,我引入了 ZonedClock,它基本上是 IClock 和 DateTimeZone 的组合。由于您可能多次希望当前时间处于同一时区,因此您可以注入它(我假设您正在使用依赖注入)并保留它,然后使用它。例如:
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() 方法。;
【讨论】:
ZonedClock 应该注册多长时间?
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();
您也可以根据您的用例使用GetCurrentLocalDateTime 或GetCurrentOffsetDateTime。
【讨论】: