如何使用spring scheduler在每个时区的上午0点做一些工作?

时间:2018-03-29 08:59:03

标签: java timezone spring-scheduled

就像标题一样,某些任务需要在每个时区的0 am执行,但@scheduler注释只支持设置一个区域,如下所示:

@Scheduled(cron = "0 0 0 * * ?", zone = "Asia/Shanghai")
public void scheduleTask() {...}

我只能在亚洲/上海的上午0点完成任务,如何在每个时区执行此任务。 Spring调度程序支持?或任何其他工具可以帮助我?

抱歉,我可能没有清楚地描述这个问题。

这是我们的任务场景:我们有一个任务要在每个月的第一天凌晨0点执行,但是每个国家/地区都有不同的UTC,那么如何在每个国家/地区执行此任务0 a.m?

我们有一个国家/地区表,我可以使用国家/地区代码获取资本utc zoneid,就像:CN - > UTC + 08:00。

2 个答案:

答案 0 :(得分:1)

我想提醒一下将国家映射到抵消的方法,主要是因为:

  • 一个国家/地区可以有超过1个时区,每个时区都有不同的偏移量。例如,美国有4个(太平洋时间,山区时间,中部时间和东部时间 - 实际上,它因阿拉斯加和夏威夷而有更多),Russia has more than 10等。甚至相同的可以有超过1个时区(例如Arizona
  • 同一个国家/地区,即使只有1个时区,也可以拥有夏令时(DST),因此全年有2种不同的偏移量
  • 在某些国家,DST从午夜开始,这意味着时钟向前跳1小时,从23:59直接跳到凌晨1点 - 所以在DST过渡期间,午夜在这些时区不存在
  • DST规则可以随时由政府更改,因此您不能认为这些规则总是相同的。一个没有DST的国家可以决定开始使用它(反之亦然),或者更改DST开始和/或结束的日期等。

因此,将国家/地区映射到偏移量是一种非常简单且容易出错的方法。它可能适用于某些情况,但不能保证在所有国家的所有月份都能一直工作。实际上,它会在很多情况下失败。

理想的方法是使用Continent/Region格式America/New_York(例如Asia/ShanghaiAmerica/New_York),并使用能够自动处理DST问题的API为您计算正确的偏移量。对于具有多个时区的国家/地区,您必须根据某些条件任意选择一个IANA名称(例如:在美国,我应该使用America/ChicagoAmerica/Los_AngelesList<String> timezones = // timezones you want // month that I care about (example: March 2018) YearMonth yearMonth = YearMonth.of(2018, 3); for (String zoneName : timezones) { ZoneId zone = ZoneId.of(zoneName); // get midnight at first day of month, in this timezone ZonedDateTime utc = yearMonth // 1st of month .atDay(1) // midnight at the timezone .atStartOfDay(zone) // convert to UTC .withZoneSameInstant(ZoneOffset.UTC); // get the fields you need to configure the job utc.getDayOfMonth(); utc.getHour(); ... etc } 吗?这取决于你决定。)

我还建议您使用IANA's timezones names(如果可用)(或Java 8 datetime API用于较低版本)。此API为您处理时区和DST内容,您可以获得与每个时区的午夜相对应的精确UTC时刻。

utc

使用此代码,变量listFileSystem: function () { var htmlString = '<ul id="file-system-list"'; var addFileEntry = function (fs) { var reader = fs.createReader(); reader.readEntries( function (entries) { entries.forEach(function (entry) { if (entry.isDirectory === true) { htmlString += '<li>' + '<h2>' + entry.fullPath + '</h2>' + '<ul>' ; // here is the recursive call that's 'skipped' // and performed some random time later // resulting in all the recursive calls // returning in random order addFileEntry(entry); htmlString += '</ul></li>'; } else { htmlString += '<li><h3>' + entry.fullPath + "</h3></li>"; } }); } ); }; // this function too is skipped, and then performed later, resulting // in the <ul> being closed instantly and appended as such // (since the callback here calls the list-building function) // in Debugging however it seems like I can just wait until this // function has executed and control flow at this point then is sane window.resolveLocalFileSystemURL(cordova.file.applicationDirectory, addFileEntry); htmlString += '</ul>'; $('#file-cont').append(htmlString); } 将等于每个时区的午夜(或当天的DST开始时的DST开始时的第一时刻),但已转换为UTC的值。您可以获得日期,月份,年份,小时,分钟,您想要的任何内容(以UTC为单位),以便将作业配置为在该时刻正好运行。

答案 1 :(得分:0)

我认为如果您创建多个触发器并将它们设置为您需要从您需要的时区列表执行任务的时间,那么您将获得更好的服务。

特别是如果作品依赖于任务被触发的时区。

    List<Integer> timezoneDelays = Arrays.asList(1, 2, 5);
    for (double d : timezoneDelays){
        CronTrigger cronTrigger = new CronTrigger("0 0 " + d + " * * ?");
        taskScheduler.schedule(new RunnableTask("Cron Trigger"), cronTrigger);
    }

http://www.baeldung.com/spring-task-scheduler

此外,简单地将任务设置为每小时或半小时启动也可能对您有用。