Run a cron job every 5 minute only on specific hours? - spring

I want to run some cronjob between monday-friday at 23.50 and 23.55. I tried some expressions but there is something wrong with my expression.
0 50/5 23-00 ? * MON-FRI
When I calculate next days with cronmaker it shows;
1. Tuesday, March 15, 2016 11:50 PM
2. Tuesday, March 15, 2016 11:55 PM
3. Wednesday, March 16, 2016 12:50 AM
4. Wednesday, March 16, 2016 12:55 AM
5. Wednesday, March 16, 2016 11:50 PM
Why it shows AM? I only specified 23-00 hours?

It should be 0 50/5 23 ? * MON-FRI
'-' specifies range. So, 0 50/5 23-00 ? * MON-FRI means 11pm to 12am

12:50 AM is the same as 00:50 or 24:50. 50 minutes after midnight. Since the hour is 00 and the minute 50 it matches your cron expression.

0 50/5 23-00 ? * MON-FRI
it can be write as below may fullfill your requirement
0 50/5 23 * * 1-5 ?
explain 1-5 means 1 = monday
... 5 = Friday
note: sunday = 0 or 7

Related

Why doesn't TimeSerial compute a correct value for negative second value?

Just facing a new weird behavior (or bug) in VBScript:
WScript.Echo TimeSerial(0, 0, 15)
WScript.Echo TimeSerial(0, 0, -15)
WScript.Echo TimeSerial(1, 0, 15)
WScript.Echo TimeSerial(1, 0, -15)
WScript.Echo TimeSerial(1, 1, 15)
WScript.Echo TimeSerial(1, 1, -15)
outputs:
00:00:15
00:00:15 <- shouldn't be 23:59:45?
01:00:15
00:59:45 <- OK.
01:01:15
01:00:45 <- OK.
Why such unexpected output?
Help only says:
However, you can also specify relative times for each argument using any numeric expression that represents some number of hours, minutes, or seconds before or after a certain time.
There is a bug/issue here, but not with the part you suspect.
The issue here is that the function that converts the underlying variant value to a string does not correctly handle the negative numbers.
The value of the TimeSerial result, however, is correct, but converting it to a string, isn't.
The TimeSerial function only promises to return something that is a time if you provide valid time values, so 0-23 for hour and 0-59 for minutes and seconds. If you start using negative numbers you end up with a relative value, and this part is apparently not handled correctly when converting the result to a string.
As an example:
WScript.Echo CDbl(TimeSerial(1, 0, -15))*24
WScript.Echo 1-15/(60*60)
gives the same output:
0,995833333333333
0,995833333333333
let's include the time you wanted to have:
WScript.Echo CDbl(TimeSerial(0, 59, 45))*24
which also gives:
0,995833333333333
And your second example:
WScript.Echo CDbl(TimeSerial(0, 0, -15))*24
WScript.Echo -15/(60*60)
gives:
-4,16666666666667E-03
-4,16666666666667E-03
As you can see, you get back a negative value, not a time.
It may be worth using a different method to provide a relative offset for seconds, you should be able to accomplish this using DateAdd() and passing a -15 then use TimeValue() to return just the time part.
Dim dt: dt = DateAdd("s", -15, TimeSerial(0, 0, 0))
WScript.Echo TimeValue(dt)
Output:
23:59:45
This is an interesting one it does seem to be a bug with relative seconds. Did a quick test that loops through 24 hours in 15 minute periods and subtracts 15 seconds each time and the results apart from the 00:00:00 are correct so a weird bug with midnight?
Option Explicit
Const hours = 24
Const minutes = 60
Const min_offset = 15
Const sec_offset = -15
Dim h, m, s
For h = 0 To hours - 1
For m = 0 To minutes - 1 Step min_offset
WScript.Echo TimeSerial(h, m, s)
WScript.Echo TimeSerial(h, m, sec_offset)
Next
Next
Output:
00:00:00
00:00:15
00:15:00
00:14:45
00:30:00
00:29:45
00:45:00
00:44:45
01:00:00
00:59:45
01:15:00
01:14:45
01:30:00
01:29:45
01:45:00
01:44:45
02:00:00
01:59:45
02:15:00
02:14:45
02:30:00
02:29:45
02:45:00
02:44:45
03:00:00
02:59:45
03:15:00
03:14:45
03:30:00
03:29:45
03:45:00
03:44:45
04:00:00
03:59:45
04:15:00
04:14:45
04:30:00
04:29:45
04:45:00
04:44:45
05:00:00
04:59:45
05:15:00
05:14:45
05:30:00
05:29:45
05:45:00
05:44:45
06:00:00
05:59:45
06:15:00
06:14:45
06:30:00
06:29:45
06:45:00
06:44:45
07:00:00
06:59:45
07:15:00
07:14:45
07:30:00
07:29:45
07:45:00
07:44:45
08:00:00
07:59:45
08:15:00
08:14:45
08:30:00
08:29:45
08:45:00
08:44:45
09:00:00
08:59:45
09:15:00
09:14:45
09:30:00
09:29:45
09:45:00
09:44:45
10:00:00
09:59:45
10:15:00
10:14:45
10:30:00
10:29:45
10:45:00
10:44:45
11:00:00
10:59:45
11:15:00
11:14:45
11:30:00
11:29:45
11:45:00
11:44:45
12:00:00
11:59:45
12:15:00
12:14:45
12:30:00
12:29:45
12:45:00
12:44:45
13:00:00
12:59:45
13:15:00
13:14:45
13:30:00
13:29:45
13:45:00
13:44:45
14:00:00
13:59:45
14:15:00
14:14:45
14:30:00
14:29:45
14:45:00
14:44:45
15:00:00
14:59:45
15:15:00
15:14:45
15:30:00
15:29:45
15:45:00
15:44:45
16:00:00
15:59:45
16:15:00
16:14:45
16:30:00
16:29:45
16:45:00
16:44:45
17:00:00
16:59:45
17:15:00
17:14:45
17:30:00
17:29:45
17:45:00
17:44:45
18:00:00
17:59:45
18:15:00
18:14:45
18:30:00
18:29:45
18:45:00
18:44:45
19:00:00
18:59:45
19:15:00
19:14:45
19:30:00
19:29:45
19:45:00
19:44:45
20:00:00
19:59:45
20:15:00
20:14:45
20:30:00
20:29:45
20:45:00
20:44:45
21:00:00
20:59:45
21:15:00
21:14:45
21:30:00
21:29:45
21:45:00
21:44:45
22:00:00
21:59:45
22:15:00
22:14:45
22:30:00
22:29:45
22:45:00
22:44:45
23:00:00
22:59:45
23:15:00
23:14:45
23:30:00
23:29:45
23:45:00
23:44:45

