Create a NodaTime LocalDate representing “today”

人盡茶涼 提交于 2019-12-03 22:37:56

First recognize that when you say "today", the answer could be different for different people in different parts of the world. Therefore, in order to get the current local date, you must have a time zone in mind.

Noda Time correctly models this by giving you an Instant when you call Now from an IClock implementation such as the system clock. An instant is universal, so you just need to convert it to some time zone to get that time zone's local date.

// 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;

That's the minimal code. Of course, if you want to use the computer's local time zone (like you did with DateTime.Now), you can get it like so:

DateTimeZone tz = DateTimeZoneProviders.Tzdb.GetSystemDefault();

And to really implement it properly, you should call .Now from the IClock interface, such that you could substitute the system clock with a fake clock for your unit tests.

This is a great example of how Noda Time intentionally doesn't hide things from you. All this is still going on under the hood when you call DateTime.Now, but you just don't see it. You can read more about Noda Time's design philosophy in the user guide.

Matt's answer is spot on for Noda Time 1.x.

In Noda Time 2.0, I'm introducing a ZonedClock, which is basically a combination of IClock and a DateTimeZone. As you're likely to want the current time in the same time zone multiple times, you can inject that (I'm assuming you're using dependency injection) and retain that, then use it. For example:

class SomeClass
{
    private readonly ZonedClock clock;

    internal SomeClass(ZonedClock clock)
    { 
        this.clock = clock;
    }

    internal void DoSomethingWithDate()
    {
        LocalDate today = clock.GetCurrentDate();
        ...
    }
}

You would normally provide the ZonedClock by taking an IClock and using one of the new extension methods, e.g.

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();

Note that your 1.x code won't work in 2.x anyway - I'm removing the Now property from IClock as it really shouldn't be a property (given the way it changes) - it's now a GetCurrentInstant() method.;

Jon's answer is right, but I think it is helpful to put it all together. For NodaTime 2.x:

SystemClock.Instance.InTzdbSystemDefaultZone().GetCurrentLocalDateTime().Date
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!