Skip to content

Commit

Permalink
Implement ZonedDateTime::offset and `ZonedDateTime::offset_nanoseco…
Browse files Browse the repository at this point in the history
…nds` (#185)

Per title, this implements the accessor methods for returning
`ZonedDateTime`'s offset and offsetNanoseconds values.
  • Loading branch information
nekevss authored Feb 4, 2025
1 parent f7d0500 commit e9448cc
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 1 deletion.
16 changes: 16 additions & 0 deletions src/builtins/compiled/zoneddatetime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,22 @@ impl ZonedDateTime {

self.millisecond_with_provider(&*provider)
}

/// Returns the current offset as a formatted offset string.
pub fn offset(&self) -> TemporalResult<String> {
let provider = TZ_PROVIDER
.lock()
.map_err(|_| TemporalError::general("Unable to acquire lock"))?;
self.offset_with_provider(&*provider)
}

/// Returns the current offset in nanoseconds
pub fn offset_nanoseconds(&self) -> TemporalResult<i64> {
let provider = TZ_PROVIDER
.lock()
.map_err(|_| TemporalError::general("Unable to acquire lock"))?;
self.offset_nanoseconds_with_provider(&*provider)
}
}

// ==== Experimental TZ_PROVIDER calendar method implementations ====
Expand Down
50 changes: 49 additions & 1 deletion src/builtins/core/zoneddatetime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ use crate::{
ResolvedRoundingOptions, RoundingIncrement, TemporalRoundingMode, TemporalUnit,
ToStringRoundingOptions,
},
parsers::{self, IxdtfStringBuilder},
parsers::{self, FormattableOffset, FormattableTime, IxdtfStringBuilder, Precision},
partial::{PartialDate, PartialTime},
provider::TimeZoneProvider,
rounding::{IncrementRounder, Round},
Expand Down Expand Up @@ -542,6 +542,54 @@ impl ZonedDateTime {
let iso = self.tz.get_iso_datetime_for(&self.instant, provider)?;
Ok(iso.time.nanosecond)
}

pub fn offset_with_provider(&self, provider: &impl TimeZoneProvider) -> TemporalResult<String> {
let offset = self
.tz
.get_offset_nanos_for(self.epoch_nanoseconds(), provider)?;
Ok(nanoseconds_to_formattable_offset(offset).to_string())
}

pub fn offset_nanoseconds_with_provider(
&self,
provider: &impl TimeZoneProvider,
) -> TemporalResult<i64> {
let offset = self
.tz
.get_offset_nanos_for(self.epoch_nanoseconds(), provider)?;
Ok(offset as i64)
}
}

pub(crate) fn nanoseconds_to_formattable_offset(nanoseconds: i128) -> FormattableOffset {
let sign = if nanoseconds >= 0 {
Sign::Positive
} else {
Sign::Negative
};
let nanos = nanoseconds.unsigned_abs();
let hour = (nanos / 3_600_000_000_000) as u8;
let minute = ((nanos / 60_000_000_000) % 60) as u8;
let second = ((nanos / 1_000_000_000) % 60) as u8;
let nanosecond = (nanos % 1_000_000_000) as u32;

let precision = if second == 0 && nanosecond == 0 {
Precision::Minute
} else {
Precision::Auto
};

FormattableOffset {
sign,
time: FormattableTime {
hour,
minute,
second,
nanosecond,
precision,
include_sep: true,
},
}
}

// ==== Core calendar method implementations ====
Expand Down

0 comments on commit e9448cc

Please sign in to comment.