0

I have a requirement where I need to run the Java program only between 9AM and 5PM on weekdays. Timezone will be UTC always. The program should start exactly at 9AM and should end before 5PM. If it can't complete before 5PM then it should sleep till next day 08:59:59. If the next day is Weekend then it should start on Monday.

The article difference in seconds between two dates using joda time? explains how to get difference in seconds between two predefined dates but I always want to calculate difference between next working day 9AM and current time.

I'm thinking of using Thread.sleep() by calculating the time difference between two dates. Is there a Joda Time api which I can use to calculate the time difference between two dates?

I already tried getting the current epoch and epoch of next day 9AM if its weekday, calculating the difference between these two epochs and using that value for Thread.sleep but it's little bit messy.

Below is the pseudocode which I used

getNextDayEpoch function contains if/else code to decide if it's a weekday or weekend using Determine if date is weekday/weekend java

Based on whether its weekday or weekend, I get the corresponding epoch value.

currentEpoch = getCurrentEpoch()
nextDayEpoch = getNextDayEpoch()

difference = nextDayEpoch - currentDayEpoch

try {
    Thread.sleep(difference);
} catch (InterruptedException e) {
    e.printStackTrace();
}

Can you please suggest any better way to do it?

M. Prokhorov
  • 3,894
  • 25
  • 39
rakesh
  • 135
  • 3
  • 15

3 Answers3

6

Maybe you want to learn about Scheduling ScheduledExecutorService you can also take a look at the Quartz-Framwork

I would take quartz for this.

Phash
  • 428
  • 2
  • 7
0

If your are currently using spring in your project, you could try @Scheduled annotation with a cron param

@Scheduled(cron = "0 0 1 * * ?")
public void doThing() {
//...
}

See https://spring.io/guides/gs/scheduling-tasks/

admlz635
  • 1,001
  • 1
  • 9
  • 18
  • Yes Im using this in spring boot project. I will try considering Scheduled annotation or Quartz framework as mentioned by @Phash – rakesh Aug 10 '19 at 08:16
0

The Joda-Time project is now in maintenance-mode. The creator of Joda-Time, Stephen Colebourne, went on to lead JSR 310 and its implementation in the java.time classes.

Set your limits.

LocalTime ltStart = LocalTime.of( 9 , 0 ) ; 
LocalTime ltStop = LocalTime.of( 17 , 0 ) ; 

Get current moment as seen in your desired time zone.

ZoneId z = ZoneOffset.UTC ;  // Or ZoneId.of( "Africa/Casablanca" ) or such.
ZonedDateTime now = ZonedDateTime.now( z ) ;

Compare the time-of-day.

if( now.toLocalTime().isBefore( ltStart() ) {
    // Wait until start
    Duration d = Duration.between( now , now.with( ltStart ) ) ;
    // Use that duration to schedule task. 
}

See if the current moment is within the work time.

if( ( ! now.toLocalTime().isBefore( ltStart ) && ( now.toLocalTime().isBefore( ltStop ) { // do work }

If now is after the stop time, add a day with plusDays, call with to set tomorrow to 9 AM, and calculate duration for length of time to wait.

You want the next working day. You could write the code yourself to skip Saturday and Sunday by using the DayOfWeek enum. But I suggest adding the ThreeTen-Extra library (also led by Stephen Colebourne) to your project. It offers the nextWorkingDay implementation of TemporalAdjuster.

// If the current time is on or after the stop time…
if( ! now.toLocalTime().isBefore( ltStop ) ) { 
    TemporalAdjuster ta = org.threeten.extra.Temporals.nextWorkingDay() ;
    ZonedDateTime nextStart = now.with( ltStart ).with( ta ) ;
    Duration d = Duration.between( now , nextStart ) ;
    // Use duration to schedule next execution.
}

After testing for your three possibilities (before start, within start-stop, and after stop), I recommend adding an "else" as defensive programming to make sure your code is correct.

Thread.sleep(difference);

Sleeping a thread can work, but is a relatively crude way of doing this.

Learn about the Executors framework in Java to make easy work of scheduling tasks. See Oracle Tutorial. And search Stack Overflow as this has been covered many times.

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
  • Thanks for the detailed explanation. I have a question though. Instead of periodically checking if the time lies between 9AM and 5PM, can I use Executors framework to trigger an event to pause program execution? For eg: when the time is 5PM, the scheduled executors should trigger an event and when the main thread receives the signal, it should sleep till next working day. – rakesh Aug 10 '19 at 08:15
  • @rakesh The executors framework is for triggering execution to start, not stop. Which is how you should be thinking. If your 9-5 worker continues nonstop, then you should have a background thread that is scheduled to raise a flag at the end of a 9-5 shift. Your 9-5 worker frequently checks for that flag, and quits when found after scheduling with an executor to start at 9 AM another 9-5 worker and start another flag-raiser. Or use another background worker to start the 9-5 shift so the 9-5 worker knows nothing about scheduling and only knows it’s work-task. (Single-Responsibility Principle). – Basil Bourque Aug 10 '19 at 15:04