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?
Related
According to https://developers.google.com/gmail/api/guides/filtering, if you search for a date, the PST timezone is used.
I have an email with:
Date: Tue, 27 Jul 2021 06:07:49 GMT (06:07 AM)
If you convert this to the PST timezone, it should be:
Date: Mon, 26 Jul 2021 23:07:49 PST (11:07 PM)
Now when i use the query
after:2021/07/27
the email is found but shouldn't be according to the definition (also when i search directly on gmail.com).
For the query
before:2021/07/27
nothing is returned.
I didn't find a description yet on how to correctly search by a date and which timezones are really applied.
I'm using google-api-services-gmail-v1-rev110-1.25.0.jar.
Additional info:
String account = "myemail#gmail.com";
List<String> labelIds = new ArrayList<>();
labelIds.add("Label_mylabelid");
String query = "after:2021/07/27";
List<Message> timeZoneMsgs = gmail.users().messages().list(account).setQ(query).setLabelIds(labelIds).execute().getMessages();
I ran another test: I scheduled some emails to be sent between 11:30pm and 01:00am on the next day.
Here are the date headers (directly out of the payload) of the messages:
Scheduled mail 1
Date: Fri, 24 Dec 2021 23:30:00 +0100
Scheduled mail 2
Date: Fri, 24 Dec 2021 23:45:00 +0100
Scheduled mail 3
Date: Sat, 25 Dec 2021 00:00:00 +0100
Scheduled mail 4
Date: Sat, 25 Dec 2021 00:15:00 +0100
Scheduled mail 5
Date: Sat, 25 Dec 2021 00:30:00 +0100
Scheduled mail 6
Date: Sat, 25 Dec 2021 00:45:00 +0100
Scheduled mail 7
Date: Sat, 25 Dec 2021 01:00:00 +0100
If I search with
after:2021/12/25
directly on gmail.com - i get the messages 3 to 7 and if i search with
before:2021/12/25
I get 1 and 2, which is both correct.
BUT when I do the same with the java call, I only get message 7 (1am) for "after:2021/12/25" and messages 1-6 for "before:2021/12/25".
Another example:
I also tried searching with the epoch time in UTC:
Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
calendar.clear();
calendar.set(2021, Calendar.DECEMBER, 25);
long secondsSinceEpoch = calendar.getTimeInMillis() / 1000L; // 1640390400
Here, I get the same result for direct gmail.com search and java search: Message 7 (1pm) for "after:1640390400" and 1-6 for "before:1640390400".
If I try this for PST (1640419200), I get no messages for "after:1640419200" and all of them for "before:1640419200".
As the documentation states:
To specify accurate dates for other timezones pass the value in seconds instead.
This is a Java sample code, is tested and working .For the example I get all the messages from yesterday 23:00 to today 13:00. Tip: You can use me as a keyword to your email account:
long startTimeEpoch = LocalDateTime.parse("2021-12-27T23:00",
DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm")).toEpochSecond(ZoneOffset.UTC);
long endTimeEpoch = LocalDateTime.parse("2021-12-28T13:00",
DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm")).toEpochSecond(ZoneOffset.UTC);
String query = String.format("after:%s before:%s", startTimeEpoch, endTimeEpoch);
String account = "me";
System.out.println(query);
List < String > labelIds = new ArrayList < > ();
labelIds.add("Label_mylabelid");
List < Message > timeZoneMsgs = service.users().messages().list(account)
.setQ(query)
.execute()
.getMessages();
System.out.println(timeZoneMsgs);
Documentation:
Gmail API Javadoc documentation
LocalDateTime
DateTimeFormatter
Below is the code,
Trigger trigger = TriggerBuilder
.newTrigger().withIdentity(job.getTriggerName(), job.getGroupName())
.withSchedule(CronScheduleBuilder.cronSchedule(new CronExpression(cronExpression)).inTimeZone(TimeZone.getTimeZone(remoteTimezone)).withMisfireHandlingInstructionFireAndProceed())
.startAt(startDate)
.endAt(endDate)
.build();
Below are the logs,
[11-28 15:30:00,906] [pool-1-thread-1] [INFO:QuartzJob:99] job.getStartTimes() - 10:00,11:00,12:00
[11-28 15:30:00,908] [pool-1-thread-1] [INFO:QuartzJob:105] dateValue - Sat Nov 28 15:30:00 IST 2020
[11-28 15:30:00,909] [pool-1-thread-1] [INFO:QuartzJob:105] dateValue - Sat Nov 28 16:30:00 IST 2020
[11-28 15:30:00,910] [pool-1-thread-1] [INFO:QuartzJob:105] dateValue - Sat Nov 28 17:30:00 IST 2020
[11-28 15:30:00,913] [pool-1-thread-1] [INFO:QuartzJob:130] mins --- 30
[11-28 15:30:00,913] [pool-1-thread-1] [INFO:QuartzJob:131] hours --- 15,16,17
[11-28 15:30:00,913] [pool-1-thread-1] [INFO:QuartzJob:132] Timezone startDate --- Sat Nov 28 15:30:00 IST 2020
[11-28 15:30:00,913] [pool-1-thread-1] [INFO:QuartzJob:133] Timezone endDate --- Sat Nov 28 17:30:00 IST 2020
[11-28 15:30:00,913] [pool-1-thread-1] [INFO:QuartzJob:137] Generated cronExpression for the Job is - 0 30 15,16,17 * * ?
Job start times values are in GMT which are converted to IST and Cron Expression is made.
But Getting the below error,
[11-28 15:30:00,936] [pool-1-thread-1] [ERROR:JobExecutor:71] org.quartz.SchedulerException: Based on configured schedule, the given trigger '2020-11-28-DUMMY_JOB_TEST-Jobs.2020-11-28-DUMMY_JOB_TEST-Trigger' will never fire.
Dont understand why this is happening ?
with .startNow() also getting the same Error.
Any help would be highly appreciated.
It seems your start and dates are the same:
Timezone startDate --- Sat Nov 28 15:30:00 IST 2020 Timezone endDate --- Sat Nov 28 17:30:00 IST 2020
they differ only in a few hours, but the quartz scheduler works in a way that the end date must be at least one day after the start date.
You may try testing by removing .endAt(endDate), it should work.
I have application written in spring that allows user to filter data by date.
Filters model:
data class FilterCommand(
#field:DateTimeFormat(pattern = "dd/MM/yyyy") val dateFrom: Date?,
#field:DateTimeFormat(pattern = "dd/MM/yyyy") val dateTo: Date?,
val author: String?,
val state: String?
)
Everything works fine, except when user chooses 07/06/2019 in UI, I get exactly same value in Spring in current timezone.
Is it possible to tell spring to treat this incoming data as UTC?
Or to convert it somehow on model level?
Date I receive: Fri Jun 07 00:00:00 CEST 2019
Date I would like to get: Fri Jun 07 00:00:00 UTC 2019
You can configure the timezone directly in the JVM, so if you set it to UTC, all dates will be on UTC.
I am working on project using GWT java GAE. In my project i have used cron job.
when i schedule its time like every 5 minutes, every 2 minutes in cron.xml then its working fine i will getting my ouput. but when i schedule it time like every 24 hours or every day 21:00 then cron job executed but its throw error :-
E 2015-11-03 20:18:10.825
com.slicktechnologies.server.cronjobimpl.ContractRenewalCronJobImpl ContractRenewallist: Date Before Adding Day03-Nov-2015
E 2015-11-03 20:18:10.832
com.slicktechnologies.server.cronjobimpl.ContractRenewalCronJobImpl ContractRenewallist: Today Date -30 Days DateSat Oct 03 23:59:59 UTC 2015
E 2015-11-03 20:18:10.832
com.slicktechnologies.server.cronjobimpl.ContractRenewalCronJobImpl ContractRenewallist: Today DateMon Nov 02 18:30:00 UTC 2015
E 2015-11-03 20:18:10.832
com.slicktechnologies.server.cronjobimpl.ContractRenewalCronJobImpl ContractRenewallist: Date After Setting the Time Mon Nov 02 23:59:59 UTC 2015
E 2015-11-03 20:18:10.833
com.slicktechnologies.server.cronjobimpl.ContractRenewalCronJobImpl ContractRenewallist: Date Before Adding Day03-Nov-2015
E 2015-11-03 20:18:10.833
com.slicktechnologies.server.cronjobimpl.ContractRenewalCronJobImpl ContractRenewallist: Today Date +30 Days DateWed Dec 02 18:30:00 UTC 2015
E 2015-11-03 20:18:10.833
com.slicktechnologies.server.cronjobimpl.ContractRenewalCronJobImpl ContractRenewallist: Date Before Adding One DayMon Nov 02 18:30:00 UTC 2015
E 2015-11-03 20:18:10.833
com.slicktechnologies.server.cronjobimpl.ContractRenewalCronJobImpl ContractRenewallist: Today Date +30 Days DateThu Dec 03 18:29:29 UTC 2015
E 2015-11-03 20:18:10.833
com.slicktechnologies.server.cronjobimpl.ContractRenewalCronJobImpl ContractRenewallist: In Contract List
E 2015-11-03 20:18:10.833
com.slicktechnologies.server.cronjobimpl.ContractRenewalCronJobImpl ContractRenewallist: Date After Adding One DateMon Nov 02 23:59:59 UTC 2015
I 2015-11-03 20:18:11.146
This request caused a new process to be started for your application, and thus caused your application code to be loaded for the first time. This request may thus take longer and use more CPU than a typical request for your application.
Any help
Thanks in advance
The message about starting a new instance is not an error, it's just an informational message, expected when app instances are dynamically created (note the i marking):
GAE automatically stops dynamic instances after a period of inactivity (of at least 15 minutes) and start new instances on demand. Your app instance is not idle long enough when the job is scheduled every 2 or 5 minutes because of the cron job itself, but it may be when running the job daily.
More details in here.
You can see the message even when running the job every 2 or 5 minutes if, for example, you stop your instance manually.
Is MySQL time zone conversion broken?
I want to save java timestamp to DATETIME db field.
DB timezone GMT
Client timezone PST (GMT -07:00)
useTimezone = true
Client time Jul 30, 09:00:00 (GMT-07:00)
In DB I got Jul 30, 02:00:00 (GMT)
Expected in GMT - Jul 30, 16:00:00 (GMT)
During debugging I found that conversion happens here
http://www.1java2c.com/Open-Source/Java-Document/Database-JDBC-Connection-Pool/mysql/com/mysql/jdbc/TimeUtil.java.htm line 899
Is that a real issue or it is my configuration fail?