Java Quartz-Scheduler 跨时区

我的服务器在欧洲/罗马时区运行-这是服务器上的默认 tz-,我需要根据用户的时区安排作业,所以,如果用户,生活在太平洋/檀香山时区,为他所在的地球地区安排了一个每天下午 22:00 触发的 CronTrigger 我找到了这个解决方案:

CronTrigger trigger = newTrigger()
  .withIdentity("name","group")
  .withSchedule(
    cronSchedule("0 0 22 ? * *").inTimeZone(TimeZone.getTimeZone("Pacific/Honolulu"))
  )
  .startNow()
  .build();

在我的服务器上这项工作从我的"第二天早上 9:00 开始.

除了时区更新之外,还有一些特殊问题需要考虑(即时区更新工具) ?

如果我想为上一份工作定义 .startAt() 和 .endAt(),这样的日期可以吗?使用此过程可能的夏令时是安全的吗?

Calendar calTZStarts = new GregorianCalendar(TimeZone.getTimeZone("Pacific/Honolulu"));
calTZStarts.set(2013,Calendar.JANUARY,10);

Calendar calTZEnds = new GregorianCalendar(TimeZone.getTimeZone("Pacific/Honolulu"));
calTZEnds.set(2013,30);

Calendar calStarts = Calendar.getInstance();
calStarts.set(Calendar.YEAR,calTZStarts.get(Calendar.YEAR));
calStarts.set(Calendar.MONTH,calTZStarts.get(Calendar.MONTH));
calStarts.set(Calendar.DAY_OF_MONTH,calTZStarts.get(Calendar.DAY_OF_MONTH));
calStarts.set(Calendar.HOUR_OF_DAY,calTZStarts.get(Calendar.HOUR_OF_DAY));
calStarts.set(Calendar.MINUTE,calTZStarts.get(Calendar.MINUTE));
calStarts.set(Calendar.SECOND,calTZStarts.get(Calendar.SECOND));
calStarts.set(Calendar.MILLISECOND,calTZStarts.get(Calendar.MILLISECOND));

Calendar calEnds = Calendar.getInstance();
calEnds.set(Calendar.YEAR,calTZEnds.get(Calendar.YEAR));
calEnds.set(Calendar.MONTH,calTZEnds.get(Calendar.MONTH));
calEnds.set(Calendar.DAY_OF_MONTH,calTZEnds.get(Calendar.DAY_OF_MONTH));
calEnds.set(Calendar.HOUR_OF_DAY,calTZEnds.get(Calendar.HOUR_OF_DAY));
calEnds.set(Calendar.MINUTE,calTZEnds.get(Calendar.MINUTE));
calEnds.set(Calendar.SECOND,calTZEnds.get(Calendar.SECOND));
calEnds.set(Calendar.MILLISECOND,calTZEnds.get(Calendar.MILLISECOND));

CronTrigger trigger = newTrigger()
  .withIdentity("name","group")
  .withSchedule(
    cronSchedule("0 0 22 ? * *").inTimeZone(TimeZone.getTimeZone("Pacific/Honolulu"))
  )
  .startAt(calStarts.getTime())
  .endAt(calEnds.getTime())
  .build();

或者我必须简单地设置开始和结束使用:

Calendar calTZStarts = new GregorianCalendar();
calTZStarts.set(2013,10,0);

Calendar calTZEnds = new GregorianCalendar();
calTZEnds.set(2013,30,0);

CronTrigger trigger = newTrigger()
  .withIdentity("name","group")
  .withSchedule(
    cronSchedule("0 0 22 ? * *").inTimeZone(TimeZone.getTimeZone("Pacific/Honolulu"))
  )
  .startAt(calTZStarts.getTime())
  .endAt(calTZEnds.getTime())
  .build();

那么工作在太平洋/檀香山"定义的日子里正确开始/结束?

提前感谢您的每一个建议

wuxiaolong0815 回答:Java Quartz-Scheduler 跨时区

我想我找到了解决方案,经过测试,它可以工作,直到证明不是这样;)

恢复我的服务器在特定时区(即欧洲/罗马)运行

如果 Pacific/Honolulu TZ 上的用户想要安排一个从 2013 年 1 月 27 日星期日下午 3:00 开始到 2013 年 1 月 31 日星期四晚上 9:00 结束的作业,从 2 点开始每天每五分钟触发一次:00PM to 10:55PM (0 0/5 14-22 * * ?) 正确方式如下:

  • 在 CronScheduleBuilder 的 inTimeZone 方法中设置用户时区
  • 通过从太平洋/檀香山转换为欧洲/罗马来适应服务器时间 startAt 和 endAt 日期

示例代码:

// Begin User Input
String userDefinedTZ = "Pacific/Honolulu"; // +11

int userStartYear = 2013;
int userStartMonth = Calendar.JANUARY;
int UserStartDayOfMonth = 27;
int userStartHour = 15;
int userStartMinute = 0;
int userStartSecond = 0;

