-
Notifications
You must be signed in to change notification settings - Fork 183
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
Update ixdtf
to handle unbound fraction length
#6036
base: main
Are you sure you want to change the base?
Conversation
ixdtf
to handle unbound fraction length
utils/ixdtf/src/parsers/records.rs
Outdated
pub enum Fraction { | ||
/// Parsed nanoseconds value (A fraction value from 1-9 digits length) | ||
Nanoseconds(u64), | ||
/// Parsed picoseconds value (A fraction value from 10-12 digits length) | ||
Picoseconds(u64), | ||
/// Parsed femtoseconds value (A fraction value from 12-15 digits length) | ||
Femtoseconds(u64), | ||
/// A parsed value truncated to nanoseconds (A fraction value of 15+ digits length) | ||
Truncated(u64), // An unbound fraction value truncated to nanoseconds | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Suggestion: change this to
pub struct Fraction {
fraction_digits: u8,
value: u64,
}
and then give it functions such as
impl Fraction {
pub fn try_to_nanoseconds(self) -> Option<u64> {
if self.fraction_digits <= 9 {
// compute the pow and return
} else {
None
}
}
pub fn to_truncated_nanoseconds(self) -> u64 {
// compute pow, either + or -
}
}
Another future advantage of this model is that the Fraction can directly return a FixedDecimal, which could make fractional second formatting more efficient in icu4x.
components/timezone/src/ixdtf.rs
Outdated
@@ -42,6 +42,8 @@ pub enum ParseError { | |||
InconsistentTimeZoneOffsets, | |||
/// There was an invalid Offset. | |||
InvalidOffsetError, | |||
/// There was an invalid subsecond fraction. | |||
InvalidFraction, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is overkill. I'd rather document that sub-nanoseconds are truncated. The formatting code only supports nanosecond precision anyway.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If not, I'd prefer naming this
/// The string contains precision that is not representable by the output type.
ExcessivePrecision
InvalidFraction
is what I'd expect for a string like "12:48:16.a0", which already produces Syntax
.
components/timezone/src/ixdtf.rs
Outdated
let Some(nanosecond) = self.time.fraction.to_nanoseconds() else { | ||
return Err(ParseError::InvalidFraction); | ||
}; | ||
let time = Time::try_new( | ||
self.time.hour, | ||
self.time.minute, | ||
self.time.second, | ||
self.time.nanosecond, | ||
nanosecond, | ||
)?; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ideally there'd only be one code path that parses the IXDTF struct into Time
, and it should be Time::try_from_ixdtf_record
. Please try to use that (also for Date
ideally).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I updated Time
with a try_from_time_record
method to address this.
I'm not entirely clear what you had meant by also "for Date
ideally." Unless the idea was to expose two methods: Time::try_from_time_record
and Date::try_from_date_record
on the referenced types. So if you were thinking of that or a bit of a different approach, let me know.
utils/ixdtf/src/error.rs
Outdated
@@ -46,6 +46,8 @@ pub enum ParseError { | |||
TimeSecond, | |||
#[displaydoc("Invalid character while parsing fraction part value.")] | |||
FractionPart, | |||
#[displaydoc("Fraction part value exceeds a representable range.")] | |||
InvalidFractionRange, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"Invalid" is not very descriptive. This is an error, that already tells me that something is not valid.
InvalidFractionRange, | |
ExcessiveSecondPrecision, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was double checking this and the error is specific to a Duration hour fraction and minute fraction potentially exceeding the range of u64::MAX
when calculated. Maybe DurationFractionExceededRange
(this would then be moved down into the Duration errors).
This PR updates
ixdtf
's fraction handling to parse fraction values beyond 9 digits in length per feedback from #6004.It introduces a new enum
Fraction
in place of the previousnanosecond
field that allows parsing fraction values beyond 9 digits while preserving the precision in the enum.It also adds a variety of tests to test the new behavior while adjusting tests from the old behavior to the new behavior