Skip to content

Commit 958f3da

Browse files
author
Andrey Nudko
committed
Fix bug in handling schedules when EndTime < StartTime and are in different timezones
It was possible to end up in a state when interval end is >24 hours before interval start (this is some quirk of the j.u.Calendar which I don't fully understand - but order of calls to setTimeZone() and setTimeInMillis() somehow matters). Adding 1 day in this case is not enough, since resulting interval is still inverted. This patch addresses the problem by moving end timestamp forward as long as it is behind the start. #486
1 parent 0425600 commit 958f3da

File tree

2 files changed

+60
-1
lines changed

2 files changed

+60
-1
lines changed

quickfixj-core/src/main/java/quickfix/DefaultSessionSchedule.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,7 @@ private TimeInterval theMostRecentIntervalBefore(Calendar t) {
208208
intervalEnd.add(Calendar.DAY_OF_WEEK, -1);
209209
}
210210

211-
if (intervalEnd.getTimeInMillis() <= intervalStart.getTimeInMillis()) {
211+
while (intervalEnd.getTimeInMillis() <= intervalStart.getTimeInMillis()) {
212212
intervalEnd.add(Calendar.DAY_OF_WEEK, 1);
213213
}
214214

quickfixj-core/src/test/java/quickfix/SessionScheduleTest.java

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1404,4 +1404,63 @@ public void testSettingsWithStartEndDayWithDSTMockedUsingWeekdays() throws Excep
14041404
TimeZone.getTimeZone("America/New_York"));
14051405
}
14061406

