Home > other >  Get seconds between next day with time
Get seconds between next day with time

Time:05-15

I am trying to get the Duration until the next time, depending on a Day of Week in Java.

I want to be able to schedule a Java task for the next day in a list, at a specific time, so for example, with a list of Monday and Thursday, and it is Sunday, I want to get the seconds until the Monday at a specific time based on hours and minutes passed into the method.

This means that if the current day is Sunday at 10:00AM, and I pass in the time 09:00, I want to go to the next day in the list.

Examples:

daysToFire = ['Monday', 'Wednesday', 'Friday', 'Sunday']

hours = 10

minutes = 10

  • On Monday 11:00, I want to get the Duration until Wednesday 10:10
  • On Monday 09:00 I want to get the Duration until Monday 10:10
  • On Sunday 20:00 I want to get the Duration until Monday 10:10
  • On Wednesday 13:00 I want to get the Duration until Friday 10:10

My current method always goes out at the last return.

private Duration getDurationUntilNext(int hours, int minutes) {
final Instant instant = Instant.now(Clock.system(timeZone));

final DayOfWeek currentDay = instant.atZone(timeZone).getDayOfWeek();

final ZonedDateTime currentZonedDateTime = instant.atZone(timeZone);

for(DayOfWeek dayOfWeek : daysToFire) {
    if(currentDay == dayOfWeek) {
        final ZonedDateTime nextTime = currentZonedDateTime
                .with(TemporalAdjusters.nextOrSame(currentDay))
                .withHour(hours)
                .withMinute(minutes)
                .withSecond(0);

        if(nextTime.isAfter(currentZonedDateTime))
            return Duration.between(currentZonedDateTime, nextTime);
    }
}

return Duration.ZERO;

}

If anyone can help, that would be very much appreciated. Thank you all for the help already!

CodePudding user response:

By the way, you could shorten Instant.now(Clock.system(timeZone)) to Instant.now().


Define the time zone by which you want to recognize date and time.

ZoneId z = ZoneId.of( "Africa/Tunis" ) ;

Capture the current moment as seen in that zone.

ZonedDateTime now = ZonedDateTime.now( z ) ;

Define your list of day-of-week.

List< DayOfWeek > dows = List.of( DayOfWeek.MONDAY , DayOfWeek.THURSDAY ) ;

Specify your target time of day.

LocalTime targetTime = LocalTime.of( 10 , 0 ) ; 

For each day of week, adjust the current moment to that day of week at that time.

TemporalAdjuster ta = TemporalAdjusters.nextOrSame( dow ) ;
ZonedDateTime zdt = now.with( ta ).with( targetTime ) ;

Be aware that your target time may not exist on that date in that zone. A further adjustment will be made automatically as needed.

Calculate duration.

Duration d = Duration.between ( now , zdt ) ;

Test to see if negative. A negative duration means we are going backward in time, means zdt came before now. When encountering a negative duration, we need to use a temporal adjuster of next rather than nextOrSame.

if( d.isNegative() ) {  // If zdt is in the past …
    zdt = zdt.with( TemporalAdjusters.next( dow ) ).with( targetTime ) ;
}

Notice that java.time uses immutable objects. So zdt.with generates a new fresh instance of ZonedDateTime rather than altering (“mutating”) the original.

Recalculate the duration.

d = Duration.between ( now , zdt ) ;

I ignored your desired ten minute gap, as I do not understand what you are doing there exactly, and it seems like a minor distraction. You can add ten minutes where needed along the process I outlined above.

CodePudding user response:

Based on your code you are checking if currentDay is from available list of days. If its not, then you are simply skipping your logic. I am suggesting you below --

for (DayOfWeek dayOfWeek : daysToFire) {
    if (currentDay == dayOfWeek) {

    final ZonedDateTime nextTime = currentZonedDateTime.with(TemporalAdjusters.nextOrSame(currentDay))
                            .withHour(hours).withMinute(mins).withSecond(0);
    
    if (nextTime.isAfter(currentZonedDateTime))
                        return Duration.between(currentZonedDateTime, nextTime);
      return Duration.between(nextTime, currentZonedDateTime);

    } else if (currentDay.getValue() < dayOfWeek.getValue()) {
                    final ZonedDateTime nextTime = currentZonedDateTime.with(TemporalAdjusters.nextOrSame(dayOfWeek))
                            .withHour(hours).withMinute(mins).withSecond(0);
                    return Duration.between(currentZonedDateTime, nextTime);
                } else
                    continue;
            }


  return Duration.ZERO;
}

Please let us know if this fulfils your requirement. Thanks.

  • Related