int userEndYear = 2013;
int userEndMonth = Calendar.JANUARY;
int UserEndDayOfMonth = 31;
int userEndHour = 21;
int userEndMinute = 0;
int userEndSecond = 0;
// End User Input


Calendar userStartDefinedTime = Calendar.getInstance();
// set start schedule by user input
userStartDefinedTime.set(userStartYear, userStartMonth, UserStartDayOfMonth, userStartHour, userStartMinute, userStartSecond);

Calendar userEndDefinedTime = Calendar.getInstance();
// set end schedule by user input
userEndDefinedTime.set(userEndYear, userEndMonth, UserEndDayOfMonth, userEndHour, userEndMinute, userEndSecond);


CronTrigger trigger = newTrigger()
  .withIdentity("name", "group")
  .withSchedule(
    // define timezone for the CronScheduleBuilder
    cronSchedule("0 0/5 14-22 * * ?").inTimeZone(TimeZone.getTimeZone("Pacific/Honolulu"))
  )
  // adapt user start date to server timezone
  .startAt( convertDateToServerTimeZone(userStartDefinedTime.getTime(), userDefinedTZ) )
  // adapt user end date to server timezone
  .endAt( convertDateToServerTimeZone(userEndDefinedTime.getTime(), userDefinedTZ) )
  .build();

根据 tz 转换日期的实用程序:

public Calendar convertDateToServerTimeZone(Date dateTime, String timeZone) {
    Calendar userDefinedTime = Calendar.getInstance();
    userDefinedTime.setTime(dateTime);
    if(!TimeZone.getDefault().getID().equalsIgnoreCase(timeZone)) {
    System.out.println        ("original defined time: " + userDefinedTime.getTime().toString() + " on tz:" + timeZone);
    Calendar quartzStartDate = new GregorianCalendar(TimeZone.getTimeZone(timeZone));
    quartzStartDate.set(Calendar.YEAR, userDefinedTime.get(Calendar.YEAR));
    quartzStartDate.set(Calendar.MONTH, userDefinedTime.get(Calendar.MONTH));
    quartzStartDate.set(Calendar.DAY_OF_MONTH, userDefinedTime.get(Calendar.DAY_OF_MONTH));
    quartzStartDate.set(Calendar.HOUR_OF_DAY, userDefinedTime.get(Calendar.HOUR_OF_DAY));
    quartzStartDate.set(Calendar.MINUTE, userDefinedTime.get(Calendar.MINUTE));
    quartzStartDate.set(Calendar.SECOND, userDefinedTime.get(Calendar.SECOND));
    quartzStartDate.set(Calendar.MILLISECOND, userDefinedTime.get(Calendar.MILLISECOND));
    System.out.println("adapted time for " + TimeZone.getDefault().getID() + ": " + quartzStartDate.getTime().toString());
    return quartzStartDate;
    } else {
    return userDefinedTime;
    }
}

== 更新开始 2012-01-24 ==

Quartz Based Utility 使用 DateBuilder 转换基于 tz 的日期:

== BEGIN OF UPDATE 2012-01-24 ==

Quartz Based Utility to convert dates based on tz using DateBuilder:

public Calendar convertDateToServerTimeZone(Date dateTime, String timeZone) {
    Calendar userDefinedTime = Calendar.getInstance();
    userDefinedTime.setTime(dateTime);
    if(!TimeZone.getDefault().getID().equalsIgnoreCase(timeZone)) {
      System.out.println("original defined time: " + userDefinedTime.getTime().toString() + " on tz:" + timeZone);

      Date translatedTime = DateBuilder.translateTime(userDefinedTime.getTime(), TimeZone.getDefault(), TimeZone.getTimeZone(timeZone));

      Calendar quartzStartDate = new GregorianCalendar();
      quartzStartDate.setTime(translatedTime);
      System.out.println("adapted time for " + TimeZone.getDefault().getID() + ": " + quartzStartDate.getTime().toString());
      return quartzStartDate;
    } else {
      return userDefinedTime;
    }
}

== 2012-01-24 更新结束 ==

所以在我的 Europe/Rome Quartz 服务器上,这项工作计划从 2013 年 1 月 28 日星期一 02:00:00 CET 到 2013 年 2 月 1 日星期五 08:00:00 CET 开始,每天每五分钟触发一次上午 01:00 至晚上 8:55

在为开始和结束时间构建日期时,还要在实例化日期之前指定时区(在 java.util.Calendar 或日期格式字符串或 org.quartz.DateBuilder 上).然后,quartz 将日期存储为自 1970 年 1 月 1 日以来在该特定时区的 UTC 中的毫秒数 - 因此,当服务器的时区更改时,触发器不会受到影响.

这篇关于Java Quartz-Scheduler 跨时区的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持前端之家!

本文链接:https://www.f2er.com/3175503.html

大家都在问