jmrozanec / cron-utils

Cron utils for parsing, validations and human readable descriptions as well as date/time interoperability.
http://cron-utils.com
Apache License 2.0
1.13k stars 263 forks source link

Migrate cron expression to another timezone #243

Open jmrozanec opened 6 years ago

jmrozanec commented 6 years ago

I need something like below:

newCronExpression = convert (localCronExpresn,fromLocalTZ, "UTC")

Is it possible using cron-utils?

Let me give an example:

My local timezone is IST i.e. GMT+5.30.

Current local time is: 11:20 AM.

I want a job to run in 45 min of every hour.

So, my cron expression: 45 * * * *

Hence I am expecting my job to run after 25 min ( as starting time is 11:45 AM)

but my job is running as per UTC, because of oozie.

Current time in UTC : 05:50 AM

As per cron expression 45 * * * , the starting time will be 06:45 AM at GMT.

So, the job will be actually started after 55 min.

Expected : After 25 min

Actual : After 55 min

So,

if I am converting my local cron expression 45 * * * to 15 * * * \ at GMT, then actual waiting period will be same as expected.

This feature was originally reported at cron-utils-examples by @jrphub

jmrozanec commented 6 years ago

The same use case is reported at Stackoverflow

SvenssonWeb commented 6 years ago

Is this really supposed to be a part of this utility? Doing the timezone conversion before building the cron expression would probably be easier for everyone. I could see the use case for this if you are writing the cron expression by hand and plugging it into a service. But is that really how this should be done? Adding cron expression to be run on server side, should be expected to run on server time, And if you build some UI to craft the schedules, you could do the time conversion before inserting the values into cron.

jmrozanec commented 6 years ago

@SvenssonWeb there may be different ways to do this - we agree on that. Nevertheless, this use case may not be that straightforward: we may have cases where converting a cron expression to another timezone involve day changes, DST, etc. We understand this could be valuable for anyone who has servers in multiple time zones and needs to execute tasks at the same time, providing a single cron expression and without a central scheduler. Tweaking multiple cron expressions for different timezones would be tedious and error prone: if the library can provide this, we may save some work and headaches to someone.

benjwarner commented 5 years ago

A real life example that I am looking at now.

All of our servers globally run in their respective local time-zones. For various reasons, all our java apps run in UTC.

We have a single app that needs to trigger tasks at various market times. e.g. The New York Close is at 17:00 NY time. The New Zealand Open is at 8am Wellington time, etc. We also need the ability to configure these tasks to run periodically (mostly for testing purposes). So a cron sort of suits, as it can handle both.

So yes, we could look for specific times in the cron expression, and adjust them according to their Time Zone difference, but as OP suggested this would be cumbersome.

Would be awesome if we could just pass the Cron through and TZ's be taken care of.

jmrozanec commented 5 years ago

@benjwarner thank you for the example provided! We will prioritize this issue for next release. You are also welcome to contribute :smile: Thanks!

antrix190 commented 5 years ago

@jmrozanec Is this issue already taken? If not then i wish to work on it.

jmrozanec commented 5 years ago

@antrix190 work in it! We will be glad to merge your PR! Thanks! :smile:

antrix190 commented 5 years ago

Sure!

jmrozanec commented 5 years ago

@antrix190 any news on this issue? It would be great to close October with a new release including this feature :smile: May seem as trivial as to replace current cron values with the GMT offset of the target timezone, but may become tricky when a block of hours gets split into two dates or similar cases. I would try mapping a single expression into equivalent ones and perhaps deliver a multi-cron that would be equivalent to the original expression. If the multi-cron can be simplified, then we should do it.

antrix190 commented 5 years ago

Hey @jmrozanec I need sometime to close this issue.

jmrozanec commented 5 years ago

@antrix190 sure! Seems easy, but has lots of corner cases :) thanks!

jmrozanec commented 5 years ago

@antrix190 if you need some help, do not hesitate to reach out on this thread and share code from your fork. Will be glad to provide assistance! 😄

HerTesla commented 5 years ago

So what is the current status of this task?

antrix190 commented 5 years ago

@HerTesla you can take this up.

jmrozanec commented 5 years ago

@antrix190 perhaps do we have some code that can be reused? @HerTesla you are welcome to help with this!

fahmpeermoh commented 4 years ago

can i pick this..?

jmrozanec commented 4 years ago

@fahmpeermoh sure! Will be happy to merge!

fahmpeermoh commented 4 years ago

@jmrozanec Thank you.

jrphub commented 4 years ago

Thank you guys for following up this feature :)

jmrozanec commented 4 years ago

@fahmpeermoh any news on this?

