安排任务在特定时间执行(在Java中)

时间:2020-06-05 01:31:55

标签: java timer schedule

我已经在论坛上找到了这个问题,并且得到了答案,但它与我的问题不太吻合。

所以事情是这样的(这是给大学分配的):我必须安排一个任务在将来的特定时间(由程序的用户定义)进行。

首先,我开始尝试通过以下方式选择日期来实现此目的:

//this is my main class

        DateFormat dateFormatter = new SimpleDateFormat("yyyy-mm-dd hh:mm:ss");
        String year = String.valueOf(LocalDate.now().getYear());
        String month = String.valueOf(LocalDate.now().getMonthValue());
        String day = "05";
        Date date = dateFormatter.parse(year + "-" + month + "-" + day + " 02:24:08");

        Timer timer = new Timer();
        timer.schedule(new MyTimeTask("Patrick"), date);

//the class MyTimeTask:

        public class MyTimeTask extends TimerTask {
           private String name;
           public MyTimeTask(String name) {
              this.name = name;
           }
           public void run() {
              System.out.println(this.name);
           }
        }

问题是:这在我想要的时间没有运行。相反,无论我选择将来的日期,它都会在我运行文件后立即自动运行。

我在哪里错了?

谢谢。

2 个答案:

答案 0 :(得分:1)

您的代码中有几个问题需要解决。

首先是:new SimpleDateFormat("yyyy-mm-dd hh:mm:ss")。仔细看看您的模式。 yyyy-mm-dd hh:mm:ss转换为year-minute-day hour:minute:second。我相信您想要的是下一年的月份,而不是分钟。只需对yyyy-MM-dd hh:mm:ss进行更改即可解决此问题。

第二,LocalDate.now().getMonthValue()返回了6(而不是06),因此您的模式yyyy:MM:dd与之不匹配。要解决此问题,我将把您的年和月字符串组合成一个变量,以便您可以使用DateTimeFormatter将月份的格式设置为MM

String yearMonth = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy-MM"));

现在,您可以像这样解析日期:

Date date = dateFormatter.parse(yearMonth + "-" + day + " 02:24:08");

我要做的最后一件事(这不是完全必要的)是指定给定时间是前子午线还是后子午线,或者将小时更改为军事时间。为此,您只需在日期格式化程序的末尾添加“ aa”即可。

这是最终代码:

DateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd hh:mm:ssaa");
String yearMonth = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy-MM"));
String day = "04";
Date date = dateFormatter.parse(yearMonth + "-" + day + " 02:24:08PM");

Timer timer = new Timer();
timer.schedule(new MyTimeTask("Patrick"), date);

答案 1 :(得分:1)

java.time

您已经在使用Java.time(现代Java日期和时间API)中的LocalDate。那很好。当Timer.schedule()需要老式的java.util.Date对象时:

  1. 独家使用java.time进行时间数学。
  2. 转换为现代的Instant
  3. 在调用需要Instant的旧版API之前,将Date转换为Date

出于您的目的,我建议:

    ZoneId zone = ZoneId.systemDefault();
    Instant scheduleTime = YearMonth.now(zone)
            .atDay(5)
            .atTime(LocalTime.of(2, 24, 8))
            .atZone(zone)
            .toInstant();
    Date oldfashionedDate = Date.from(scheduleTime);

    System.out.println(oldfashionedDate);

在我的时区中运行时的输出:

2020年6月5日星期五02:24:08

您的代码出了什么问题?

  1. 您的格式模式字符串yyyy-mm-dd hh:mm:ss是错误的。格式模式字母区分大小写,因此无论您使用大写MM还是小写mm,以及使用HH还是hh都不同。我相信这是您的计时器过早触发的原因。
  2. 作为清晰的代码,我宁愿将时区传递给LocalDate.now(),即使您传递的时区是ZoneId.systemDefault()
  3. 不要读LocalDate.now()两次。如果您的代码运行于午夜,则可能会冒两个不同的日期,并且最终结果不一致。读取一次日期,然后在其余代码中使用该日期。