在Noda Time中将系统时间作为LocalDateTime
的惯用方法是什么?我能想到的最直接的方法是
var dt = DateTime.Now
LocalDateTime systemTime = new LocalDateTime(dt.Year, dt.Month, dt.Day, dt.Hour, dt.Minute);
但鉴于Noda Time的entire purpose is to replace DateTime with something that has nicer semantics,我认为有一种首选方法,而不是以上述方式使用DateTime
。我能想出使用Noda的设施是最好的
var zone = NodaTime.TimeZones.BclDateTimeZone.ForSystemDefault();
LocalDateTime systemTime = SystemClock.Instance.Now.InZone(zone).LocalDateTime;
但这似乎很冗长。
答案 0 :(得分:38)
你的第二个例子就是你将如何做到这一点。这是故意详细。请参阅Noda Time's design philosophy。
分三个部分来考虑:
获取当前时刻:
// Instant now = SystemClock.Instance.Now; // NodaTime 1.x
Instant now = SystemClock.Instance.GetCurrentInstant(); // NodaTime 2.x
获取系统的时区。 (这是首选语法)
DateTimeZone tz = DateTimeZoneProviders.Bcl.GetSystemDefault();
将时区应用于瞬间:
ZonedDateTime zdt = now.InZone(tz);
获取LocalDateTime
的最后一步是微不足道的,但要认识到当你这样做时,你正在剥离任何时区信息。 NodaTime中的“Local”不表示“代码运行的计算机的本地”。 (换句话说,它不像DateTimeKind.Local
)
需要考虑的其他事项:
您可能更喜欢使用IClock
界面抽象时钟:
IClock clock = SystemClock.Instance;
// Instant now = clock.Now; // NodaTime 1.x
Instant now = clock.GetCurrentInstant(); // NodaTime 2.x
然后您可以将时钟作为方法参数传递,或者将其注入您喜欢的DI / IoC框架。 (Autofac,Ninject,StructureMap,等等......)。这样做的好处是你可以在单元测试中使用NodaTime.Testing.FakeClock
。有关详细信息,请参阅Unit Testing with Noda Time。
您可能还希望传入DateTimeZone
,这样您就可以在任何地方运行代码,而不必依赖于系统时区。这对于服务器应用程序很重要,但对桌面/移动应用程序则不那么重要。
如果您有其他使用IANA时区的工作,或者您正在使用Noda Time的.NET Standard版本,请更改步骤2以使用Tzdb
提供商:
DateTimeZone tz = DateTimeZoneProviders.Tzdb.GetSystemDefault();
TZDB区域比BCL区域准确得多。 Noda Time会在此初始调用中将您系统的Windows(BCL)时区映射到IANA(TZDB)时区。
如果您对DateTime.Now
如此紧凑而Noda Time如此详细的原因有好奇心,请尝试反编译DateTime.Now
或查看MS参考源。你会发现它在幕后做了基本相同的步骤。