Skip to content

Commit

Permalink
use datetime.fold to distinguish ambiguous datetimes when converting
Browse files Browse the repository at this point in the history
  • Loading branch information
bschoenmaeckers committed Dec 13, 2024
1 parent 603a55f commit 1861f3b
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 6 deletions.
1 change: 1 addition & 0 deletions newsfragments/4791.fixed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
use `datetime.fold` to distinguish ambiguous datetimes when converting to `chrono::DateTime<Tz>`
27 changes: 21 additions & 6 deletions src/conversions/chrono.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,8 @@ use crate::{intern, DowncastError};
use crate::{IntoPy, ToPyObject};
use chrono::offset::{FixedOffset, Utc};
use chrono::{
DateTime, Datelike, Duration, NaiveDate, NaiveDateTime, NaiveTime, Offset, TimeZone, Timelike,
DateTime, Datelike, Duration, LocalResult, NaiveDate, NaiveDateTime, NaiveTime, Offset,
TimeZone, Timelike,
};

#[allow(deprecated)]
Expand Down Expand Up @@ -503,12 +504,26 @@ impl<Tz: TimeZone + for<'py> FromPyObject<'py>> FromPyObject<'_> for DateTime<Tz
));
};
let naive_dt = NaiveDateTime::new(py_date_to_naive_date(dt)?, py_time_to_naive_time(dt)?);
naive_dt.and_local_timezone(tz).single().ok_or_else(|| {
PyValueError::new_err(format!(
"The datetime {:?} contains an incompatible or ambiguous timezone",
match naive_dt.and_local_timezone(tz) {
LocalResult::Single(value) => Ok(value),
LocalResult::Ambiguous(earliest, latest) => {
#[cfg(not(Py_LIMITED_API))]
let fold = dt.get_fold();

#[cfg(Py_LIMITED_API)]
let fold = dt.getattr(intern!(dt.py(), "fold"))?.extract::<usize>()? > 0;

if fold {
Ok(latest)
} else {
Ok(earliest)
}
}
LocalResult::None => Err(PyValueError::new_err(format!(
"The datetime {:?} contains an incompatible timezone",
dt
))
})
))),
}
}
}

Expand Down

0 comments on commit 1861f3b

Please sign in to comment.