创建一个代表 "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
,它基本上是 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()
方法。;
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
。
创建表示 "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
,它基本上是 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()
方法。;
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
。