My server runs on Europe/Rome timezone -and this one is the default tz on the server-, I need to schedule jobs according the user's timezone, so, if a user, living on Pacific/Honolulu timezone, schedules a CronTrigger that fires every day at 22:00pm for his region of the Earth I have found this solution:
CronTrigger trigger = newTrigger()
.withIdentity("name", "group")
.withSchedule(
cronSchedule("0 0 22 ? * *").inTimeZone(TimeZone.getTimeZone("Pacific/Honolulu"))
)
.startNow()
.build();
On my server this job starts at 09:00am of the "my" next day.
There are particular problems to be taken into consideration besides the fact to keep updated the timezone (i.e. Timezone Updater Tool) ?
If I want to define the .startAt() and .endAt() for the previous job, is this kind of date ok? A possible daylight saving time is safe using this procedure?
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();
or I have to set simply start and end using:
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();
Then the job starts/ends correctly in "Pacific/Honolulu" defined days?
Thanks in advance for every suggestion
Create a CronTrigger with the given name and group, associated with the identified JobDetail , and with the given "cron" expression. The start-time will also be set to the current time, and the time zone will be set the the system's default time zone.
Quartz is distributed as a small java library (. jar file) that contains all of the core Quartz functionality. The main interface (API) to this functionality is the Scheduler interface. It provides simple operations such as scheduling/unscheduling jobs, starting/stopping/pausing the scheduler.
Thankfully, you can configure a specific timezone for your Cron job as follows: First, you need to export the TZ variable in your Shell script before any other Shell entries. Next, access your crontab and use the crontab environment variable CRON_TZ at the start of the crontab file.
Quartz scheduler allows an enterprise to schedule a job at a specified date and time. It allows us to perform the operations to schedule or unschedule the jobs. It provides operations to start or stop or pause the scheduler. It also provides reminder services.
I think I found the solution, tested and it works until proved otherwise ;)
Recup My server runs on a specific timezone (i.e. Europe/Rome)
If a user on Pacific/Honolulu TZ want to schedule a job that starts on Sun, 27 Jan 2013 at 3:00PM end ends on Thu, 31 Jan 2013 at 9:00PM that fire every day every five minutes starting from 2:00PM to 10:55PM (0 0/5 14-22 * * ?) the correct way is the following:
Sample Code:
// 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();
Utility to convert dates based on 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;
}
}
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;
}
}
So on my Europe/Rome Quartz server this job are scheduled for starting from Mon Jan 28 02:00:00 CET 2013 to Fri Feb 01 08:00:00 CET 2013 and fire every five minute every day from 01:00AM to 08:55PM
When building your Dates for start and end times also specify the timezone (on the java.util.Calendar, or date format string, or org.quartz.DateBuilder) before instantiating the Date. Then quartz stores the date as milliseconds since January 1, 1970 in UTC in that particular timezone - and hence when the server's timezone changes, the trigger is not affected.
Date doesn't carry any TZ data, and Daylight Savings Time is actually its own TZ (EST is Easter Standard Time, EDT is Eastern Daylight Savings Time). The only thing that may pe an issue is that some places, like Phoenix Arizona, do not recognize DST. Any time you need TZ data preserved, Calendar is the way to go.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With