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

Make conversion from NaiveDateTime to DateTime easier #687

Closed
gerritsangel opened this issue May 7, 2022 · 1 comment · Fixed by #711
Closed

Make conversion from NaiveDateTime to DateTime easier #687

gerritsangel opened this issue May 7, 2022 · 1 comment · Fixed by #711

Comments

@gerritsangel
Copy link

Hello,

I noticed that the conversion from a NaiveDateTime to a DateTime by supplying a TimeZone is not really as easy as it could be (or IDE-friendly).

Mostly, I think the problem is that you have the conversion method on the TimeZone trait, instead of on the NaiveDateTime object. At least speaking for myself, if I want to convert a NaiveDateTime, I already have one (e.g. because I manually parsed it from somewhere without Time information) and then just want to supply the TimeZone object. As a normal developer, I would just press . on the object and hope that my IDE will display me a suitable method.

Therefore, what about something like this?

impl NaiveDateTime {
    pub fn to_datetime_local<Tz: TimeZone>(&self, tz: Tz) -> LocalResult<DateTime<Tz>> {
        tz.from_local_datetime(self)
    }
}

This makes it really obvious how to construct a DateTime from a NaiveDateTime:

#[test]
fn test_naivedatetime_to_local() {
    let offset = FixedOffset::east(3600);
    let dt = NaiveDate::from_ymd(2022,05,07).and_hms(14,51,00)
        .to_datetime_local(offset);
    assert_eq!("2022-05-07T14:51:00+01:00", dt.single().unwrap().to_rfc3339());
}

Furthermore, while the LocalResult is of course correct, I think it would be nice to have some kind of "lossy" output. I would assume that most of the time there is only one result (as the DST transitions are mostly in the night anyway, where they have the least impact). Currently the user has to handle this situation every time, while most of the time the conversion will be correct. Anyway, I think it would be good for a time library to have some sensible default how to work with this, as not every user might know what to do in this case.

I checked on the Java time API, and they handle it like this (https://docs.oracle.com/javase/8/docs/api/java/time/LocalDateTime.html#atZone-java.time.ZoneId-):

In most cases, there is only one valid offset for a local date-time. In the case of an overlap, where clocks are set back, there are two valid offsets. This method uses the earlier offset typically corresponding to "summer".

In the case of a gap, where clocks jump forward, there is no valid offset. Instead, the local date-time is adjusted to be later by the length of the gap. For a typical one hour daylight savings change, the local date-time will be moved one hour later into the offset typically corresponding to "summer".

To obtain the later offset during an overlap, call ZonedDateTime.withLaterOffsetAtOverlap() on the result of this method. To throw an exception when there is a gap or overlap, use ZonedDateTime.ofStrict(LocalDateTime, ZoneOffset, ZoneId).

Why not create an additional method on LocalResult which returns something like the Java handling (not quite sure how other time libraries handle this situation)?

@botahamec
Copy link
Contributor

I'll work on the first issue, but the second part of this should probably be moved to its own issue. Would you like to make a new one? It's a complicated problem that I think would require a breaking change.

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

Successfully merging a pull request may close this issue.

2 participants