time-rs/time

Solve "large-dates" ambiguity

dennisorlando opened this issue · 13 comments

Hi,
bson enables the "large-dates" feature, which means that when you add it to your crate, everything that parsed some time::PrimitiveDateTimes using the plain version of time will potentially break, due to some documented ambiguities.
Is it possible to provide a way to solve those ambiguity, so that we don't have to change our program in order to handle different date-time formats?
Maybe a way to provide the number of characters dedicated to the [year] value?

This is the datetime which causes problems when "large-dates" is enabled:
20240602205731Z

This is related to #650. After some thought, I should be able to add a modifier whose value would control whether the extended range can be used. This is what I want eventually anyway; the only difference would be that the default has to be backwards-compatible (essentially opt-out instead of opt-in).

I recently ran into this exact problem with the simple_asn1 crate when attempting to use bson in the same binary.

Upstream issue: acw/simple_asn1#34

This problem is ultimately the root cause of this issue in the arti-client crate (when bson crate is also present): https://gitlab.torproject.org/tpo/core/arti/-/issues/1632

@morganava Feel free to create a pull request if you are able. Otherwise you'll be waiting on me to eventually get around to this (and there is no time frame).

@jhpratt would the acceptable solution be to make an explicit [short-year] (or some other better name) format specifier which forces years into the range -9999 to 9999 even if time/large-dates is enabled?

The solution would be what I described in a previous comment. Basically it would be a modifier rather than its own component.

What do you mean by modifier? This -> https://docs.rs/modifier ?

@dennisorlando See the current reference, which contains terminology and all current supported syntax.

https://time-rs.github.io/book/api/format-description.html

Minimal reproducable example, which panics when "large-dates" is enabled:

use time::{macros::format_description, PrimitiveDateTime};


fn main() {
    let format = format_description!("[year][month][day][hour][minute][second]");
    let datetime = PrimitiveDateTime::parse("20240602205731", format).unwrap();
    println!("{}", datetime);
}

Anyways: I'm currently working on this. Is this new modifier suitable? I.e. an explicit 4 digit modifier?

#[non_exhaustive]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum YearRepr {
    /// The full value of the year.
    Full,
    /// Standard 4 digit format, to be used when `large-dates` feature is enabled
    Four,
    /// Only the last two digits of the year.
    LastTwo,
}