Skip to content

Commit

Permalink
Add jiff example (#5997)
Browse files Browse the repository at this point in the history
  • Loading branch information
robertbastian authored Jan 15, 2025
1 parent 5b8e8c0 commit 0959d99
Show file tree
Hide file tree
Showing 4 changed files with 133 additions and 3 deletions.
45 changes: 45 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions components/icu/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ icu_datetime = { path = "../../components/datetime", features = ["serde"] }
icu_provider_adapters = { path = "../../provider/adapters", features = ["serde"] }
icu_provider_blob = { path = "../../provider/blob" }
writeable = { path = "../../utils/writeable" }
jiff = "0.1"

[features]
default = [
Expand Down Expand Up @@ -134,3 +135,6 @@ skip_feature_sets = [[]]
[[example]]
name = "tui"
required-features = ["serde"]

[[example]]
name = "jiff"
66 changes: 66 additions & 0 deletions components/icu/examples/jiff.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
// This file is part of ICU4X. For terms of use, please see the file
// called LICENSE at the top level of the ICU4X source tree
// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ).

use icu::{
calendar::Date,
datetime::{fieldsets, DateTimeFormatter},
locale::locale,
timezone::{IxdtfParser, Time, TimeZoneIdMapper, UtcOffset, ZoneVariant, ZonedDateTime},
};

fn main() -> Result<(), Box<dyn core::error::Error>> {
let ts: jiff::Timestamp = "2024-09-10T23:37:20.123456789Z".parse()?;
let zoned: jiff::Zoned = ts.intz("Asia/Tokyo")?;

// Convert to ICU types
let date = Date::try_new_iso(
i32::from(zoned.year()),
zoned.month().unsigned_abs(),
zoned.day().unsigned_abs(),
)?;

let time = Time::try_new(
zoned.hour().unsigned_abs(),
zoned.minute().unsigned_abs(),
zoned.second().unsigned_abs(),
u32::from(zoned.millisecond().unsigned_abs()) * 1_000_000
+ u32::from(zoned.microsecond().unsigned_abs()) * 1_000
+ u32::from(zoned.nanosecond().unsigned_abs()),
)?;

let zone =
// ICU uses BCP47 time zone IDs
TimeZoneIdMapper::new().iana_to_bcp47(zoned.time_zone().iana_name().unwrap_or("Etc/Unknown"))
// In ICU's model, a time zone has a fixed offset, as that's required for formatting
.with_offset(UtcOffset::try_from_seconds(zoned.offset().seconds()).ok())
// Display names might change over time for a given zone (e.g. it might change from Eastern Time to
// Central Time), so the ICU timezone needs a reference date and time.
.at_time((date, time))
// And finally, the zone variant is also required for formatting
.with_zone_variant(match zoned.time_zone().to_offset(zoned.timestamp()).1 {
jiff::tz::Dst::Yes => ZoneVariant::Daylight,
jiff::tz::Dst::No => ZoneVariant::Standard,
});

let zoned_date_time = ZonedDateTime { date, time, zone };

// Alternatively, the ICU ZonedDateTime can be parsed from a serialized IXDTF string.
assert_eq!(
IxdtfParser::new()
.try_iso_from_str(&zoned.to_string())
.unwrap(),
zoned_date_time
);

// Preferences for an English formatter using the Japanese calendar
let prefs = locale!("en-GB-u-ca-japanese").into();

// A medium-length year-month-day-time-specific-zone formatter
let formatter =
DateTimeFormatter::try_new(prefs, fieldsets::YMDT::medium().with_zone_specific_long())?;

println!("{}", formatter.format_any_calendar(&zoned_date_time)); // 11 Sept 6 Reiwa, 08:37:20 Japan Standard Time

Ok(())
}
21 changes: 18 additions & 3 deletions components/timezone/src/ixdtf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -322,7 +322,12 @@ impl<'a> Intermediate<'a> {
};
let time_zone_id = mapper.iana_bytes_to_bcp47(iana_identifier);
let date = Date::<Iso>::try_new_iso(self.date.year, self.date.month, self.date.day)?;
let time = Time::try_new(self.time.hour, self.time.minute, self.time.second, 0)?;
let time = Time::try_new(
self.time.hour,
self.time.minute,
self.time.second,
self.time.nanosecond,
)?;
let offset = match time_zone_id.as_str() {
"utc" | "gmt" => Some(UtcOffset::zero()),
_ => None,
Expand Down Expand Up @@ -358,7 +363,12 @@ impl<'a> Intermediate<'a> {
},
};
let date = Date::<Iso>::try_new_iso(self.date.year, self.date.month, self.date.day)?;
let time = Time::try_new(self.time.hour, self.time.minute, self.time.second, 0)?;
let time = Time::try_new(
self.time.hour,
self.time.minute,
self.time.second,
self.time.nanosecond,
)?;
Ok(time_zone_id.with_offset(offset).at_time((date, time)))
}

Expand All @@ -375,7 +385,12 @@ impl<'a> Intermediate<'a> {
};
let time_zone_id = mapper.iana_bytes_to_bcp47(iana_identifier);
let date = Date::try_new_iso(self.date.year, self.date.month, self.date.day)?;
let time = Time::try_new(self.time.hour, self.time.minute, self.time.second, 0)?;
let time = Time::try_new(
self.time.hour,
self.time.minute,
self.time.second,
self.time.nanosecond,
)?;
let offset = UtcOffset::try_from_utc_offset_record(offset)?;
let zone_variant = match zone_offset_calculator
.compute_offsets_from_time_zone(time_zone_id, (date, time))
Expand Down

0 comments on commit 0959d99

Please sign in to comment.