I have a written a java code to popup a dialog box every day at 8pm (20:00 hours). However the code worked for the first time only and didn't work later after I changed the time. This is my code:
import java.util.Calendar;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
import javax.swing.JOptionPane;
public class PopUp {
public static void main(String[] args) {
Timer timer = new Timer();
TimerTask tt = new TimerTask() {
@Override
public void run() {
Calendar cal = Calendar.getInstance();
int hour = cal.get(Calendar.HOUR_OF_DAY);
int min = cal.get(Calendar.MINUTE);
int sec = cal.get(Calendar.SECOND);
if (hour == 20 && min == 00 && sec == 0) {
JOptionPane.showMessageDialog(null, "PopUp Success at "+new Date().toString());
System.out.println("PopUp Success at "+new Date().toString());
}
}
};
timer.schedule(tt, 1000, 1000 * 5);
}
}
Is there anything wrong with my code? Plz help me out in solving this issue to popup the dialog box every day at 8pm.
Is there anything wrong with my code?
Your timer task checks the time, precisely the hour, minute and second. You are scheduling this task with a periodic delay of 5 second (1000 * 5
milliseconds). This means that you are unlikely to hit 20:00:00 exactly. You may for example check at 19:59:57 and then again at 20:00:02, or even 20:00:03 since each check takes a bit of time and timing is never accurate.
Apparently you were lucky the first time but haven’t been the succeeding times.
A possible fix is to use one of the two overloaded scheduleAtFixedRate
methods with a period of 1 day. Then your timer task when invoked can trust that the time has come and needs not check. I would specify 1 day as TimeUnit.DAYS.toMillis(1)
, it’s clearer to read and less error-prone than some multiplication.
You may also consider using the scheduling capability of your operating system rather than coding your own. Reinventing the wheel is often a poor investment.
Calendar
is outdated
The Calendar
class you are using is long outdated and poorly designed. I recommend you look into java.time, the modern Java date and time API, for a replacement.
Unfortunately scheduleAtFixedRate(TimerTask, Date, long)
takes an argument of a type that is at least as outdated, java.util.Date
. To obtain a Date
using java.time:
ZoneId zone = ZoneId.of("Asia/Chungking");
ZonedDateTime at2000 = LocalDate.now(zone)
.atTime(LocalTime.of(20, 0))
.atZone(zone);
if (at2000.isBefore(ZonedDateTime.now(zone))) {
// Time has passed for today; use tomorrow
at2000 = at2000.plusDays(1);
}
Date dateForScheduler = Date.from(at2000.toInstant());
Of course use your own time zone where I put Asia/Chungking.
Links
java.time
.Timer.scheduleAtFixedRate
documentation