创建一个代表“今天”的NodaTime LocalDate
建议表示“今天”的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
接口调用IClock
,这样你就可以用假时钟代替系统时钟进行unit testing。
这是Noda Time故意不向您隐瞒事情的一个很好的例子。 当你调用DateTime.Now
,所有这些仍然在引擎盖下,但你只是看不到它。 您可以在用户指南中阅读有关Noda Time的设计理念的更多信息 。
对于Noda Time 1.x来说,马特的回答是现实的。
在Noda Time 2.0中,我介绍了一个ZonedClock
,它基本上是IClock
和DateTimeZone
的组合。 由于您可能需要多次在同一时区中的当前时间,您可以注入(我假设您正在使用dependency injection)并保留它,然后使用它。 例如:
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()
方法。
乔恩的答案是正确的,但我认为将它们放在一起是有帮助的。 对于NodaTime 2.x:
SystemClock.Instance.InTzdbSystemDefaultZone().GetCurrentLocalDateTime().Date