summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/datetime.rs32
-rw-r--r--src/month.rs2
-rw-r--r--src/tai.rs6
-rw-r--r--src/timezone.rs8
4 files changed, 39 insertions, 9 deletions
diff --git a/src/datetime.rs b/src/datetime.rs
index 9332de1..49506e3 100644
--- a/src/datetime.rs
+++ b/src/datetime.rs
@@ -30,6 +30,16 @@ impl<Tz: TimeZone> DateTime<Tz> {
}
}
+ pub fn from_local(local_datetime: NaiveDateTime, timezone: Tz) -> Result<Self, Tz::Err> {
+ let offset = timezone.offset_from_local_naive(local_datetime)?;
+ // TODO overflow
+ let utc_datetime = local_datetime
+ .add_seconds_overflowing(-offset.seconds_ahead() as i64)
+ .0;
+
+ Ok(Self::from_utc(utc_datetime, timezone))
+ }
+
pub fn offset(&self) -> UtcOffset {
let utc = self.as_utc();
self.timezone.utc_offset(utc)
@@ -69,6 +79,26 @@ impl<Tz: TimeZone> DateTime<Tz> {
pub fn tai_timestamp(&self) -> UnixTimestamp {
self.as_tai().to_naive_overflowing().0.timestamp()
}
+
+ #[must_use]
+ pub fn add_seconds_overflowing(self, seconds: i64) -> (Self, bool) {
+ let (tai_timestamp, overflow) = self.tai_timestamp().add_seconds_overflowing(seconds);
+ let tai_naive_dt = NaiveDateTime::from_timestamp(tai_timestamp);
+ let tai_dt = DateTime::from_local(tai_naive_dt, Tai).unwrap();
+
+ (tai_dt.into_timezone(self.timezone), overflow)
+ }
+
+ #[must_use]
+ pub fn add_nanoseconds_overflowing(self, nanoseconds: i64) -> (Self, bool) {
+ let (tai_timestamp, overflow) = self
+ .tai_timestamp()
+ .add_nanoseconds_overflowing(nanoseconds);
+ let tai_naive_dt = NaiveDateTime::from_timestamp(tai_timestamp);
+ let tai_dt = DateTime::from_local(tai_naive_dt, Tai).unwrap();
+
+ (tai_dt.into_timezone(self.timezone), overflow)
+ }
}
impl NaiveDateTime {
@@ -285,7 +315,7 @@ impl<Tz: TimeZone, Other: TimeZone> PartialEq<DateTime<Other>> for DateTime<Tz>
}
impl<Tz: TimeZone> Hash for DateTime<Tz> {
- fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
+ fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
self.utc_datetime.hash(state);
}
}
diff --git a/src/month.rs b/src/month.rs
index 1419717..faf891d 100644
--- a/src/month.rs
+++ b/src/month.rs
@@ -405,7 +405,7 @@ impl Month {
let zero_indexed_month = zero_indexed_num % 12;
let month = match Self::from_u8((zero_indexed_month as u8) + 1) {
Some(month) => month,
- None => unsafe { std::hint::unreachable_unchecked() },
+ None => unsafe { core::hint::unreachable_unchecked() },
};
(month, wraps)
diff --git a/src/tai.rs b/src/tai.rs
index 8dd91d2..015e70e 100644
--- a/src/tai.rs
+++ b/src/tai.rs
@@ -83,7 +83,7 @@ impl TimeZone for Tai {
}
// TODO optimize
- fn offset_from_local_time(&self, date_time: NaiveDateTime) -> Result<UtcOffset, Self::Err> {
+ fn offset_from_local_naive(&self, date_time: NaiveDateTime) -> Result<UtcOffset, Self::Err> {
// TAI times cannot have leap seconds
if date_time.second() == 60 {
return Err(UnexpectedLeapSecond {
@@ -120,7 +120,7 @@ mod tests {
#[test]
fn test_conversion_no_leap_seconds() {
let offset = unsafe {
- Tai.offset_from_local_time(NaiveDateTime::new(
+ Tai.offset_from_local_naive(NaiveDateTime::new(
Date::from_ymd_unchecked(2000.into(), Month::January, 1),
Time::from_hms_unchecked(0, 0, 0),
))
@@ -134,7 +134,7 @@ mod tests {
fn test_conversion_one_leap_second() {
add_leap_second(unsafe { Date::from_ymd_unchecked(2000.into(), Month::January, 1) });
let offset = unsafe {
- Tai.offset_from_local_time(NaiveDateTime::new(
+ Tai.offset_from_local_naive(NaiveDateTime::new(
Date::from_ymd_unchecked(2000.into(), Month::January, 2),
Time::from_hms_unchecked(0, 0, 0),
))
diff --git a/src/timezone.rs b/src/timezone.rs
index f0096c6..eb539fb 100644
--- a/src/timezone.rs
+++ b/src/timezone.rs
@@ -5,7 +5,7 @@ use core::fmt::Display;
/// A type that can be used to represent a `TimeZone`
pub trait TimeZone: Sized + Eq + Display {
/// The error to return in case of a failure to convert the local time to UTC
- type Err;
+ type Err: core::fmt::Debug;
/// Given the time in the UTC timezone, determine the `UtcOffset`
fn utc_offset(&self, date_time: DateTime<Utc>) -> UtcOffset;
@@ -16,7 +16,7 @@ pub trait TimeZone: Sized + Eq + Display {
///
/// This returns an Err if the given `NaiveDateTime` cannot exist in this timezone.
/// For example, the time may have been skipped because of daylight savings time.
- fn offset_from_local_time(&self, date_time: NaiveDateTime) -> Result<UtcOffset, Self::Err>;
+ fn offset_from_local_naive(&self, date_time: NaiveDateTime) -> Result<UtcOffset, Self::Err>;
}
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
@@ -30,7 +30,7 @@ impl TimeZone for Utc {
UtcOffset::UTC
}
- fn offset_from_local_time(&self, _: NaiveDateTime) -> Result<UtcOffset, Self::Err> {
+ fn offset_from_local_naive(&self, _: NaiveDateTime) -> Result<UtcOffset, Self::Err> {
Ok(UtcOffset::UTC)
}
}
@@ -121,7 +121,7 @@ impl TimeZone for UtcOffset {
*self
}
- fn offset_from_local_time(&self, _: NaiveDateTime) -> Result<UtcOffset, Self::Err> {
+ fn offset_from_local_naive(&self, _: NaiveDateTime) -> Result<UtcOffset, Self::Err> {
Ok(*self)
}
}