Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix!: Fix a TimeRange off-by-one bug in nanosecond calculation #5648

Merged
merged 7 commits into from
Aug 28, 2024

Conversation

chipkent
Copy link
Member

@chipkent chipkent commented Jun 21, 2024

Fix a TimeRange off-by-one bug in nanosecond calculation.

Resolves #5646

BREAKING CHANGE: The length of a business day was being incorrectly computed by 1 ns. To keep the business day length the same for existing calendars, the close of a business period has been changed from inclusive to exclusive. This default behavior can be overridden by using <includeClose>true</includeClose> when specifying time ranges. This will include the closing time for the range and will result in a business period that is 1 ns longer. Business calendars using the legacy format must be upgraded to the current format to use <includeClose>true</includeClose>.

@chipkent chipkent added bug Something isn't working query engine labels Jun 21, 2024
@chipkent chipkent added this to the June 2024 milestone Jun 21, 2024
@chipkent chipkent self-assigned this Jun 21, 2024
@chipkent chipkent changed the title bug: Fix a TimeRange off-by-one bug in nanosecond calculation fix: Fix a TimeRange off-by-one bug in nanosecond calculation Jun 21, 2024
@chipkent
Copy link
Member Author

By default calendars are created with inclusive ranges. This fix will make the trading day 1 ns longer, unless we decide to make it exclusive.

…e. This makes the trading day the expected length instead of being 1 ns longer.
@@ -262,7 +262,7 @@ private static TimeRange<LocalTime>[] parseBusinessRanges(final List<Element> bu

final LocalTime open = DateTimeUtils.parseLocalTime(openTxt);
final LocalTime close = DateTimeUtils.parseLocalTime(closeTxt);
rst[i] = new TimeRange<>(open, close, true);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wasn't this set to true so that "23:59:59.999999999" would include the last nanosecond in the day?

Right now, it looks like we can't represent a full day?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I seem to recall some discussion involving DHE? Maybe Japan business day, or some other international concerns?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right that there may have been a UTC discussion. I'll look at that case.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The fix in there allows UTC to be supported correctly with full 24 hour days. It also gives users control over how to count the close times.

… of a range. This allows UTC calendars to be supported and gives users configuration options.
@@ -262,7 +270,8 @@ private static TimeRange<LocalTime>[] parseBusinessRanges(final List<Element> bu

final LocalTime open = DateTimeUtils.parseLocalTime(openTxt);
final LocalTime close = DateTimeUtils.parseLocalTime(closeTxt);
rst[i] = new TimeRange<>(open, close, true);
final boolean inclusiveEnd = Boolean.parseBoolean(includeCloseTxt); // defaults to false
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should use true by default to match our previous behavior? (and fix the test cases by setting to false where appropriate...)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

true really doesn't match the prior behavior. It yields a business time that is 1 ns longer. false is closer to the prior behavior.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The TimeRange#nanos being incorrect doesn't before doesn't change the fact that up until now, callers might be relying on parsing returning io.deephaven.time.calendar.TimeRange#isInclusiveEnd as true.

Also, does this code path get hit when parsing a "legacy" calendar file?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've asked DHE to take a look at how this effects them.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good question on the legacy path.

These are the key parts for the legacy parsing of TimeRange:

The "legacy" and "new" TimeRange formats are parsed separately, so we could handle them differently if we want to. Currently, legacy has inclusiveEnd=true. This will result in a trading day that is 1ns longer than the current implementation, so in this case, I also advocate for setting inclusiveEnd=false so that the business day length does not change. The legacy format for time ranges is not pure XML, so adding in inclusive controls is a little more messy, and I would prefer to avoid it.

I'm going to commit the inclusiveEnd=false change for legacy, and I'm adding @rbasralian for thoughts on these changes since he deals with calendars.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The PR description has been updated to reflect the breaking change.

@chipkent chipkent changed the title fix: Fix a TimeRange off-by-one bug in nanosecond calculation fix!: Fix a TimeRange off-by-one bug in nanosecond calculation Jun 25, 2024
@pete-petey pete-petey modified the milestones: June 2024, Backlog Aug 26, 2024
Copy link
Contributor

@rbasralian rbasralian left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me.

Not strictly related to this change, but It would be nice to have comments around multi and multi2 in TestCalendarDay.testMultiPeriod; the 1 and 2 ns offsets were a bit tough to follow. Just something along the lines of // multi/multi2 are constructed from periods inclusive of the ends, so each period includes an extra nanosecond

(And I guess the point of multi2 is that it sorts the periods you create it with, so it's equivalent to multi?)

@devinrsmith devinrsmith added the ReleaseNotesNeeded Release notes are needed label Aug 27, 2024
@chipkent chipkent enabled auto-merge (squash) August 27, 2024 21:13
@devinrsmith devinrsmith removed the NoReleaseNotesNeeded No release notes are needed. label Aug 27, 2024
@chipkent chipkent added ReleaseNotesNeeded Release notes are needed and removed ReleaseNotesNeeded Release notes are needed labels Aug 28, 2024
@chipkent chipkent merged commit e75b192 into deephaven:main Aug 28, 2024
15 checks passed
@chipkent chipkent deleted the timerange_off_by_one branch August 28, 2024 15:39
@github-actions github-actions bot locked and limited conversation to collaborators Aug 28, 2024
@deephaven-internal
Copy link
Contributor

Labels indicate documentation is required. Issues for documentation have been opened:

Community: deephaven/deephaven-docs-community#302

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Calendar TimeRange has an off-by-one error in nanosecond calculation
5 participants