6

I'd like to be able to get a correct DateTime for the NEXT occurrence of a time that I can specify with just an hour and minute. I'd also like to be able to do this by specifying the same thing for that hour and minute, but for the next occurrence of that on (say) a Wednesday.

Also, note that if the current minute has already "started" (which I guess means that we're in 00 milliseconds of that minute) then, again, we need to find the "next" occurrence of that time.

An example with (say) getting a DateTime for the next 10:34 AM and next 12:45 PM that's on a Wednesday, would be greatly appreciated.

How can I do this in Joda?

LuxuryMode
  • 33,401
  • 34
  • 117
  • 188

2 Answers2

10

Something like this, for "next 10:34 AM on a Wednesday:"

DateTime getNextTimeOnDay(int dayOfWeek, int hourOfDay, int minuteOfHour)
{
    DateTime now = new DateTime();
    DateTime then = now
        .withDayOfWeek(dayOfWeek)
        .withHourOfDay(hourOfDay)
        .withMinuteOfHour(minuteOfHour)
        .withSecondOfMinute(0)
        .withMillisOfSecond(0);

    return then.isBefore(now) ? then.plusWeeks(1) : then;
}

DateTime nextWednesdayAtTenThirtyFour
    = getNextTimeOnDay(DateTimeConstants.WEDNESDAY, 10, 34);

// as of now, this is 2012-01-06T10:34:00.000-05:00
Matt Ball
  • 354,903
  • 100
  • 647
  • 710
0

java.time

The Answer by Matt Ball is correct for Joda-Time. The makers of Joda-Time have said we should move to the java.time framework built into Java 8 and later as soon as is convenient. So here is the same kind of code rewritten for java.time.

DayOfWeek enum

Since java.time is built into Java, it seems reasonable to replace the argument using an int as the day-of-week with the bundled enum DayOfWeek.

Time Zone

The code in the other Answer has one major issue: It depends implicitly on the JVM’s current default time zone. That default can change at any moment, even during runtime(!). Better to always specify the expected/desired time zone. So I added another argument to our method.

DST Adjustment

If your specified hour and minute land in an anomaly such as Daylight Saving Time (DST), java.time will make an adjustment. Be sure to read the doc to understand that behavior and verify it meets with your desires/expectations.

Using a TemporalAdjustor of next( dayOfWeek ) defined in TemporalAdjustors (notice the plural s) means we will get the next such day, going forward in the future and never the past. So we can drop the ternary test in the return statement.

public ZonedDateTime getNextTimeOnDay ( ZoneId zoneId, DayOfWeek dayOfWeek, int hourOfDay, int minuteOfHour ) {
    ZonedDateTime now = ZonedDateTime.now ( zoneId );
    ZonedDateTime then = now
            .with ( TemporalAdjusters.next ( dayOfWeek ) )
            .withHour ( hourOfDay )
            .withMinute ( minuteOfHour )
            .withSecond ( 0 )
            .withNano ( 0 );

    return then;
}

An example calling that method.

ZoneId zoneId = ZoneId.of ( "America/Montreal" );
ZonedDateTime nextWednesdayAtTenThirtyFour = this.getNextTimeOnDay ( zoneId, DayOfWeek.WEDNESDAY, 10, 34 );

Dump to console.

System.out.println ( nextWednesdayAtTenThirtyFour );

2016-01-20T10:34-05:00[America/Montreal]

By the way, you may want to pass a ZonedDateTime to be used by the method as the starting point rather than assume “now”. This route might be more useful/flexible and facilitate testing. If you choose this route, no need to pass the ZoneId as the passed ZonedDateTime carries with it the assigned time zone.

Community
  • 1
  • 1
Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154