Ronnie Overby
Ronnie Overby

Reputation: 46490

Calculate the duration between now and next local time

I need to determine the duration between now and the next occurrance of a local time. Here's what I've got:

Duration GetDuration(IClock clock, LocalTime time, DateTimeZone zone)
{
    // get the current time in this zone
    var now = clock.Now.InZone(zone);

    // find the time in our zone today
    var timeToday = zone.AtLeniently(now.Date + time);

    // find the time in our zone tomorrow
    var timeTomorrow = zone.AtLeniently(now.Date.PlusDays(1) + time);

    // get the next occurrance of that time
    var next = new[]{timeToday, timeTomorrow}.Where(x => x > now).Min();        

    // calculate the duration between now and the next occurance of that time
    var duration = next.ToInstant() - now.ToInstant();  
    Debug.Assert(duration > Duration.Zero);
    return duration;
}

And a test to get the duration between now and the next instant of 5PM eastern time:

var duration = GetDuration(
    SystemClock.Instance,
    new LocalTime(17,00),
    DateTimeZoneProviders.Tzdb["US/Eastern"]);

My question is, since I'm new to NodaTime, am I taking any unnecessary steps or missing any shortcuts?

Upvotes: 3

Views: 414

Answers (2)

Mavlarn
Mavlarn

Reputation: 3883

The most easy way is like this:

    LocalDate now = LocalDate.now();
    LocalDate now2 = now.plusDays(4);
    ChronoUnit.DAYS.between(now, now2);

Upvotes: 0

Jon Skeet
Jon Skeet

Reputation: 1504092

This code is a bit more long-winded than it needs to be - I'd do most of the work in the "local" context, and only convert back to the time zone when you know the LocalDateTime you want to map.

var now = clock.Now.InZone(zone);
// Change this to <= time if you want it to be a "strictly next".
var nextDate = now.TimeOfDay < time ? now.Date : now.Date.PlusDays(1);

return zone.AtLeniently(nextDate + time).ToInstant() - now.ToInstant();

AtLeniently will always return a value which is no earlier than the given LocalDateTime (it returns the later of two ambiguous options, and the start of the interval after a skipped time), so you don't need to worry about DST transitions.

As an aside, feedback about whether the ToInstant() calls in the last line are annoying would be useful. I'd at least consider adding a Duration operator-(ZonedDateTime, ZonedDateTime) to 2.0.

Upvotes: 3

Related Questions