grahamar / cron-parser Goto Github PK
View Code? Open in Web Editor NEWJava Parser For Cron Expressions
License: MIT License
Java Parser For Cron Expressions
License: MIT License
In both 2.6 and 2.7, using 0 for Sunday gives an error, but using 7 for Sunday gives the expected output. Possibly a regression error, since I see support for 7 was added in 2.4.
Exception in thread "AWT-EventQueue-0" org.joda.time.IllegalFieldValueException: Value 0 for dayOfWeek must be in the range [1,7]
at org.joda.time.field.FieldUtils.verifyValueBounds(FieldUtils.java:215)
at org.joda.time.field.PreciseDurationDateTimeField.set(PreciseDurationDateTimeField.java:78)
at org.joda.time.chrono.ZonedChronology$ZonedDateTimeField.set(ZonedChronology.java:466)
at org.joda.time.DateTime.withDayOfWeek(DateTime.java:1748)
at net.redhogs.cronparser.DateAndTimeUtils.getDayOfWeekName(DateAndTimeUtils.java:47)
at net.redhogs.cronparser.builder.DayOfWeekDescriptionBuilder.getSingleItemDescription(DayOfWeekDescriptionBuilder.java:49)
at net.redhogs.cronparser.builder.AbstractDescriptionBuilder.getSegmentDescription(AbstractDescriptionBuilder.java:52)
at net.redhogs.cronparser.CronExpressionDescriptor.getDayOfWeekDescription(CronExpressionDescriptor.java:117)
at net.redhogs.cronparser.CronExpressionDescriptor.getFullDescription(CronExpressionDescriptor.java:235)
at net.redhogs.cronparser.CronExpressionDescriptor.getDescription(CronExpressionDescriptor.java:62)
at net.redhogs.cronparser.CronExpressionDescriptor.getDescription(CronExpressionDescriptor.java:27)
We've been using cron-parser in our product for more than three years. We recently extended our cron expressions with "standard" way of using offset as it is supported by more than one schedulers. Here is how drupal describes it:
https://www.drupal.org/node/1666964
The plus ('+') operator (called "offset") can be used as an offset to a given range. For example, "*/10+2" in the minute field is equivalent to "2,12,22,32,42,52".
As of now, cron parser considers above expression invalid and fails to parse it. Can you please consider extending the parser and support +M notation when it is coupled with */N expression as above?
Because of this it is not available in application servers like JBoss or Websphere out of the box. The cleanest solution is to use the Java class java.util.regex.Pattern which is the standard way to use regular expressions in Java.
Given
Options options = new Options();
options.setZeroBasedDayOfWeek( false );
options.setTwentyFourHourTime( true );
the description is At 00:00, only on Sunday, Sunday, Monday, Tuesday, Wednesday, Thursday and Friday, every year
expect ParseException to be thrown instead
Original .net library supports it.
See the following commit:
bradymholt/cron-expression-descriptor@f81065c
Method normaliseExpression in ExpressionParser.java
description: convert 0/, 1/ to /
expressionParts[0] = expressionParts[0].replace("0/", "
/") ; // seconds
does not check if the to be converted expression is whole and not in part - check that expression starts with 0/ and 1/ respectively
Fix:
expressionParts[0] = expressionParts[0].startsWith("0/") ? expressionParts[0].replace("0/", "*/") : expressionParts[0]; // seconds
Test Case:
@Test
public void testEveryXMinutePastTheHourWithInterval() throws Exception {
Assert.assertEquals("Every 2 minutes, minutes 00 through 30 past the hour, at 5:00 PM, Monday through Friday",
CronExpressionDescriptor.getDescription("0 0-30/2 17 ? * MON-FRI"));
}
Reproduced by:
@Test
public void infiniteLoop() {
Cron cron = new CronParser(CronDefinitionBuilder.instanceDefinitionFor(CronType.UNIX))
.parse("0 0 30 2 *");
ExecutionTime.forCron(cron).nextExecution(ZonedDateTime.now());
}
The expression "0 0,5,10,15,20,25,30,35,40,45,50,55 * ? * *"
becomes "At 00, 05, 10, 15, 20, 25, 30, 35, 40, 45, 50, and 55 minutes past the hour" (with a comma before the word "and"),
instead of "At 00, 05, 10, 15, 20, 25, 30, 35, 40, 45, 50 and 55 minutes past the hour"
This is just an example. Happens for all expression with more than 3 elements in the cron part.
Thanks for this port! Very useful! 😄
Since you are a library using slf4j you should not force your users to a specific slf4j implementation since this will create errors when they want to use a different one (like slf4j-simple).
You could easily fix that by changing the dependencies to scope test:
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>${slf4j.version}</version>
<scope>test</scope> // ADD THIS
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>${log4j.version}</version>
<scope>test</scope> // ADD THIS
</dependency>
I believe there is an issue with generating the textual description for CRON expressions that contains hour-range definiton - according to the tutorial and the documentation, the hour-range is inclusive, meaning that if we put an hour definition as 10-14, the cron will also run in 14 hour (or 2PM). However, the textual description generated says between 10:00 AM and 1:00 PM, which is not true and is actually confusing.
Attached please find the failing test case:
/**
* From QUARTZ tutorial (http://www.quartz-scheduler.org/documentation/quartz-2.x/tutorials/tutorial-lesson-06.html):
* CronTrigger Example 3 - an expression to create a trigger that fires at 10:30, 11:30, 12:30, and 13:30, on every Wednesday and Friday.
*
* Expected output (including 1PM):
* At 30 minutes past the hour, between 10:00 AM and 2:00 PM, only on Wednesday and Friday
*
* Actual output:
* At 30 minutes past the hour, between 10:00 AM and 1:00 PM, only on Wednesday and Friday
* @throws Exception
*/
@Test
public void shouldMatchQuartzCronTutorial() throws Exception {
Assert.assertEquals("At 30 minutes past the hour, between 10:00 AM and 2:00 PM, only on Wednesday and Friday", CronExpressionDescriptor.getDescription("0 30 10-13 ? * WED,FRI"));
}
Hi Guys,
First of all, kudos for all the great works in the very nice library.
Just wanted to know if we have any plan to support Japanese locale ?
Thank You
Harshad
For a schedule like 0 2 18 * * ?
If you have
Options cronOptions = new Options();
cronOptions.setZeroBasedDayOfWeek(false); //day of the week for quartz cron starts at 1 i.e. SUN
cronOptions.setTwentyFourHourTime(true);
String description = CronExpressionDescriptor.getDescription(cronString, cronOptions, Locale.ENGLISH);
it will display something like At 6:02 PM
. I would expect it to display something like "At 18:02". It does this for other locales e.g. it, de etc.
First thanks a lot for the library.
I tried the following expression
0 0,5,10,15,20,25,30,35,40,45,50,55 * ? * *
It seems to translate fine in the original library to
http://www.geekytidbits.com/cron-expression-descriptor-demo/Default.aspx
At 00, 05, 10, 15, 20, 25, 30, 35, 40, 45, 50, and 55 minutes past the hour
but i get a format exception:
java.lang.NumberFormatException: For input string: "0,5,10,15,20,25,30,35,40,45,50,55"
I should look at the code to give you a better report. I will. In the mean time, just a heads up, or maybe I am doing something wrong.
getTimeOfDayDescription(String[] expressionParts) in CronExpressionDescriptor .java
// Handle special cases first
line: 178 } else if (minutesExpression.contains("-") && !StringUtils.containsAny(hoursExpression, specialCharacters)) {
Above condition does not cater for cron expression "0 0-30/2 17 ? * MON-FRI"
It ignores that minute expression can also have '/' when condition 2 is true.
To reproduce see test case below.
The following additional check fixed the issue
} else if (minutesExpression.contains("-") && !minutesExpression.contains("/") && !StringUtils.containsAny(hoursExpression, specialCharacters)) {
Test case for the above [not sure if I have named it appropriately - please check]
@test
public void testEveryXMinutePastTheHourWithInterval() throws Exception {
Assert.assertEquals("Every 2 minutes, minutes 00 through 30 past the hour, at 5:00 PM, Monday through Friday",
CronExpressionDescriptor.getDescription("0 0-30/2 17 ? * MON-FRI"));
}
In my opinion this code can be improved if the special case handling is either removed by not having to code for special cases or by enhancing the special case scenarios. certainly if the parsing logic in description builders can handle the scenarios then special cases handling will not be required.
It prints:
At 7:00 AM, on the first Sunday of the month
Should be:
At 07:00 AM, on the first Saturday of the month
System.out.println(CronExpressionDescriptor.getDescription("0 0 7 ? * 7#1"));
Verify here:
https://www.freeformatter.com/cron-expression-generator-quartz.html
Thanks!
"0 0 2/4 * * ?" is parsed like "Every 4 hours". There is no "starting from 2.00am every day".
System.out.println(CronExpressionDescriptor.getDescription("0 */5 8-17 ? * *"));
The description is
Every 5 minutes, between 8:00 AM and 5:00 PM
It should be
Every 5 minutes, between 08:00 AM and 05:59 PM
- https://bradymholt.github.io/cron-expression-descriptor/
Or, even better, it should be
Every 5 minutes, between 8:00 AM and 5:55 PM
First thanks for sharing!
I'm using your library to translate a CRON expression to a human readable String and it works fine.
Here are some improvements that could be very useful (in my opinion):
When you specify more than one minute, or every minute, and the hour is 0 for midnight, an extra comma will be placed after the minutes:
5 0 * * * At 0:05 AM
5,10 0 * * * At 05 and 10 minutes past the hour,
5,10 0 2 * * At 05 and 10 minutes past the hour, , on day 2 of the month
5/10 0 2 * * Every 10 minutes, , on day 2 of the month
Time part from cron expression does not respect Locales whereas hour-part is 0-23h, not AM/PM.
Like in Spanish locale the hour-part from the cron-expression "0 15 16 ? * MON-FRI" should be "En 16:15, lunes hasta viernes", not "En 4:15 PM, lunes hasta viernes".
Few expressions below:
DateTimeFormat.forPattern("EEE").parseDateTime(WordUtils.capitalizeFully(exp)).dayOfWeek().getAsText(I18nMessages.getCurrentLocale());
uses the system Locale which is wrong, because the week days in Cron Expressions are always in English. Therefore the Locale should be fixed to English:
DateTimeFormat.forPattern("EEE").withLocale(Locale.ENGLISH).parseDateTime(WordUtils.capitalizeFully(exp)).dayOfWeek().getAsText(I18nMessages.getCurrentLocale());
1、add chinese locale supporting
2、Chinese, Japanese, Korean and other East Asian languages have no spaces between words,add needSpaceBetweenWords option
(添加中文的本地文件支持,因为中文每个字之间没有空格,在“and”等连词前后去掉空格)
Exception during parsing "0 0/30 0-6,10-23 * * ? *"
java.lang.NumberFormatException: For input string: "6,10" at java.lang.NumberFormatException.forInputString(Unknown Source) ~[na:1.8.0_77] at java.lang.Integer.parseInt(Unknown Source) ~[na:1.8.0_77] at java.lang.Integer.parseInt(Unknown Source) ~[na:1.8.0_77] at net.redhogs.cronparser.DateAndTimeUtils.formatTime(DateAndTimeUtils.java:33) ~[cron-parser-2.6.jar!/:na] at net.redhogs.cronparser.DateAndTimeUtils.formatTime(DateAndTimeUtils.java:23) ~[cron-parser-2.6.jar!/:na] at net.redhogs.cronparser.builder.HoursDescriptionBuilder.getSingleItemDescription(HoursDescriptionBuilder.java:16) ~[cron-parser-2.6.jar!/:na] at net.redhogs.cronparser.builder.AbstractDescriptionBuilder.getSegmentDescription(AbstractDescriptionBuilder.java:36) ~[cron-parser-2.6.jar!/:na] at net.redhogs.cronparser.CronExpressionDescriptor.getHoursDescription(CronExpressionDescriptor.java:174) ~[cron-parser-2.6.jar!/:na] at net.redhogs.cronparser.CronExpressionDescriptor.getTimeOfDayDescription(CronExpressionDescriptor.java:211) ~[cron-parser-2.6.jar!/:na] at net.redhogs.cronparser.CronExpressionDescriptor.getFullDescription(CronExpressionDescriptor.java:232) ~[cron-parser-2.6.jar!/:na] at net.redhogs.cronparser.CronExpressionDescriptor.getDescription(CronExpressionDescriptor.java:62) ~[cron-parser-2.6.jar!/:na] at net.redhogs.cronparser.CronExpressionDescriptor.getDescription(CronExpressionDescriptor.java:39) ~[cron-parser-2.6.jar!/:na] at net.redhogs.cronparser.format.CronExpressionFormatter.print(CronExpressionFormatter.java:45) ~[cron-parser-spring-2.8.jar!/:na]
It should work in that way
http://cronexpressiondescriptor.azurewebsites.net/?Language=en-US&DayOfWeekStartIndexOne=false&Use24HourFormat=false&VerboseDescription=false&Expression=0+0%2F30+0-6%2C10-23+*+*+%3F+*
A problem that some cron expressions historically get their day of the week to start from 1 (Sunday=1, Monday=2,...Saturday=7). It is totally out of a regular way of cron expressions.
cron-parser currently expects values to be 0 based, which is how it should be (http://en.wikipedia.org/wiki/Cron), day of the week is 0 based.
Is there any way to make that configurable?
Using Tuesday as day of the week is translated into Monday
12 * * ? 3 Tue --> At 12 seconds past the minute, only on Tuesday, only in March
12 * * ? 3 Tuesday --> At 12 seconds past the minute, only on Monday, only in March
The tests below fail, because , elk jaar
is appended to the timestamp Om 11:40 AM
making Om 11:40 AM, elk jaar
(At 11:40 AM, every year) which doesn't make sense because "elke dag" (every day) is missing. I would expect something like Om 11:40 AM, elke dag, elk jaar
(At 11:40 AM, every day, every year) or just Om 11:40 AM
// expected:<Om 11:40 AM[]> but was:<Om 11:40 AM[, elk jaar]>
Assert.assertEquals("Om 11:40 AM", CronExpressionDescriptor.getDescription("0 40 11 1/1 * ? *", DUTCH));
Assert.assertEquals("Om 11:40 AM", CronExpressionDescriptor.getDescription("0 40 11 * * ? *", DUTCH));
Currently only a 5-pos expression is tested in testDailyAtTime()
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.