Skip to content

Commit 21dfdbb

Browse files
committed
fix(test): Fix CronConverterTest that failed on Standard Time
- America/St_Johns UTC-3:30 Standard Time - America/St_Johns UTC-2:30 Daylight Time
1 parent d31697e commit 21dfdbb

File tree

2 files changed

+107
-80
lines changed

2 files changed

+107
-80
lines changed

src/main/java/com/cronutils/converter/CronConverter.java

Lines changed: 54 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -13,71 +13,75 @@
1313

1414
package com.cronutils.converter;
1515

16+
import com.cronutils.utils.StringUtils;
1617
import org.slf4j.Logger;
1718
import org.slf4j.LoggerFactory;
1819

1920
import java.time.ZoneId;
2021
import java.util.Calendar;
2122
import java.util.TimeZone;
22-
23-
import com.cronutils.utils.StringUtils;
23+
import java.util.function.Function;
2424

2525
public class CronConverter {
2626

27-
private static final Logger LOGGER = LoggerFactory.getLogger(CronConverter.class);
27+
private static final Logger LOGGER = LoggerFactory.getLogger(CronConverter.class);
28+
private static final Function<ZoneId, Calendar> DEFAULT_CALENDAR_FACTORY = (zoneId) -> Calendar.getInstance(TimeZone.getTimeZone(zoneId));
29+
30+
private static final String CRON_FIELDS_SEPARATOR = " ";
31+
private String[] cronParts;
32+
private Calendar fromCalendar;
33+
private String sourceCron;
34+
private ZoneId sourceZoneId;
35+
private ZoneId targetZoneId;
2836

29-
private static final String CRON_FIELDS_SEPARATOR = " ";
30-
private String[] cronParts;
31-
private Calendar fromCalendar;
32-
private String sourceCron;
33-
private ZoneId sourceZoneId;
34-
private ZoneId targetZoneId;
37+
private CronToCalendarTransformer toCalendarConverter;
38+
private CalendarToCronTransformer toCronConverter;
3539

36-
private CronToCalendarTransformer toCalendarConverter;
37-
private CalendarToCronTransformer toCronConverter;
40+
private Function<ZoneId, Calendar> calendarFactory;
3841

39-
public CronConverter(CronToCalendarTransformer toCalendarConverter, CalendarToCronTransformer toCronConverter){
40-
this.toCalendarConverter = toCalendarConverter;
41-
this.toCronConverter = toCronConverter;
42-
}
42+
public CronConverter(CronToCalendarTransformer toCalendarConverter, CalendarToCronTransformer toCronConverter) {
43+
this(toCalendarConverter, toCronConverter, DEFAULT_CALENDAR_FACTORY);
44+
}
4345

44-
public CronConverter using(String cronExpression) {
45-
this.sourceCron = cronExpression;
46-
cronParts = cronExpression.split(CRON_FIELDS_SEPARATOR);
47-
LOGGER.debug("Cron '{}' split into {}", cronExpression, cronParts);
48-
return this;
49-
}
46+
public CronConverter(CronToCalendarTransformer toCalendarConverter, CalendarToCronTransformer toCronConverter, Function<ZoneId, Calendar> calendarFactory) {
47+
this.toCalendarConverter = toCalendarConverter;
48+
this.toCronConverter = toCronConverter;
49+
this.calendarFactory = calendarFactory;
50+
}
5051

51-
public CronConverter from(ZoneId zoneId) {
52-
sourceZoneId = zoneId;
53-
fromCalendar = getCalendar(zoneId);
54-
toCalendarConverter.apply(cronParts, fromCalendar);
55-
LOGGER.debug("Calendar object built using cron :{} and zoneID {} => {}",
56-
cronParts, zoneId, fromCalendar);
57-
return this;
58-
}
52+
public CronConverter using(String cronExpression) {
53+
this.sourceCron = cronExpression;
54+
cronParts = cronExpression.split(CRON_FIELDS_SEPARATOR);
55+
LOGGER.debug("Cron '{}' split into {}", cronExpression, cronParts);
56+
return this;
57+
}
5958

60-
public CronConverter to(ZoneId zoneId) {
61-
targetZoneId = zoneId;
62-
Calendar toCalendar = getCalendar(zoneId);
63-
toCalendar.setTimeInMillis(fromCalendar.getTimeInMillis());
64-
LOGGER.debug(
65-
"Calendar object built from calendar {} and zoneID {} => {}",
66-
fromCalendar, zoneId, toCalendar);
67-
toCronConverter.apply(cronParts, toCalendar);
68-
LOGGER.debug("cron after applying calendar {} => {}", toCalendar,
69-
cronParts);
70-
return this;
71-
}
59+
public CronConverter from(ZoneId zoneId) {
60+
sourceZoneId = zoneId;
61+
fromCalendar = calendarFactory.apply(zoneId);
62+
toCalendarConverter.apply(cronParts, fromCalendar);
63+
LOGGER.debug("Calendar object built using cron :{} and zoneID {} => {}",
64+
cronParts, zoneId, fromCalendar);
65+
return this;
66+
}
7267

73-
public String convert() {
74-
String targetCron = StringUtils.join(cronParts, CRON_FIELDS_SEPARATOR);
75-
LOGGER.info("Converted CRON -- {} :[{}] => {} :[{}]", sourceZoneId,
76-
sourceCron, targetZoneId, targetCron);
77-
return targetCron;
78-
}
68+
public CronConverter to(ZoneId zoneId) {
69+
targetZoneId = zoneId;
70+
Calendar toCalendar = calendarFactory.apply(zoneId);
71+
toCalendar.setTimeInMillis(fromCalendar.getTimeInMillis());
72+
LOGGER.debug(
73+
"Calendar object built from calendar {} and zoneID {} => {}",
74+
fromCalendar, zoneId, toCalendar);
75+
toCronConverter.apply(cronParts, toCalendar);
76+
LOGGER.debug("cron after applying calendar {} => {}", toCalendar,
77+
cronParts);
78+
return this;
79+
}
7980

80-
private Calendar getCalendar(ZoneId id) {
81-
return Calendar.getInstance(TimeZone.getTimeZone(id));
82-
}
81+
public String convert() {
82+
String targetCron = StringUtils.join(cronParts, CRON_FIELDS_SEPARATOR);
83+
LOGGER.info("Converted CRON -- {} :[{}] => {} :[{}]", sourceZoneId,
84+
sourceCron, targetZoneId, targetCron);
85+
return targetCron;
86+
}
8387
}