Using Apple Foundation Calendar properly

I'm a little bit confused about the correct usage of Calendar of Apple Foundations framework.
let calendar = Calendar(identifier: .iso8601)
let dayComponent = DateComponents(year: 2019, weekday: 1, weekOfYear: 6)
let date = calendar.date(from: dayComponent)
I need to get the first day of a given week of year. When using the code above the following dates are given depending on weekday:
//weekday:
//0 -> 08 FEB
//1 -> 09 FEB
//2 -> 03 FEB
//3 -> 04 FEB
//4 -> 05 FEB
Why does weekday starts with 0 at the current week (6) while switching to week 5 when increased?
Thanks for any help.
A couple of observations:
When iterate through weekdays, you want to go from 1 through 7, because, “Day, week, weekday, month, and year numbers are generally 1-based...” Date and Time Programming Guide: Date Components and Calendar Units. You can use range(of:in:for:), maximumRange(of:), etc., to find the range of possible values.
The weekday values from 1 through 7 do not mean “first day of the week”, “second day of the week”, etc. They refer to specific days of the week, e.g. for .iso8601, “Sun” is 1, “Mon” is 2, etc.
Make sure when you use weekOfYear, you use yearForWeekOfYear:
let calendar = Calendar(identifier: .iso8601)
let firstOfWeek = DateComponents(calendar: calendar, weekOfYear: 6, yearForWeekOfYear: 2019).date!
Your code is iterating through the weekdays. Consider this code that enumerates all of the days of the week for the sixth week of 2019 (i.e. the week starting Monday, February 4th and ending Sunday, February 10th):
let weekdays = calendar.range(of: .weekday, in: .weekOfYear, for: firstOfWeek)!
let daysOfTheWeek = Dictionary(uniqueKeysWithValues: zip(weekdays, calendar.weekdaySymbols))
for weekday in weekdays {
let date = DateComponents(calendar: calendar, weekday: weekday, weekOfYear: 6, yearForWeekOfYear: 2019).date!
print("The", daysOfTheWeek[weekday]!, "in the 6th week of 2019 is", formatter.string(from: date))
}
That results in:
The Sun in the 6th week of 2019 is Sunday, February 10, 2019
The Mon in the 6th week of 2019 is Monday, February 4, 2019
The Tue in the 6th week of 2019 is Tuesday, February 5, 2019
The Wed in the 6th week of 2019 is Wednesday, February 6, 2019
The Thu in the 6th week of 2019 is Thursday, February 7, 2019
The Fri in the 6th week of 2019 is Friday, February 8, 2019
The Sat in the 6th week of 2019 is Saturday, February 9, 2019
This is effectively what your code does and why you’re not seeing what you expected.
If you want iterate through the seven days of the week in order, just get the start of the week and then offset it from there:
let calendar = Calendar(identifier: .iso8601)
let startOfWeek = DateComponents(calendar: calendar, weekOfYear: 6, yearForWeekOfYear: 2019).date!
for offset in 0 ..< 7 {
let date = calendar.date(byAdding: .day, value: offset, to: startOfWeek)!
print(offset, "->", formatter.string(from: date))
}
That results in:
0 -> Monday, February 4, 2019
1 -> Tuesday, February 5, 2019
2 -> Wednesday, February 6, 2019
3 -> Thursday, February 7, 2019
4 -> Friday, February 8, 2019
5 -> Saturday, February 9, 2019
6 -> Sunday, February 10, 2019
You asked:
I need to get the first day of a given week of year.
Probably needless to say at this point, but just omit the weekday:
let startOfWeek = DateComponents(calendar: calendar, weekOfYear: 6, yearForWeekOfYear: 2019).date!
Also see Date and Time Programming Guide: Week-Based Calendars.

