Skip to content

Commit 0f9ba47

Browse files
Add ZoneNameTimestamp::from_epoch_seconds (#7720)
The current API requires constructing a `ZonedDateTime` from UNIX seconds, and then internally converts it back to UNIX seconds. Split from #7630
1 parent 3e9771a commit 0f9ba47

File tree

16 files changed

+130
-156
lines changed

16 files changed

+130
-156
lines changed

components/datetime/src/chrono.rs

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -279,12 +279,7 @@ impl<Tz: chrono::TimeZone> GetField<Option<UtcOffset>> for chrono::DateTime<Tz>
279279
impl<Tz: chrono::TimeZone> GetField<ZoneNameTimestamp> for chrono::DateTime<Tz> {
280280
#[inline]
281281
fn get_field(&self) -> ZoneNameTimestamp {
282-
ZoneNameTimestamp::from_zoned_date_time_iso(
283-
ZonedDateTime::from_epoch_milliseconds_and_utc_offset(
284-
self.timestamp() * 1000,
285-
UtcOffset::zero(),
286-
),
287-
)
282+
ZoneNameTimestamp::from_epoch_seconds(self.timestamp())
288283
}
289284
}
290285

components/datetime/src/fieldsets.rs

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -947,7 +947,7 @@ macro_rules! impl_zone_marker {
947947
/// // Time zone info for America/Chicago in the summer
948948
/// let zone = TimeZone::from_iana_id("America/Chicago")
949949
/// .with_offset(UtcOffset::try_from_seconds(-5 * 3600).ok())
950-
/// .at_date_time_iso(DateTime{ date: Date::try_new_iso(2022, 8, 29).unwrap(), time: Time::start_of_day() });
950+
/// .with_zone_name_timestamp(icu::time::zone::ZoneNameTimestamp::from_epoch_seconds(1661724000));
951951
///
952952
/// assert_writeable_eq!(
953953
/// fmt.format(&zone),
@@ -1338,7 +1338,7 @@ pub mod zone {
13381338
/// // Time zone info for Europe/Istanbul in the winter
13391339
/// let zone = TimeZone::from_iana_id("Europe/Istanbul")
13401340
/// .with_offset(UtcOffset::try_from_seconds(3 * 3600).ok())
1341-
/// .at_date_time_iso(DateTime{ date: Date::try_new_iso(2022, 1, 29).unwrap(), time: Time::start_of_day() });
1341+
/// .with_zone_name_timestamp(icu::time::zone::ZoneNameTimestamp::from_epoch_seconds(1643410800));
13421342
///
13431343
/// let fmt = NoCalendarFormatter::try_new(
13441344
/// locale!("en").into(),
@@ -1363,7 +1363,7 @@ pub mod zone {
13631363
/// // Time zone info for America/Chicago with a wrong offset
13641364
/// let wrong_offset = TimeZone::from_iana_id("America/Chicago")
13651365
/// .with_offset(UtcOffset::try_from_seconds(-4 * 3600).ok())
1366-
/// .at_date_time_iso(DateTime{ date: Date::try_new_iso(2022, 8, 29).unwrap(), time: Time::start_of_day() });
1366+
/// .with_zone_name_timestamp(icu::time::zone::ZoneNameTimestamp::from_epoch_seconds(1661724000));
13671367
///
13681368
/// let fmt = NoCalendarFormatter::try_new(
13691369
/// locale!("en").into(),
@@ -1434,7 +1434,7 @@ pub mod zone {
14341434
/// // Time zone info for Asia/Tokyo
14351435
/// let zone = TimeZone::from_iana_id("Asia/Tokyo")
14361436
/// .with_offset(UtcOffset::try_from_seconds(9 * 3600).ok())
1437-
/// .at_date_time_iso(DateTime{ date: Date::try_new_iso(2022, 1, 29).unwrap(), time: Time::start_of_day() });
1437+
/// .with_zone_name_timestamp(icu::time::zone::ZoneNameTimestamp::from_epoch_seconds(1643410800));
14381438
///
14391439
/// let fmt = NoCalendarFormatter::try_new(
14401440
/// locale!("en").into(),
@@ -1460,7 +1460,7 @@ pub mod zone {
14601460
/// // Time zone info for America/Chicago with a wrong offset
14611461
/// let wrong_offset = TimeZone::from_iana_id("America/Chicago")
14621462
/// .with_offset(UtcOffset::try_from_seconds(-4 * 3600).ok())
1463-
/// .at_date_time_iso(DateTime{ date: Date::try_new_iso(2022, 8, 29).unwrap(), time: Time::start_of_day() });
1463+
/// .with_zone_name_timestamp(icu::time::zone::ZoneNameTimestamp::from_epoch_seconds(1661724000));
14641464
///
14651465
/// let fmt = NoCalendarFormatter::try_new(
14661466
/// locale!("en").into(),
@@ -1528,9 +1528,7 @@ pub mod zone {
15281528
/// let utc_offset = UtcOffset::try_from_seconds(-6 * 3600).unwrap();
15291529
/// let time_zone_basic = TimeZone::from_iana_id("America/Chicago").with_offset(Some(utc_offset));
15301530
///
1531-
/// let date = Date::try_new_iso(2024, 10, 18).unwrap();
1532-
/// let time = Time::start_of_day();
1533-
/// let time_zone_at_time = time_zone_basic.at_date_time_iso(DateTime{ date, time });
1531+
/// let time_zone_at_time = time_zone_basic.with_zone_name_timestamp(icu::time::zone::ZoneNameTimestamp::from_epoch_seconds(1729202400));
15341532
///
15351533
/// let formatter = NoCalendarFormatter::try_new(
15361534
/// locale!("en-US").into(),
@@ -1575,9 +1573,7 @@ pub mod zone {
15751573
/// let utc_offset = UtcOffset::try_from_seconds(-6 * 3600).unwrap();
15761574
/// let time_zone_basic = TimeZone::from_iana_id("America/Chicago").with_offset(Some(utc_offset));
15771575
///
1578-
/// let date = Date::try_new_iso(2024, 10, 18).unwrap();
1579-
/// let time = Time::start_of_day();
1580-
/// let time_zone_at_time = time_zone_basic.at_date_time_iso(DateTime{ date, time });
1576+
/// let time_zone_at_time = time_zone_basic.with_zone_name_timestamp(icu::time::zone::ZoneNameTimestamp::from_epoch_seconds(1729202400));
15811577
///
15821578
/// let formatter = NoCalendarFormatter::try_new(
15831579
/// locale!("en-US").into(),
@@ -1621,7 +1617,7 @@ pub mod zone {
16211617
/// // Time zone info for Europe/Istanbul in the winter
16221618
/// let zone = TimeZone::from_iana_id("Europe/Istanbul")
16231619
/// .with_offset(UtcOffset::try_from_seconds(3 * 3600).ok())
1624-
/// .at_date_time_iso(DateTime{ date: Date::try_new_iso(2022, 1, 29).unwrap(), time: Time::start_of_day() });
1620+
/// .with_zone_name_timestamp(icu::time::zone::ZoneNameTimestamp::from_epoch_seconds(1643410800));
16251621
///
16261622
/// let fmt = NoCalendarFormatter::try_new(
16271623
/// locale!("en").into(),
@@ -1646,7 +1642,7 @@ pub mod zone {
16461642
/// // Time zone info for America/Chicago with a wrong offset
16471643
/// let wrong_offset = TimeZone::from_iana_id("America/Chicago")
16481644
/// .with_offset(UtcOffset::try_from_seconds(-4 * 3600).ok())
1649-
/// .at_date_time_iso(DateTime{ date: Date::try_new_iso(2022, 8, 29).unwrap(), time: Time::start_of_day() });
1645+
/// .with_zone_name_timestamp(icu::time::zone::ZoneNameTimestamp::from_epoch_seconds(1661724000));
16501646
///
16511647
/// let fmt = NoCalendarFormatter::try_new(
16521648
/// locale!("en").into(),
@@ -1718,7 +1714,7 @@ pub mod zone {
17181714
/// // Time zone info for Asia/Tokyo
17191715
/// let zone = TimeZone::from_iana_id("Asia/Tokyo")
17201716
/// .with_offset(UtcOffset::try_from_seconds(9 * 3600).ok())
1721-
/// .at_date_time_iso(DateTime{ date: Date::try_new_iso(2022, 1, 29).unwrap(), time: Time::start_of_day() });
1717+
/// .with_zone_name_timestamp(icu::time::zone::ZoneNameTimestamp::from_epoch_seconds(1643410800));
17221718
///
17231719
/// let fmt = NoCalendarFormatter::try_new(
17241720
/// locale!("en").into(),
@@ -1744,7 +1740,7 @@ pub mod zone {
17441740
/// // Time zone info for America/Chicago with a wrong offset
17451741
/// let wrong_offset = TimeZone::from_iana_id("America/Chicago")
17461742
/// .with_offset(UtcOffset::try_from_seconds(-4 * 3600).ok())
1747-
/// .at_date_time_iso(DateTime{ date: Date::try_new_iso(2022, 8, 29).unwrap(), time: Time::start_of_day() });
1743+
/// .with_zone_name_timestamp(icu::time::zone::ZoneNameTimestamp::from_epoch_seconds(1661724000));
17481744
///
17491745
/// let fmt = NoCalendarFormatter::try_new(
17501746
/// locale!("en").into(),

components/datetime/src/jiff.rs

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@ use icu_calendar::{AnyCalendar, AnyCalendarKind, Date, Gregorian};
99
#[cfg(feature = "compiled_data")]
1010
use icu_time::zone::models::AtTime;
1111
use icu_time::zone::{UtcOffset, ZoneNameTimestamp};
12-
use icu_time::{DateTime, Hour, Minute, Nanosecond, Second, Time, ZonedDateTime};
12+
use icu_time::{DateTime, Hour, Minute, Nanosecond, Second, Time};
1313
#[cfg(feature = "compiled_data")]
14-
use icu_time::{TimeZone, TimeZoneInfo};
14+
use icu_time::{TimeZone, TimeZoneInfo, ZonedDateTime};
1515

1616
impl UnstableSealed for jiff::civil::Time {}
1717
impl<C> InFixedCalendar<C> for jiff::civil::Time {}
@@ -278,12 +278,7 @@ impl GetField<Option<UtcOffset>> for jiff::Zoned {
278278
impl GetField<ZoneNameTimestamp> for jiff::Zoned {
279279
#[inline]
280280
fn get_field(&self) -> ZoneNameTimestamp {
281-
ZoneNameTimestamp::from_zoned_date_time_iso(
282-
ZonedDateTime::from_epoch_milliseconds_and_utc_offset(
283-
self.timestamp().as_millisecond(),
284-
UtcOffset::zero(),
285-
),
286-
)
281+
ZoneNameTimestamp::from_epoch_seconds(self.timestamp().as_second())
287282
}
288283
}
289284

components/datetime/src/provider/time_zones.rs

Lines changed: 16 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -384,8 +384,6 @@ pub(crate) mod legacy {
384384

385385
#[test]
386386
fn test_metazone_timezone_compat() {
387-
use icu_time::ZonedDateTime;
388-
389387
let converted = metazone_timezone_compat(
390388
&icu_provider_blob::BlobDataProvider::try_new_from_static_blob(
391389
// icu4x-datagen --markers TimezoneMetazonePeriodsV1 --format blob
@@ -398,26 +396,22 @@ pub(crate) mod legacy {
398396
.payload;
399397

400398
let tz = TimeZone::from_iana_id("Antarctica/Casey");
401-
for timestamp in [
402-
"1970-01-01 00:00Z",
403-
"2009-10-17 18:00Z",
404-
"2010-03-04 15:00Z",
405-
"2011-10-27 18:00Z",
406-
"2012-02-21 17:00Z",
407-
"2016-10-21 16:00Z",
408-
"2018-03-10 17:00Z",
409-
"2018-10-06 20:00Z",
410-
"2019-03-16 16:00Z",
411-
"2019-10-03 19:00Z",
412-
"2020-03-07 16:00Z",
413-
"2021-03-13 13:00Z",
414-
"2022-03-12 13:00Z",
415-
"2023-03-08 16:00Z",
399+
for t in [
400+
ZoneNameTimestamp::from_epoch_seconds(0),
401+
ZoneNameTimestamp::from_epoch_seconds(1255802400),
402+
ZoneNameTimestamp::from_epoch_seconds(1267714800),
403+
ZoneNameTimestamp::from_epoch_seconds(1319738400),
404+
ZoneNameTimestamp::from_epoch_seconds(1329843600),
405+
ZoneNameTimestamp::from_epoch_seconds(1477065600),
406+
ZoneNameTimestamp::from_epoch_seconds(1520701200),
407+
ZoneNameTimestamp::from_epoch_seconds(1538856000),
408+
ZoneNameTimestamp::from_epoch_seconds(1552752000),
409+
ZoneNameTimestamp::from_epoch_seconds(1570129200),
410+
ZoneNameTimestamp::from_epoch_seconds(1583596800),
411+
ZoneNameTimestamp::from_epoch_seconds(1615640400),
412+
ZoneNameTimestamp::from_epoch_seconds(1647090000),
413+
ZoneNameTimestamp::from_epoch_seconds(1678291200),
416414
] {
417-
let t = ZoneNameTimestamp::from_zoned_date_time_iso(
418-
ZonedDateTime::try_offset_only_from_str(timestamp, icu_calendar::Iso).unwrap(),
419-
);
420-
421415
assert_eq!(
422416
converted
423417
.get()
@@ -435,7 +429,7 @@ pub(crate) mod legacy {
435429
.unwrap()
436430
.1
437431
.map(|mz| mz.id.get()),
438-
"{timestamp:?}",
432+
"{t:?}",
439433
);
440434
}
441435
}

components/time/src/chrono.rs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
use icu_calendar::Gregorian;
66

77
use crate::zone::models::{AtTime, Base};
8-
use crate::zone::UtcOffset;
8+
use crate::zone::{UtcOffset, ZoneNameTimestamp};
99
use crate::{DateTime, Hour, Minute, Nanosecond, Second, Time};
1010
use crate::{TimeZone, TimeZoneInfo, ZonedDateTime};
1111

@@ -64,10 +64,9 @@ where
6464
ZonedDateTime {
6565
date,
6666
time,
67-
zone: zone.at_date_time_iso(DateTime {
68-
date: date.to_calendar(icu_calendar::Iso),
69-
time,
70-
}),
67+
zone: zone.with_zone_name_timestamp(ZoneNameTimestamp::from_epoch_seconds(
68+
chrono.timestamp(),
69+
)),
7170
}
7271
}
7372
}

components/time/src/jiff.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ use icu_calendar::Gregorian;
77
#[cfg(feature = "compiled_data")]
88
use crate::zone::models::{AtTime, Base};
99
use crate::zone::UtcOffset;
10+
#[cfg(feature = "compiled_data")]
11+
use crate::zone::ZoneNameTimestamp;
1012
use crate::{DateTime, Hour, Minute, Nanosecond, Second, Time};
1113
#[cfg(feature = "compiled_data")]
1214
use crate::{TimeZone, TimeZoneInfo, ZonedDateTime};
@@ -69,10 +71,9 @@ impl From<&jiff::Zoned> for ZonedDateTime<Gregorian, TimeZoneInfo<AtTime>> {
6971
ZonedDateTime {
7072
date,
7173
time,
72-
zone: zone.at_date_time_iso(DateTime {
73-
date: date.to_calendar(icu_calendar::Iso),
74-
time,
75-
}),
74+
zone: zone.with_zone_name_timestamp(ZoneNameTimestamp::from_epoch_seconds(
75+
jiff.timestamp().as_second(),
76+
)),
7677
}
7778
}
7879
}

components/time/src/zone/mod.rs

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,7 @@ impl<'a> zerovec::maps::ZeroMapKV<'a> for TimeZone {
268268
/// use icu::time::Time;
269269
/// use icu::time::TimeZone;
270270
/// use icu::time::zone::UtcOffset;
271+
/// use icu::time::zone::ZoneNameTimestamp;
271272
///
272273
/// // Parse the IANA ID
273274
/// let id = TimeZone::from_iana_id("America/Chicago");
@@ -278,7 +279,12 @@ impl<'a> zerovec::maps::ZeroMapKV<'a> for TimeZone {
278279
/// // Create a TimeZoneInfo<Base> by associating the ID with an offset
279280
/// let time_zone = id.with_offset(UtcOffset::try_from_seconds(-6 * 3600).ok());
280281
///
281-
/// // Extend to a TimeZoneInfo<AtTime> by adding a local time
282+
/// // Extend to a `TimeZoneInfo<AtTime>` by adding a timestamp ...
283+
/// let time_zone_at_time = time_zone.with_zone_name_timestamp(
284+
/// ZoneNameTimestamp::from_epoch_seconds(1701493200)
285+
/// );
286+
///
287+
/// // ... or by adding a local time
282288
/// let time_zone_at_time = time_zone.at_date_time_iso(DateTime {
283289
/// date: Date::try_new_iso(2023, 12, 2).unwrap(),
284290
/// time: Time::start_of_day(),
@@ -494,6 +500,7 @@ impl TimeZoneInfo<models::AtTime> {
494500
/// ```
495501
/// use icu::calendar::Date;
496502
/// use icu::time::zone::TimeZoneVariant;
503+
/// use icu::time::zone::ZoneNameTimestamp;
497504
/// use icu::time::zone::VariantOffsetsCalculator;
498505
/// use icu::time::DateTime;
499506
/// use icu::time::Time;
@@ -503,32 +510,23 @@ impl TimeZoneInfo<models::AtTime> {
503510
/// // Chicago at UTC-6
504511
/// let info = TimeZone::from_iana_id("America/Chicago")
505512
/// .with_offset(UtcOffset::try_from_seconds(-6 * 3600).ok())
506-
/// .at_date_time_iso(DateTime {
507-
/// date: Date::try_new_iso(2023, 12, 2).unwrap(),
508-
/// time: Time::start_of_day(),
509-
/// })
513+
/// .with_zone_name_timestamp(ZoneNameTimestamp::from_epoch_seconds(1701493200))
510514
/// .infer_variant(VariantOffsetsCalculator::new());
511515
///
512516
/// assert_eq!(info.variant(), TimeZoneVariant::Standard);
513517
///
514518
/// // Chicago at at UTC-5
515519
/// let info = TimeZone::from_iana_id("America/Chicago")
516520
/// .with_offset(UtcOffset::try_from_seconds(-5 * 3600).ok())
517-
/// .at_date_time_iso(DateTime {
518-
/// date: Date::try_new_iso(2023, 6, 2).unwrap(),
519-
/// time: Time::start_of_day(),
520-
/// })
521+
/// .with_zone_name_timestamp(ZoneNameTimestamp::from_epoch_seconds(1685678400))
521522
/// .infer_variant(VariantOffsetsCalculator::new());
522523
///
523524
/// assert_eq!(info.variant(), TimeZoneVariant::Daylight);
524525
///
525526
/// // Chicago at UTC-7
526527
/// let info = TimeZone::from_iana_id("America/Chicago")
527528
/// .with_offset(UtcOffset::try_from_seconds(-7 * 3600).ok())
528-
/// .at_date_time_iso(DateTime {
529-
/// date: Date::try_new_iso(2023, 12, 2).unwrap(),
530-
/// time: Time::start_of_day(),
531-
/// })
529+
/// .with_zone_name_timestamp(ZoneNameTimestamp::from_epoch_seconds(1701493200))
532530
/// .infer_variant(VariantOffsetsCalculator::new());
533531
///
534532
/// // Whatever it is, it's not Chicago

components/time/src/zone/offset.rs

Lines changed: 16 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -402,7 +402,6 @@ pub use crate::provider::VariantOffsets;
402402
#[test]
403403
#[allow(deprecated)]
404404
pub fn test_legacy_offsets_data() {
405-
use crate::ZonedDateTime;
406405
use icu_locale_core::subtags::subtag;
407406
use icu_provider_blob::BlobDataProvider;
408407

@@ -417,32 +416,28 @@ pub fn test_legacy_offsets_data() {
417416

418417
let tz = TimeZone(subtag!("aqcas"));
419418

420-
for timestamp in [
421-
"1970-01-01 00:00Z",
422-
"2009-10-17 18:00Z",
423-
"2010-03-04 15:00Z",
424-
"2011-10-27 18:00Z",
425-
"2012-02-21 17:00Z",
426-
"2016-10-21 16:00Z",
427-
"2018-03-10 17:00Z",
428-
"2018-10-06 20:00Z",
429-
"2019-03-16 16:00Z",
430-
"2019-10-03 19:00Z",
431-
"2020-03-07 16:00Z",
432-
"2021-03-13 13:00Z",
433-
"2022-03-12 13:00Z",
434-
"2023-03-08 16:00Z",
419+
for t in [
420+
ZoneNameTimestamp::from_epoch_seconds(0),
421+
ZoneNameTimestamp::from_epoch_seconds(1255802400),
422+
ZoneNameTimestamp::from_epoch_seconds(1267714800),
423+
ZoneNameTimestamp::from_epoch_seconds(1319738400),
424+
ZoneNameTimestamp::from_epoch_seconds(1329843600),
425+
ZoneNameTimestamp::from_epoch_seconds(1477065600),
426+
ZoneNameTimestamp::from_epoch_seconds(1520701200),
427+
ZoneNameTimestamp::from_epoch_seconds(1538856000),
428+
ZoneNameTimestamp::from_epoch_seconds(1552752000),
429+
ZoneNameTimestamp::from_epoch_seconds(1570129200),
430+
ZoneNameTimestamp::from_epoch_seconds(1583596800),
431+
ZoneNameTimestamp::from_epoch_seconds(1615640400),
432+
ZoneNameTimestamp::from_epoch_seconds(1647090000),
433+
ZoneNameTimestamp::from_epoch_seconds(1678291200),
435434
] {
436-
let t = ZoneNameTimestamp::from_zoned_date_time_iso(
437-
ZonedDateTime::try_offset_only_from_str(timestamp, icu_calendar::Iso).unwrap(),
438-
);
439-
440435
assert_eq!(
441436
c.as_borrowed()
442437
.compute_offsets_from_time_zone_and_name_timestamp(tz, t),
443438
VariantOffsetsCalculator::new()
444439
.compute_offsets_from_time_zone_and_name_timestamp(tz, t),
445-
"{timestamp:?}",
440+
"{t:?}",
446441
);
447442
}
448443
}

0 commit comments

Comments
 (0)