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

Rewrite Interval.parse(CharSequence) #242

Open
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

perceptron8
Copy link
Contributor

@perceptron8 perceptron8 commented Dec 11, 2022

This is an attempt to make Interval parsing more readable and (hopefully) less error prone. I believe that proposed way of splitting code into methods makes much more sense than before. At least one bug was fixed. At the same time, parsing became a little more flexible.


The bug was caused by the following:

long move = end.isBefore(Instant.EPOCH) ? 1000 * 86400 : -1000 * 86400;
Instant start = end.plusSeconds(move).atOffset(ZoneOffset.UTC).minus(amount).toInstant().minusSeconds(move);
long move = start.isBefore(Instant.EPOCH) ? 1000 * 86400 : -1000 * 86400;
Instant end = start.plusSeconds(move).atOffset(ZoneOffset.UTC).plus(amount).toInstant().minusSeconds(move);

It looks like author's intention was to move instant 1000 days towards Instant.EPOCH. First, it is not exactly 1000 days - it's approximately 1000 days. What's important is that it can (but doesn't have to) move instant into month with different number of days. I decided to use leap year cycle length (which is fixed) to avoid this kind of problems.

Without this fix, not a single test covered by org.threeten.extra.TestInterval.data_parse_outside_bounds(String, String, String) is going to pass. For instance -1000000000-01-31T00:00:00Z/P1M should be parsed to interval ending at -02-29, not -03-02 and for -1000000000-01-31T00:00:00Z/P2M interval's end should be -03-31 instead of -04-01 .

There are still some cases that this rewrite doesn't fix. All of them involve duration. Please, see org.threeten.extra.TestInterval.data_parse_crossing_bounds(String, String, String) (intervals starting within date-time bounds, with duration making them end outside of it) and org.threeten.extra.TestInterval.data_parse_crossing_bounds_twice(String, String, String) (intervals starting before OffsetDateTime.MIN and ending after OffsetDateTime.MAX because of duration). Maybe someone will be interested in making these tests pass - for now, they are disabled.


As I mentioned, parsing became a little more flexible. It is now possible to parse `OffsetDateTime/LocalDateTime` and `LocalDateTime/OffsetDateTime` (previously only `OffsetDateTime/LocalDateTime` was supported). It seems to be valid according to spec, at least if Wiki can be trusted.

For <start>/<end> expressions, if any elements are missing from the end value, they are assumed to be the same as for the start value including the time zone
(https://en.wikipedia.org/wiki/ISO_8601#Time_intervals)

Edit: I must have misread something. If desired, I can easily revert old behavior.


Probably related: #80.

@perceptron8 perceptron8 changed the title rewrite Interval.parse(CharSequence) Rewrite Interval.parse(CharSequence) Dec 11, 2022
@perceptron8
Copy link
Contributor Author

LocalDateTime/OffsetDateTime format is illegal again. Sorry for the confusion!

@perceptron8
Copy link
Contributor Author

@jodastephen Almost 4 months later, this PR is still ready to review... ;)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

2 participants