2

I am creating a universal scheduler where the user can select the Zone and schedule the job at a specified start time. I take start time in ZonedDateTime type and quartz .startAt() requires a Date which is converted as follows.

Current Scenarios:

Cron Expression: 0 0/1 * * * ? (Every minute)
Server TimeZone: Asia/Kolkata 
Client TimeZone: [Europe/Paris] -4.5 

Start firing from next minute after schedule because of date gets convert in IST as per server Thu Jan 09 10:00:31 IST 2020. Please correct me if I am wrong.

14:24:37.054 [XNIO-1 task-17] DEBUG c.c.a.s.impl.ScheduledJobServiceImpl - creating trigger for key 2104:  at date :2020-01-09T09:00:31Z[UTC] 
14:24:37.054 [XNIO-1 task-17] DEBUG c.c.a.s.util.JobScheduleCreator - Request to create simple-trigger for minutes groupKey:1101, scheduleId: 2104, cron-expression: 0 0/1 * * * ?
14:24:37.055 [XNIO-1 task-17] DEBUG c.c.a.s.util.JobScheduleCreator - Request to create date from ZonedDateTime in UTC based on localtime of user: 2020-01-09T09:00:31Z[UTC], zoneId: Europe/Paris
14:24:37.055 [XNIO-1 task-17] DEBUG c.c.a.s.util.JobScheduleCreator - startTime to Instance: 2020-01-09T09:00:31Z
14:24:37.055 [XNIO-1 task-17] DEBUG c.c.a.s.util.JobScheduleCreator - time at zone: 2020-01-09T10:00:31+01:00[Europe/Paris]
14:24:37.055 [XNIO-1 task-17] DEBUG c.c.a.s.util.JobScheduleCreator - localDateTime at Zone: 2020-01-09T10:00:31
14:24:37.055 [XNIO-1 task-17] DEBUG c.c.a.s.util.JobScheduleCreator - DATE: Thu Jan 09 10:00:31 IST 2020

Cron Expression: 0 0/1 * * * ? (Every minute) 
Server TimeZone: Asia/Kolkata 
Client TimeZone: [Australia/Sydney] +5.5 

Will Fire at Thu Jan 09 20:00:41 IST 2020 which should be Thu Jan 09 20:00:41 AET 2020. Right?

14:24:48.185 [XNIO-1 task-18] DEBUG c.c.a.s.impl.ScheduledJobServiceImpl - creating trigger for key 2105:  at date :2020-01-09T09:00:41Z[UTC] 
14:24:48.186 [XNIO-1 task-18] DEBUG c.c.a.s.util.JobScheduleCreator - Request to create simple-trigger for minutes groupKey:1101, scheduleId: 2105, cron-expression: 0 0/2 * * * ?
14:24:48.186 [XNIO-1 task-18] DEBUG c.c.a.s.util.JobScheduleCreator - Request to create date from ZonedDateTime in UTC based on localtime of user: 2020-01-09T09:00:41Z[UTC], zoneId: Australia/Sydney
14:24:48.186 [XNIO-1 task-18] DEBUG c.c.a.s.util.JobScheduleCreator - startTime to Instance: 2020-01-09T09:00:41Z
14:24:48.186 [XNIO-1 task-18] DEBUG c.c.a.s.util.JobScheduleCreator - time at zone: 2020-01-09T20:00:41+11:00[Australia/Sydney]
14:24:48.186 [XNIO-1 task-18] DEBUG c.c.a.s.util.JobScheduleCreator - localDateTime at Zone: 2020-01-09T20:00:41
14:24:48.186 [XNIO-1 task-18] DEBUG c.c.a.s.util.JobScheduleCreator - DATE: Thu Jan 09 20:00:41 IST 2020

Question is:

As said in these answer, For Date JVM’s current default time zone is applied on-the-fly.. So it is not possible to convert IST to AET/ECT! Is it with Date? So I think I have to change the trigger creation implementation which currently takes .startAt() in the only **Date** format. Is there any other way to specify start-time in other formats in trigger creation?

createTrigger(String groupKey, ScheduledJob scheduledJob)

public CronTrigger createTrigger(String groupKey, ScheduledJob scheduledJob) {

        Date startDate = createDatefromZonedDateTime(scheduledJob.getScheduledStartTime(), scheduledJob.getZoneId());

        return newTrigger()
            .withIdentity(scheduledJob.getId().toString(),groupKey)
            .withDescription(scheduledJob.getZoneId())
            .withSchedule(CronScheduleBuilder.cronSchedule(scheduledJob.getCronExpression()).inTimeZone(TimeZone.getTimeZone(scheduledJob.getZoneId()))) 
            .startAt(startDate)
            .build();
    }

createDatefromZonedDateTime(ZonedDateTime startTime, String zoneId)

private Date createDatefromZonedDateTime(ZonedDateTime startTime, String zoneId) {

        log.debug("Request to create date from ZonedDateTime in UTC based on localtime of user: {}, zoneId: {}",startTime, zoneId);

        Instant utc = startTime.toInstant();
        log.debug("startTime to Instance: {}",utc);

        ZonedDateTime timeAtZone = utc.atZone(ZoneId.of(zoneId));
        log.debug("time at zone: {}",timeAtZone);

        LocalDateTime localDateTimeAtZone = timeAtZone.toLocalDateTime();
        log.debug("localDateTime at Zone: {}",localDateTimeAtZone);

        Date dateZone = Date.from(localDateTimeAtZone.atZone(ZoneId.systemDefault()).toInstant());
        log.debug("DATE: "+dateZone);

        return dateZone;
   }

UPDATE:

To convert Date from IST to ECT or user-defined zone, I found TimeZone.setDefault(TimeZone.getTimeZone(zone)); but it's not a recommanded way. Even if I use it, there will be multiple jobs in different zones and .setDefault value will be overwritten by the new one.

Another idea is to dynamically change the DatePicker based on the user-selected zone in angular and based on the value we will convert it to the server zone and schedule it with server zone date and will set user defined zone in .withSchedule(CronScheduleBuilder.cronSchedule(scheduledJob.getCronExpression()).inTimeZone(TimeZone.getTimeZone(scheduledJob.getZoneId()))). Is it the right way to do so?

Romil Patel
  • 12,879
  • 7
  • 47
  • 76

0 Answers0