11

私のサーバーはヨーロッパ/ローマのタイムゾーンで実行されています-これはサーバーのデフォルトのtzです-ユーザーのタイムゾーンに従ってジョブをスケジュールする必要があるため、太平洋/ローマのタイムゾーンに住んでいるユーザーが、地球の彼の地域の22:00pmの日、私はこの解決策を見つけました:

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

私のサーバーでは、このジョブは翌日の「私の」午前9時に開始されます。

タイムゾーンを更新し続けるという事実(つまり、タイムゾーンアップデータツール)以外に、考慮すべき特定の問題がありますか?

前のジョブの.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, Calendar.JANUARY, 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, Calendar.JANUARY, 10, 0, 0, 0);

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

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

次に、ジョブは「太平洋/ホノルル」で定義された日数で正しく開始/終了しますか?

すべての提案を事前に感謝します

4

3 に答える 3

12

私は解決策を見つけ、テストし、そうでないことが証明されるまで機能すると思います;)

Recup Myサーバーは特定のタイムゾーン(つまりヨーロッパ/ローマ)で実行されます

Pacific / Honolulu TZのユーザーが、2013年1月27日午後3時に開始し、2013年1月31日木曜日午後9時に終了するジョブをスケジュールする場合、毎日午後2時から5分ごとに起動します。 10:55 PM(0 0/5 14-22 * *?)正しい方法は次のとおりです。

  • CronScheduleBuilderのinTimeZoneメソッドでユーザーのタイムゾーンを設定します
  • Pacific/HonoluluからEurope/Romeに変換することにより、サーバーの時刻に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==

DateBuilderを使用して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);

      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==

したがって、私のヨーロッパ/ローマクォーツサーバーでは、このジョブは2013年1月28日月曜日02:00:00CET2013から2013年2月1日金曜日08:00:00CET2013まで開始し、毎日午前01:00から08まで5分ごとに起動するようにスケジュールされています。午後55時

開始時刻と終了時刻の日付を作成するときは、日付をインスタンス化する前に、タイムゾーン(java.util.Calendar、または日付形式の文字列、またはorg.quartz.DateBuilder)も指定します。次に、クォーツは1970年1月1日からの日付をその特定のタイムゾーンのUTCでミリ秒単位で保存します。したがって、サーバーのタイムゾーンが変更されても、トリガーは影響を受けません。

于 2013-01-16T08:22:20.027 に答える
1

日付にはTZデータは含まれず、夏時間は実際には独自のTZです(ESTはイースター標準時間、EDTは東部夏時間です)。問題を引き起こす可能性がある唯一のことは、アリゾナ州フェニックスなどの一部の場所がDSTを認識しないことです。TZデータを保存する必要があるときはいつでも、カレンダーが最適です。

于 2013-01-11T13:52:38.090 に答える
0

java8 / java8 +から使用できますZonedDateTime。このようにして、指定された時刻をサーバー固有の時刻に明示的に変換する必要はありません。

protected static Trigger createCronTrigger(String triggerName, ZonedDateTime startTime, String cronExpression, int misFireInstruction, ZoneId timeZone) {
    Trigger trigger = TriggerBuilder.newTrigger()
        .withIdentity(triggerName)
        .startAt(Date.from(startTime.toInstant())).withSchedule(CronScheduleBuilder.cronSchedule(cronExpression).inTimeZone(TimeZone.getTimeZone(timeZone)).withMisfireHandlingInstructionDoNothing())
        .build();
    return trigger;
}

ZonedDateTimeの詳細については、こちらをご覧ください。

于 2020-06-24T12:55:28.390 に答える