Skip to content

Commit

Permalink
Fix bug in handling schedules when EndTime < StartTime and are in dif…
Browse files Browse the repository at this point in the history
…ferent 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.

quickfix-j#486
  • Loading branch information
Andrey Nudko committed Nov 18, 2022
1 parent 0425600 commit 958f3da
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ private TimeInterval theMostRecentIntervalBefore(Calendar t) {
intervalEnd.add(Calendar.DAY_OF_WEEK, -1);
}

if (intervalEnd.getTimeInMillis() <= intervalStart.getTimeInMillis()) {
while (intervalEnd.getTimeInMillis() <= intervalStart.getTimeInMillis()) {
intervalEnd.add(Calendar.DAY_OF_WEEK, 1);
}

Expand Down
59 changes: 59 additions & 0 deletions quickfixj-core/src/test/java/quickfix/SessionScheduleTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -1404,4 +1404,63 @@ public void testSettingsWithStartEndDayWithDSTMockedUsingWeekdays() throws Excep
TimeZone.getTimeZone("America/New_York"));
}

// https://github.com/quickfix-j/quickfixj/issues/486
@Test
public void testSessionTimeEndBeforeStartUsingWeekdaysDifferentTimeZones() throws Exception {
SessionSettings settings = new SessionSettings();
settings.setString(Session.SETTING_START_TIME, "23:55:00 Europe/Madrid");
settings.setString(Session.SETTING_END_TIME, "17:05:00 America/New_York");
settings.setString(Session.SETTING_WEEKDAYS, "Sun,Mon,Tue,Wed,Thu");

mockSystemTimeSource.setTime(getTimeStamp(2008, Calendar.NOVEMBER, 2, 18, 0, 0, TimeZone.getTimeZone("America/New_York")));

SessionID sessionID = new SessionID("FIX.4.2", "SENDER", "TARGET");
SessionSchedule schedule = new DefaultSessionSchedule(settings, sessionID);
// Schedule should be (assuming daylight savings time):
// 23:55 Sunday Madrid to 17:05 Monday NY // 21:55 Sunday UTC to 21:05 Monday UTC
// 23:55 Monday Madrid to 17:05 Tuesday NY // 21:55 Monday UTC to 21:05 Tuesday UTC
// 23:55 Tuesday Madrid to 17:05 Wednesday NY // 21:55 Tuesday UTC to 21:05 Wednesday UTC
// 23:55 Wednesday Madrid to 17:05 Thursday NY // 21:55 Wednesday UTC to 21:05 Thursday UTC
// 23:55 Thursday Madrid to 17:05 Friday NY // 21:55 Thursday UTC to 21:05 Friday UTC

// Saturday
doIsSessionTimeTest(schedule, false, 2022, Calendar.APRIL, 16, 21, 0, 0); // 23:00 Madrid
doIsSessionTimeTest(schedule, false, 2022, Calendar.APRIL, 16, 22, 0, 0); // 00:00 Madrid next day
doIsSessionTimeTest(schedule, false, 2022, Calendar.APRIL, 16, 22, 1, 0); // 00:01 Madrid next day
doIsSessionTimeTest(schedule, false, 2022, Calendar.APRIL, 16, 23, 0, 0); // 01:00 Madrid next day

// Sunday
doIsSessionTimeTest(schedule, false, 2022, Calendar.APRIL, 17, 0, 1, 0); // 19:01 Madrid
doIsSessionTimeTest(schedule, false, 2022, Calendar.APRIL, 17, 21, 54, 59);// 23:54 Madrid
doIsSessionTimeTest(schedule, true, 2022, Calendar.APRIL, 17, 21, 55, 00); // 23:55 Madrid. Correct opening time
doIsSessionTimeTest(schedule, true, 2022, Calendar.APRIL, 17, 21, 57, 0); // 23:57 Madrid
doIsSessionTimeTest(schedule, true, 2022, Calendar.APRIL, 17, 22, 00, 0); // 00:00 Madrid next day.
doIsSessionTimeTest(schedule, true, 2022, Calendar.APRIL, 17, 23, 57, 0); // 01:57 Madrid next day.

// Monday
doIsSessionTimeTest(schedule, true, 2022, Calendar.APRIL, 18, 0, 1, 0); // 02:01 Madrid.
doIsSessionTimeTest(schedule, true, 2022, Calendar.APRIL, 18, 3, 0, 1); // 05:00 Madrid.
doIsSessionTimeTest(schedule, true, 2022, Calendar.APRIL, 18, 3, 59, 59); // 05:59 Madrid.
doIsSessionTimeTest(schedule, true, 2022, Calendar.APRIL, 18, 4, 00, 59); // 06:00 Madrid.
doIsSessionTimeTest(schedule, true, 2022, Calendar.APRIL, 18, 17, 00, 59); // 19:00 Madrid.
doIsSessionTimeTest(schedule, true, 2022, Calendar.APRIL, 18, 21, 00, 00); // 23:00 Madrid / 17:00 NY
doIsSessionTimeTest(schedule, true, 2022, Calendar.APRIL, 18, 21, 4, 59); // 23:04:59 Madrid / 17:04:59 NY
doIsSessionTimeTest(schedule, true, 2022, Calendar.APRIL, 18, 21, 5, 0); // 23:05:00 Madrid / 17:05 NY
doIsSessionTimeTest(schedule, false, 2022, Calendar.APRIL, 18, 21, 5, 1); // 23:05:01 Madrid / 17:05:01 NY. Correct close time
doIsSessionTimeTest(schedule, false, 2022, Calendar.APRIL, 18, 21, 54, 0); // 23:54:00 Madrid.
doIsSessionTimeTest(schedule, true, 2022, Calendar.APRIL, 18, 21, 55, 00); // 23:55 Madrid. Correct opening time
doIsSessionTimeTest(schedule, true, 2022, Calendar.APRIL, 18, 21, 57, 0); // 23:57 Madrid
doIsSessionTimeTest(schedule, true, 2022, Calendar.APRIL, 18, 22, 56, 0); //
doIsSessionTimeTest(schedule, true, 2022, Calendar.APRIL, 18, 23, 6, 0); //
doIsSessionTimeTest(schedule, true, 2022, Calendar.APRIL, 18, 23, 54, 0); //
doIsSessionTimeTest(schedule, true, 2022, Calendar.APRIL, 18, 23, 56, 0); //
// Tuesday
doIsSessionTimeTest(schedule, true, 2022, Calendar.APRIL, 19, 0, 1, 0); //
doIsSessionTimeTest(schedule, true, 2022, Calendar.APRIL, 19, 3, 0, 1); //
doIsSessionTimeTest(schedule, true, 2022, Calendar.APRIL, 19, 17, 00, 59);
doIsSessionTimeTest(schedule, true, 2022, Calendar.APRIL, 19, 21, 00, 00);
doIsSessionTimeTest(schedule, false, 2022, Calendar.APRIL, 19, 21, 6, 0);
doIsSessionTimeTest(schedule, false, 2022, Calendar.APRIL, 19, 21, 54, 0);
}

}

0 comments on commit 958f3da

Please sign in to comment.