Search code examples
javatimercalendarpopupalarm

How to pop up a dialog box at 8pm (20:00 hours) every day using java?


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.


Solution

  • 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