如何使用java在每天晚上8点(20:00时)弹出对话框?
How to pop up a dialog box at 8pm (20:00 hours) every day using java?
我写了一个 java 代码,每天晚上 8 点(20:00 时)弹出一个对话框。然而,代码只在第一次工作,在我改变时间后就不再工作了。这是我的代码:
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);
}
}
我的代码有什么问题吗?请帮我解决这个问题,每天晚上8点弹出对话框。
Is there anything wrong with my code?
您的计时器任务会检查时间,精确到小时、分钟和秒。您计划此任务的周期性延迟为 5 秒(1000 * 5
毫秒)。这意味着您不太可能准确命中 20:00:00。例如,您可以在 19:59:57 检查,然后在 20:00:02 再次检查,甚至 20:00:03 因为每次检查都需要一些时间,而且时间永远不会准确。
显然你第一次很幸运,但后来就没有了。
一个可能的修复方法是使用两个重载 scheduleAtFixedRate
方法之一,周期为 1 天。然后你的计时器任务在被调用时可以相信时间已经到了并且不需要检查。我会将 1 天指定为 TimeUnit.DAYS.toMillis(1)
,它比某些乘法更易读且不易出错。
您也可以考虑使用操作系统的调度功能,而不是自己编写代码。重新发明轮子往往是一项糟糕的投资。
Calendar
已过时
您使用的 Calendar
class 早已过时且设计不佳。我建议您查看 java.time,现代 Java 日期和时间 API,以进行替换。
不幸的是,scheduleAtFixedRate(TimerTask, Date, long)
接受了一个至少与 java.util.Date
一样过时的类型的参数。使用 java.time 获得 Date
:
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());
当然使用你自己的时区,我把Asia/Chungking.
链接
- Oracle tutorial: Date Time 解释如何使用
java.time
.
Timer.scheduleAtFixedRate
documentation
我写了一个 java 代码,每天晚上 8 点(20:00 时)弹出一个对话框。然而,代码只在第一次工作,在我改变时间后就不再工作了。这是我的代码:
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);
}
}
我的代码有什么问题吗?请帮我解决这个问题,每天晚上8点弹出对话框。
Is there anything wrong with my code?
您的计时器任务会检查时间,精确到小时、分钟和秒。您计划此任务的周期性延迟为 5 秒(1000 * 5
毫秒)。这意味着您不太可能准确命中 20:00:00。例如,您可以在 19:59:57 检查,然后在 20:00:02 再次检查,甚至 20:00:03 因为每次检查都需要一些时间,而且时间永远不会准确。
显然你第一次很幸运,但后来就没有了。
一个可能的修复方法是使用两个重载 scheduleAtFixedRate
方法之一,周期为 1 天。然后你的计时器任务在被调用时可以相信时间已经到了并且不需要检查。我会将 1 天指定为 TimeUnit.DAYS.toMillis(1)
,它比某些乘法更易读且不易出错。
您也可以考虑使用操作系统的调度功能,而不是自己编写代码。重新发明轮子往往是一项糟糕的投资。
Calendar
已过时
您使用的 Calendar
class 早已过时且设计不佳。我建议您查看 java.time,现代 Java 日期和时间 API,以进行替换。
不幸的是,scheduleAtFixedRate(TimerTask, Date, long)
接受了一个至少与 java.util.Date
一样过时的类型的参数。使用 java.time 获得 Date
:
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());
当然使用你自己的时区,我把Asia/Chungking.
链接
- Oracle tutorial: Date Time 解释如何使用
java.time
. Timer.scheduleAtFixedRate
documentation