1

I'm trying to write code to run at 1 am. The idea is to find the amount of time to next day in milliseconds, then do a sleep on that time I do this by getting the reminder of the current time divided by to days time.

remainder= current time % 8640000

where current time is gotten from Time.getTimeInMillis();
I got 61175831
to get days by divide it by (606024)
witch gives me 16 hours

It's 1pm so 13+16=30 or 6am next day not 1 am in morning

delayTime=24*60*60*1000; // i day
Calendar Time = Calendar.getInstance(); 
long delay=TimeToNumber%delayTime;
ling days=delay/1000;
days=days/60;
days=days/60

Got 16 for days

Abra
  • 19,142
  • 7
  • 29
  • 41
Ted pottel
  • 6,869
  • 21
  • 75
  • 134
  • 3
    Why not do this with a [cron](https://en.wikipedia.org/wiki/Cron) task? Long timers like this are usually not well suited for things like this as they won't run if the program crashes or if anything goes wrong with the clock. Cron is the defacto way to schedule some task on a *nix system. – zero298 May 10 '21 at 17:35
  • Use scheduler(cron ore prefix_delay) and enable it in your spring application – Lunatic May 10 '21 at 17:41
  • 1
    Does this answer your question? [How to run certain task every day at a particular time using ScheduledExecutorService?](https://stackoverflow.com/questions/20387881/how-to-run-certain-task-every-day-at-a-particular-time-using-scheduledexecutorse) – Abra May 10 '21 at 18:09
  • @zero298 One problem with *cron* as a solution is that in deployment it requires the correct administration by a sysadmin, and lays outside he control of the Java programmer. – Basil Bourque May 10 '21 at 18:46
  • This code as is doesn't compile. It has some syntax errors (`ling` vs. `long`), variables that aren't declared (`TimeToNumber`), etc. This would be much improved (and probably receive fewer downvotes/votes to close) those were fixed. – M. Justin May 10 '21 at 18:50

1 Answers1

2

Without knowing more about your usage scenario, I can't really comment on whether your suggested approach is the best way to do the actual scheduling. However, I can answer the question of how to determine the number of milliseconds until 1:00 AM.

ZonedDateTime now = ZonedDateTime.now();

LocalTime targetTime = LocalTime.parse("01:00");

ZonedDateTime targetDateTime;
if (now.toLocalTime().isBefore(targetTime)) {
    targetDateTime = now.with(targetTime);
} else {
    targetDateTime = now.plusDays(1).with(targetTime);
}

long millis = Duration.between(now, targetDateTime).toMillis();

Explanation

The Calendar API is a legacy API that comes with a bunch of challenges and gotchas with using it. Additionally, by attempting to do the calculations yourself mathematically, you're missing the various nuances that are automatically handled for you by the libraries (such as daylight saving time shifts and the like). For these reasons, I strongly suggest using the newer java.time API.

For this particular question, you need to determine the number of milliseconds until the next 1:00 AM. If the time is before 1:00 in the current date, you want to return the current date's 1:00. If it's after 1:00, you want to return tomorrow's 1:00.

ZonedDateTime is a good choice to represent 1:00 today/tomorrow, since in addition to the date & time, a time zone is needed in order to correlate the datetime with a specific instant in time.

Retrieving the next 1:00 can be achieved by comparing the current LocalTime with a LocalTime of 1:00 AM:

ZonedDateTime now = ZonedDateTime.now();

LocalTime targetTime = LocalTime.parse("01:00");

ZonedDateTime targetDateTime;
if (now.toLocalTime().isBefore(targetTime)) {
    targetDateTime = now.with(targetTime);
} else {
    targetDateTime = now.plusDays(1).with(targetTime);
}

This is assuming you're using the system default time zone. If you want to use a different time zone, this can be specified in the call to ZonedDateTime.now():

ZonedDateTime now = ZonedDateTime.now(ZoneId.of("America/New_York"));

With this ZonedDateTime representing the next 1:00 AM, you can use a Duration between the current time and that time, and then get the number of milliseconds in the duration:

long millis = Duration.between(now, targetDateTime).toMillis();
M. Justin
  • 14,487
  • 7
  • 91
  • 130
  • Solid Answer, correct and clear. Much better than any of the Answers on the [proposed duplicate](https://stackoverflow.com/questions/20387881/how-to-run-certain-task-every-day-at-a-particular-time-using-scheduledexecutorse). – Basil Bourque May 10 '21 at 18:44