src/test/java/com/cronutils/converter/CronConverterTest.java

Lines changed: 53 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -13,44 +13,67 @@
1313

1414
package com.cronutils.converter;
1515

16+
import org.junit.jupiter.api.Test;
1617
import org.junit.jupiter.params.ParameterizedTest;
1718
import org.junit.jupiter.params.provider.Arguments;
1819
import org.junit.jupiter.params.provider.MethodSource;
1920

2021
import java.time.ZoneId;
22+
import java.util.Calendar;
23+
import java.util.GregorianCalendar;
24+
import java.util.TimeZone;
25+
import java.util.function.Function;
2126
import java.util.stream.Stream;
2227

2328
import static org.junit.jupiter.api.Assertions.assertEquals;
24-
import static org.mockito.Mockito.spy;
2529

2630
public class CronConverterTest {
27-
private CronConverter cronConverter = spy(new CronConverter(
28-
new CronToCalendarTransformer(),
29-
new CalendarToCronTransformer()
30-
));
31-
32-
public static Stream<Arguments> cronExpressions() {
33-
return Stream.of(Arguments.of("Pacific/Pago_Pago", "15 * * * *", "15 * * * *"),
34-
Arguments.of("Antarctica/Casey", "? * * * *", "? * * * *"),
35-
Arguments.of("Antarctica/Troll", "45 * * * *", "45 * * * *"),
36-
Arguments.of("Pacific/Chatham", "15 * * * *", "30 * * * *"),
37-
Arguments.of("Asia/Colombo", "45 * * ? *", "15 * * ? *"),
38-
Arguments.of("Asia/Colombo", "0/45 * * ? *", "0/45 * * ? *"),
39-
Arguments.of("Australia/Eucla", "13 * * ? *", "28 * * ? *"),
40-
Arguments.of("America/St_Johns", "0 0/15 * * * ?", "30 0/15 * * * ?"),
41-
Arguments.of("America/St_Johns", "0 8 * * ?", "30 10 * * ?"),
42-
Arguments.of("America/St_Johns", "0 0/1 * * ?", "30 0/1 * * ?"),
43-
Arguments.of("America/St_Johns", "20 0 * * ?", "50 2 * * ?"),
44-
Arguments.of("Asia/Kolkata", "20 0 * * ?", "50 18 * * ?")
45-
);
46-
}
47-
48-
@ParameterizedTest
49-
@MethodSource("cronExpressions")
50-
public void testCronConverterBuilder(String timezone, String inputCronExpression, String expectedCronExpression) {
51-
assertEquals(expectedCronExpression,
52-
cronConverter.using(inputCronExpression)
53-
.from(ZoneId.of(timezone)).to(ZoneId.of("UTC"))
54-
.convert());
55-
}
31+
32+
// Fix the date to prevent test failure during the transition between Standard Time and Daylight Time.
33+
Function<ZoneId, Calendar> calendarFactory = (zoneId) -> {
34+
Calendar fixedDay = new GregorianCalendar(2020, 06, 01);
35+
fixedDay.setTimeZone(TimeZone.getTimeZone(zoneId));
36+
return fixedDay;
37+
};
38+
39+
private CronConverter cronConverter = new CronConverter(
40+
new CronToCalendarTransformer(),
41+
new CalendarToCronTransformer(),
42+
calendarFactory
43+
);
44+
45+
public static Stream<Arguments> cronExpressions() {
46+
return Stream.of(Arguments.of("Pacific/Pago_Pago", "15 * * * *", "15 * * * *"),
47+
Arguments.of("Antarctica/Casey", "? * * * *", "? * * * *"),
48+
Arguments.of("Antarctica/Troll", "45 * * * *", "45 * * * *"),
49+
Arguments.of("Pacific/Chatham", "15 * * * *", "30 * * * *"),
50+
Arguments.of("Asia/Colombo", "45 * * ? *", "15 * * ? *"),
51+
Arguments.of("Asia/Colombo", "0/45 * * ? *", "0/45 * * ? *"),
52+
Arguments.of("Australia/Eucla", "13 * * ? *", "28 * * ? *"),
53+
Arguments.of("America/St_Johns", "0 0/15 * * * ?", "30 0/15 * * * ?"),
54+
Arguments.of("America/St_Johns", "0 8 * * ?", "30 10 * * ?"),
55+
Arguments.of("America/St_Johns", "0 0/1 * * ?", "30 0/1 * * ?"),
56+
Arguments.of("America/St_Johns", "20 0 * * ?", "50 2 * * ?"),
57+
Arguments.of("Asia/Kolkata", "20 0 * * ?", "50 18 * * ?")
58+
);
59+
}
60+
61+
@ParameterizedTest
62+
@MethodSource("cronExpressions")
63+
public void testCronConverterBuilder(String timezone, String inputCronExpression, String expectedCronExpression) {
64+
assertEquals(expectedCronExpression,
65+
cronConverter.using(inputCronExpression)
66+
.from(ZoneId.of(timezone)).to(ZoneId.of("UTC"))
67+
.convert());
68+
}
69+
70+
@Test
71+
public void testCronExpressionsDefaultTimeFactory() {
72+
CronConverter defaultCronConverter = new CronConverter(new CronToCalendarTransformer(), new CalendarToCronTransformer());
73+
// No Daylight Time @ Kolkata
74+
assertEquals("50 18 * * ?",
75+
defaultCronConverter.using("20 0 * * ?")
76+
.from(ZoneId.of("Asia/Kolkata")).to(ZoneId.of("UTC"))
77+
.convert());
78+
}
5679
}

0 commit comments

Comments
 (0)