How do I create a cron expression running in Kibana on weekday?

I would like my watcher to run from Monday to Friday only. So I'm trying to use this schedule:
"trigger": {
"schedule" : { "cron" : "0 0 0/4 * * MON-FRI" }
},
"input": {
...
However, I'm getting
Error
Watcher: [parse_exception] could not parse [cron] schedule
when I'm trying to save the watcher. Removing MON-FRI does helps but I need it.
This expression works:
0 0 0/4 ? * MON-FRI
But I'm not sure I understand why ? is required for either the day_of_week or day_of_month
Thank you!
I believe this is what you are looking for:
"0 0 0/4 ? * MON-FRI"
You can use croneval to check your cron expressions 1:
$ /usr/share/elasticsearch/bin/x-pack/croneval "0 0 0/4 ? * MON-FRI"
Valid!
Now is [Mon, 20 Aug 2018 13:32:26]
Here are the next 10 times this cron expression will trigger:
1. Mon, 20 Aug 2018 09:00:00
2. Mon, 20 Aug 2018 13:00:00
3. Mon, 20 Aug 2018 17:00:00
4. Mon, 20 Aug 2018 21:00:00
5. Tue, 21 Aug 2018 01:00:00
6. Tue, 21 Aug 2018 05:00:00
7. Tue, 21 Aug 2018 09:00:00
8. Tue, 21 Aug 2018 13:00:00
9. Tue, 21 Aug 2018 17:00:00
10. Tue, 21 Aug 2018 21:00:00
For the first expression you'll get following java exception:
java.lang.IllegalArgumentException: support for specifying both a day-of-week AND a day-of-month parameter is not implemented.
You can also use Crontab guru to get human readable descriptions like:
At every minute past every 4th hour from 0 through 23 on every day-of-week from Monday through Friday.
The question mark means 'No Specific value'. From the documentation on Quartz's website:
? (“no specific value”) - useful when you need to specify something in one of the two fields in which the character is allowed, but not the other. For example, if I want my trigger to fire on a particular day of the month (say, the 10th), but don’t care what day of the week that happens to be, I would put “10” in the day-of-month field, and “?” in the day-of-week field. See the examples below for clarification.
http://www.quartz-scheduler.org/documentation/quartz-2.x/tutorials/crontrigger.html
I suppose since you want your schedule to run every 4 hours, mon-fri, the actual day of the month is irrelevant, so the ? specifies that. * on teh other hand would be 'all values' which would not make sense since you are specifying only mon-fri for day of the week.
Hope that helps!

empty match in Regex

I've made the following regex with case insenstive \i
(([a-z]+(\s*-\s*[a-z]+)?)\:)\s*(\d{1,2}:\d{1,2}\s*[ap]m\s*-\s*\d{1,2}:\d{1,2}\s*[ap]m)
for this kind of input
Mon - Fri: 10:00 am - 8:00 pm
Sat: 10:00 am - 7:00 pm
Sun: 12:00 am - 5:00 pm
but I am getting these matches
Match 1
1. Mon - Fri:
2. Mon - Fri
3. - Fri
4. 10:00 am - 8:00 pm
Match 2
1. Sat:
2. Sat
3.
4. 10:00 am - 7:00 pm
Match 3
1. Sun:
2. Sun
3.
4. 12:00 am - 5:00 pm
why am I getting the 3rd (empty and "-Fri") matches?
you can play around with this in http://rubular.com/r/M4a1Jnnyrm
In order not to see that, just make the group non-capturing ((?:\s*\-\s*[A-Za-z]+)?):
(([A-Za-z]+(?:\s*\-\s*[A-Za-z]+)?)\:)\s*(\d{1,2}:\d{1,2}\s*[ap]m\s*-\s*\d{1,2}:\d{1,2}\s*[ap]m)
I'd even say that the 2nd group can also be non-capturing:
((?:[a-z]+(?:\s*-\s*[a-z]+)?)\:)\s*(\d{1,2}:\d{1,2}\s*[ap]m\s*-\s*\d{1,2}:\d{1,2}\s*[ap]m)
Now, it is much cleaner, with just 2 groups.
Because in this Mon - Fri: 10:00 am - 8:00 pm input, your optional third capturing group (\s*-\s*[a-z]+)? matches the - Fri part. For the others Sat: 10:00 am - 7:00 pm, there isn't a second part (the hyphen part) of string to capture like in the first string. So the third group returns an empty match for string 2 and 3.
The 3rd matches are captured by the group (\s*-\s*[a-z]+)
You can use a non-capturing group to omit the 3rd match group e.g.
(([a-z]+(?:\s*-\s*[a-z]+)?)\:)\s*(\d{1,2}:\d{1,2}\s*[ap]m\s*-\s*\d{1,2}:\d{1,2}\s*[ap]m)

algorithm for calculating a week # from a date with custom start of week? (for iCal)

I can only find algorithm for getting ISO 8601 week (week starts on a Monday).
However, the iCal spec says
A week is defined as a seven day period, starting on the day of the
week defined to be the week start (see WKST). Week number one of the
calendar year is the first week that contains at least four (4) days
in that calendar year.
Therefore, it is more complex than ISO 8601 since the start of week can be any day of the week.
Is there an algorithm to determine what is the week number of a date, with a custom start day of week?
or... is there a function in iCal4j that does this? Determine a weekno from a date?
Thanks!
p.s. Limitation: I'm using a JVM language that cannot extend a Java class, but I can invoke Java methods or instantiate Java classes.
if (input_date < firstDateOfTheYear(WKST, year))
{
return ((isLeapYear(year-1))?53:52);
}
else
{
return ((dayOfYear(input_date) - firstDateOfTheYear(WKST, year).day)/7 + 1);
}
firstDateOfTheYear returns the first calendar date given a start of week(WKST) and the year, e.g. if WKST = Thursday, year = 2012, then it returns Jan 5th.
dayOfYear returns sequencial numerical day of the year, e.g. Feb 1st = 32
Example #1: Jan 18th, 2012, start of week is Monday
dayOfYear(Jan 18th, 2012) = 18
firstDateOfTheYear(Monday, 2012) = Jan 2nd, 2012
(18 - 2)/7 + 1 = 3
Answer Week no. 3
Example #2: Jan 18th, 2012, start of week is Thursday
dayOfYear(Jan 18th, 2012) = 18
firstDateOfTheYear(Thursday, 2012) = Jan 5th, 2012
(18 - 5)/7 + 1 = 2
Answer Week no. 2
Example #3: Jan 1st, 2012, start of week is Monday
firstDateOfTheYear(Monday, 2012) = Jan 2nd, 2012
IsLeapYear(2012-1) = false
Jan 1st, 2012 < Jan 2nd, 2012
Answer Week no. 52
Let daysInFirstWeek be the number of days on the first week of the year that are in January. Week starts on a WKST day. (e.g. if Jan 1st is a WKST day, return 7)
Set dayOfYear to the n-th days of the input date's year (e.g. Feb 1st = 32)
If dayOfYear is less than or equal to daysInFirstWeek
3.1. if daysInFirstWeek is greater than or equal to 4, weekNo is 1, skip to step 5.
3.2. Let daysInFirstWeekOfLastYear be the number of days on the first week of the previous year that are in January. Week starts on a WKST day.
3.3. if daysInFirstWeekOfLastYear is 4 or last year is Leap year and daysInFirstWeekOfLastYear is 5, weekNo is 53, otherwise weekNo is 52, skip to step 5.
Set weekNo to ceiling((dayOfYear - daysInFirstWeek) / 7)
4.1. if daysInFirstWeek greater than or equal to 4, increment weekNo by 1
4.2. if daysInFirstWeek equal 53 and count of days on the first week (starting from WKST) of January in the year of inputDate's year + 1 is greater than or equal to 4, set weekNo to 1
return weekNo

Resources