1407+
// https://github.com/quickfix-j/quickfixj/issues/486
1408+
@Test
1409+
public void testSessionTimeEndBeforeStartUsingWeekdaysDifferentTimeZones() throws Exception {
1410+
SessionSettings settings = new SessionSettings();
1411+
settings.setString(Session.SETTING_START_TIME, "23:55:00 Europe/Madrid");
1412+
settings.setString(Session.SETTING_END_TIME, "17:05:00 America/New_York");
1413+
settings.setString(Session.SETTING_WEEKDAYS, "Sun,Mon,Tue,Wed,Thu");
1414+
1415+
mockSystemTimeSource.setTime(getTimeStamp(2008, Calendar.NOVEMBER, 2, 18, 0, 0, TimeZone.getTimeZone("America/New_York")));
1416+
1417+
SessionID sessionID = new SessionID("FIX.4.2", "SENDER", "TARGET");
1418+
SessionSchedule schedule = new DefaultSessionSchedule(settings, sessionID);
1419+
// Schedule should be (assuming daylight savings time):
1420+
// 23:55 Sunday Madrid to 17:05 Monday NY // 21:55 Sunday UTC to 21:05 Monday UTC
1421+
// 23:55 Monday Madrid to 17:05 Tuesday NY // 21:55 Monday UTC to 21:05 Tuesday UTC
1422+
// 23:55 Tuesday Madrid to 17:05 Wednesday NY // 21:55 Tuesday UTC to 21:05 Wednesday UTC
1423+
// 23:55 Wednesday Madrid to 17:05 Thursday NY // 21:55 Wednesday UTC to 21:05 Thursday UTC
1424+
// 23:55 Thursday Madrid to 17:05 Friday NY // 21:55 Thursday UTC to 21:05 Friday UTC
1425+
1426+
// Saturday
1427+
doIsSessionTimeTest(schedule, false, 2022, Calendar.APRIL, 16, 21, 0, 0); // 23:00 Madrid
1428+
doIsSessionTimeTest(schedule, false, 2022, Calendar.APRIL, 16, 22, 0, 0); // 00:00 Madrid next day
1429+
doIsSessionTimeTest(schedule, false, 2022, Calendar.APRIL, 16, 22, 1, 0); // 00:01 Madrid next day
1430+
doIsSessionTimeTest(schedule, false, 2022, Calendar.APRIL, 16, 23, 0, 0); // 01:00 Madrid next day
1431+
1432+
// Sunday
1433+
doIsSessionTimeTest(schedule, false, 2022, Calendar.APRIL, 17, 0, 1, 0); // 19:01 Madrid
1434+
doIsSessionTimeTest(schedule, false, 2022, Calendar.APRIL, 17, 21, 54, 59);// 23:54 Madrid
1435+
doIsSessionTimeTest(schedule, true, 2022, Calendar.APRIL, 17, 21, 55, 00); // 23:55 Madrid. Correct opening time
1436+
doIsSessionTimeTest(schedule, true, 2022, Calendar.APRIL, 17, 21, 57, 0); // 23:57 Madrid
1437+
doIsSessionTimeTest(schedule, true, 2022, Calendar.APRIL, 17, 22, 00, 0); // 00:00 Madrid next day.
1438+
doIsSessionTimeTest(schedule, true, 2022, Calendar.APRIL, 17, 23, 57, 0); // 01:57 Madrid next day.
1439+
1440+
// Monday
1441+
doIsSessionTimeTest(schedule, true, 2022, Calendar.APRIL, 18, 0, 1, 0); // 02:01 Madrid.
1442+
doIsSessionTimeTest(schedule, true, 2022, Calendar.APRIL, 18, 3, 0, 1); // 05:00 Madrid.
1443+
doIsSessionTimeTest(schedule, true, 2022, Calendar.APRIL, 18, 3, 59, 59); // 05:59 Madrid.
1444+
doIsSessionTimeTest(schedule, true, 2022, Calendar.APRIL, 18, 4, 00, 59); // 06:00 Madrid.
1445+
doIsSessionTimeTest(schedule, true, 2022, Calendar.APRIL, 18, 17, 00, 59); // 19:00 Madrid.
1446+
doIsSessionTimeTest(schedule, true, 2022, Calendar.APRIL, 18, 21, 00, 00); // 23:00 Madrid / 17:00 NY
1447+
doIsSessionTimeTest(schedule, true, 2022, Calendar.APRIL, 18, 21, 4, 59); // 23:04:59 Madrid / 17:04:59 NY
1448+
doIsSessionTimeTest(schedule, true, 2022, Calendar.APRIL, 18, 21, 5, 0); // 23:05:00 Madrid / 17:05 NY
1449+
doIsSessionTimeTest(schedule, false, 2022, Calendar.APRIL, 18, 21, 5, 1); // 23:05:01 Madrid / 17:05:01 NY. Correct close time
1450+
doIsSessionTimeTest(schedule, false, 2022, Calendar.APRIL, 18, 21, 54, 0); // 23:54:00 Madrid.
1451+
doIsSessionTimeTest(schedule, true, 2022, Calendar.APRIL, 18, 21, 55, 00); // 23:55 Madrid. Correct opening time
1452+
doIsSessionTimeTest(schedule, true, 2022, Calendar.APRIL, 18, 21, 57, 0); // 23:57 Madrid
1453+
doIsSessionTimeTest(schedule, true, 2022, Calendar.APRIL, 18, 22, 56, 0); //
1454+
doIsSessionTimeTest(schedule, true, 2022, Calendar.APRIL, 18, 23, 6, 0); //
1455+
doIsSessionTimeTest(schedule, true, 2022, Calendar.APRIL, 18, 23, 54, 0); //
1456+
doIsSessionTimeTest(schedule, true, 2022, Calendar.APRIL, 18, 23, 56, 0); //
1457+
// Tuesday
1458+
doIsSessionTimeTest(schedule, true, 2022, Calendar.APRIL, 19, 0, 1, 0); //
1459+
doIsSessionTimeTest(schedule, true, 2022, Calendar.APRIL, 19, 3, 0, 1); //
1460+
doIsSessionTimeTest(schedule, true, 2022, Calendar.APRIL, 19, 17, 00, 59);
1461+
doIsSessionTimeTest(schedule, true, 2022, Calendar.APRIL, 19, 21, 00, 00);
1462+
doIsSessionTimeTest(schedule, false, 2022, Calendar.APRIL, 19, 21, 6, 0);
1463+
doIsSessionTimeTest(schedule, false, 2022, Calendar.APRIL, 19, 21, 54, 0);
1464+
}
1465+
14071466
}

0 commit comments

Comments
 (0)