aleskiontherun commented 4 years ago

The merged code doesn't work with multiple values in one field, e. g. 0 9,15,18 * * *. Also some tests do not pass due to daylight saving time offsets.

In our case we have some auto-generated Jenkins jobs, performing scheduled tasks, which need to be adjusted to daylight saving time in some time zones.

jmrozanec commented 4 years ago

@dizeee thank you for reporting this. May we ask you to point us the tests failing due to daylight savings in some timezones? This way we can fix them. If those are tests of your own, we would welcome them into our codebase, to ensure better quality. Thanks! 😄

aleskiontherun commented 4 years ago

@jmrozanec I'm talking about the tests in the pull request ;) https://github.com/jmrozanec/cron-utils/pull/400/files#diff-191b64506d58f9422b0b28100abfed44

dswitzer commented 4 years ago

First, thanks for the wonderful project!

I'm working on a web-based project that uses Quartz Scheduler. The servers and the web application all run in UTC. However, clients will need to see the cron schedule expression reflected in their time zone.

The new CronConverter() code seemed to be exactly what I needed. However, as @dizeee mentioned, some of the use cases do not work as expected. For example, I would expect the following code:

cronConverter
    .using("0 0/5 15-22 * * ?")
    .from(ZoneId.of("UTC"))
    .to(ZoneId.of("America/New_York"))
    .convert()
;

To produce the string:

0 0/5 10-17 * * ?

However, the returned string is the same as the input.

Is this something that's intended to work as I expect or am I misunderstanding the intentions?

dswitzer commented 4 years ago

Likewise, I'd expect:

cronConverter
    .using("0 0 17 * * ?")
    .from(ZoneId.of("UTC"))
    .to(ZoneId.of("America/New_York"))
    .convert()
;

To generate:

0 0 12 * * ?

But it's generating:

0 19 16 * * ?

Which is really wrong.

Gwynbleidd017 commented 4 years ago

Would this script help?

#!/usr/bin/python
import sys

difference_source_utc = 10
mode = sys.argv[1]
minute = sys.argv[2]
hour   = sys.argv[3]
days = sys.argv[-1].split(",")
days = map(int,days);
day_change = False

if(mode == "source-utc"):
    hour_result = int(hour) - difference_source_utc
if(mode == "utc-source"):
    hour_result = int(hour) + difference_source_utc

if(hour_result < 0):
    hour_result = hour_result + 24
    days_result = [(x-1)%7 for x in days]
elif(hour_result >= 24):
    hour_result = hour_result - 24
    days_result = [(x+1)%7 for x in days]
else:
    days_result = days

days_result_str = ','.join(map(str, days_result)) 
print minute , hour_result , "* *" , days_result_str

NOTE: Update difference_source_utc in the script to difference between your source and UTC. Example : For AEST it is 10.


Example 1:
Convert a local time to UTC.
./crontab-converter.py source-utc  30 08 * * 0,1,2                                                                                                                   
Result: 30 22 * * 6,0,1
Example 2:
Convert a UTC time to local.
./crontab-converter.py utc-source 30 22 * * 6,0,1                                                                                                                    
Result: 30 8 * * 0,1,2```
jmrozanec commented 4 years ago

@jarvis017 this script is helpful! We will try to translate ASAP into our code. Meanwhile, you are welcome to contribute as well! Thanks!

kakumasn commented 3 years ago

has this feature been added to cron-utils ?? or is it still open

jmrozanec commented 3 years ago

@kakumasn this feature was not added to cron-utils yet. Will do our best to include and test over next week. Will post an update when done and released.

saurabnigam commented 3 years ago

Hi Any updates on this

vishborade commented 3 years ago

Any update on this feature.

jmrozanec commented 3 years ago

@vishborade no updates 😄 If you have time, we will be glad to get some help on it. Thanks!

Haarolean commented 3 years ago

I don't get why everyone's struggling so much with this issue :) I personally think it will just complicate the whole thing, probably even add more bugs.

That's how I do timezone conversions:

Save your initial date in some timezone (like UTC) and calculate next launches with the same timezone, after that call ZonedDateTime#withZoneSameInstant(ZoneId) method and voilà, you've got your next launch with the timezone you need.

jmrozanec commented 3 years ago

@Haarolean can we wrap that into a method and a PR? 😄

Haarolean commented 3 years ago

@Haarolean can we wrap that into a method and a PR? 😄

Yeah, sure. Into the cron-utils-examples I suppose?

jmrozanec commented 3 years ago

@Haarolean that would be great 😄 Thanks!

Pablillo92 commented 5 months ago

Try this solution: https://www.npmjs.com/package/crontzconvert