313
313
//! tzf.format(&time_zone),
314
314
//! "HST"
315
315
//! );
316
+ //!
317
+ //! // Mis-spelling of "America/Chicago" results in a fallback to GMT format
318
+ //! let time_zone = TimeZoneInfo::from_id_and_offset(
319
+ //! mapper.as_borrowed().iana_to_bcp47("America/Chigagou"),
320
+ //! UtcOffset::from_eighths_of_hour(-5 * 8),
321
+ //! )
322
+ //! .at_time((Date::try_new_iso(2022, 8, 29).unwrap(), Time::midnight()));
323
+ //! assert_try_writeable_eq!(
324
+ //! tzf.format(&time_zone),
325
+ //! "GMT-5"
326
+ //! );
316
327
//! ```
317
328
318
329
#[ cfg( doc) ]
@@ -2059,6 +2070,8 @@ macro_rules! impl_zone_marker {
2059
2070
$( zone_specific_short = $zone_specific_short_yes: ident, ) ?
2060
2071
// Whether metazone periods are needed
2061
2072
$( metazone_periods = $metazone_periods_yes: ident, ) ?
2073
+ // Whether to require the TimeZoneBcp47Id
2074
+ $( input_tzid = $tzid_input_yes: ident, ) ?
2062
2075
// Whether to require the ZoneVariant
2063
2076
$( input_variant = $variant_input_yes: ident, ) ?
2064
2077
// Whether to require the Local Time
@@ -2155,7 +2168,7 @@ macro_rules! impl_zone_marker {
2155
2168
const COMPONENT : NeoTimeZoneStyle = $components;
2156
2169
}
2157
2170
impl ZoneMarkers for $type {
2158
- type TimeZoneIdInput = datetime_marker_helper!( @input/timezone/id, yes ) ;
2171
+ type TimeZoneIdInput = datetime_marker_helper!( @input/timezone/id, $ ( $tzid_input_yes ) ? ) ;
2159
2172
type TimeZoneOffsetInput = datetime_marker_helper!( @input/timezone/offset, yes) ;
2160
2173
type TimeZoneVariantInput = datetime_marker_helper!( @input/timezone/variant, $( $variant_input_yes) ?) ;
2161
2174
type TimeZoneLocalTimeInput = datetime_marker_helper!( @input/timezone/local_time, $( $localtime_input_yes) ?) ;
@@ -2467,6 +2480,35 @@ impl_zone_marker!(
2467
2480
/// "GMT-3"
2468
2481
/// );
2469
2482
/// ```
2483
+ ///
2484
+ /// Only a full time zone info can be formatted with this style.
2485
+ /// For example, AtTime cannot be formatted.
2486
+ ///
2487
+ /// ```compile_fail
2488
+ /// use icu::calendar::{DateTime, Iso};
2489
+ /// use icu::datetime::neo::TypedNeoFormatter;
2490
+ /// use icu::datetime::neo_marker::NeoTimeZoneSpecificMarker;
2491
+ /// use icu::datetime::neo_skeleton::NeoSkeletonLength;
2492
+ /// use icu::timezone::{TimeZoneBcp47Id, UtcOffset, ZoneVariant};
2493
+ /// use tinystr::tinystr;
2494
+ /// use icu::locale::locale;
2495
+ /// use writeable::assert_try_writeable_eq;
2496
+ ///
2497
+ /// let datetime = DateTime::try_new_gregorian(2024, 10, 18, 0, 0, 0).unwrap();
2498
+ /// let utc_offset = UtcOffset::from_eighths_of_hour(-6 * 8);
2499
+ /// let time_zone_basic = utc_offset.with_id(TimeZoneBcp47Id(tinystr!(8, "uschi")));
2500
+ /// let time_zone_at_time = time_zone_basic.at_time((datetime.date.to_iso(), datetime.time));
2501
+ ///
2502
+ /// let formatter = TypedNeoFormatter::try_new(
2503
+ /// &locale!("en-US").into(),
2504
+ /// NeoTimeZoneSpecificMarker::with_length(NeoSkeletonLength::Medium),
2505
+ /// )
2506
+ /// .unwrap();
2507
+ ///
2508
+ /// // error[E0271]: type mismatch resolving `<AtTime as TimeZoneModel>::ZoneVariant == ZoneVariant`
2509
+ /// // note: required by a bound in `TypedNeoFormatter::<C, FSet>::format`
2510
+ /// formatter.format(&time_zone_at_time);
2511
+ /// ```
2470
2512
NeoTimeZoneSpecificMarker ,
2471
2513
NeoTimeZoneStyle :: Specific ,
2472
2514
description = "specific time zone, or raw offset if unavailable" ,
@@ -2476,6 +2518,7 @@ impl_zone_marker!(
2476
2518
zone_specific_long = yes,
2477
2519
zone_specific_short = yes,
2478
2520
metazone_periods = yes,
2521
+ input_tzid = yes,
2479
2522
input_variant = yes,
2480
2523
input_localtime = yes,
2481
2524
) ;
@@ -2534,6 +2577,35 @@ impl_zone_marker!(
2534
2577
///
2535
2578
/// assert!(matches!(result, Err(LoadError::TypeTooNarrow(_))));
2536
2579
/// ```
2580
+ ///
2581
+ /// Only a full time zone info can be formatted with this style.
2582
+ /// For example, AtTime cannot be formatted.
2583
+ ///
2584
+ /// ```compile_fail
2585
+ /// use icu::calendar::{DateTime, Iso};
2586
+ /// use icu::datetime::neo::TypedNeoFormatter;
2587
+ /// use icu::datetime::neo_marker::NeoTimeZoneSpecificShortMarker;
2588
+ /// use icu::datetime::neo_skeleton::NeoSkeletonLength;
2589
+ /// use icu::timezone::{TimeZoneBcp47Id, UtcOffset, ZoneVariant};
2590
+ /// use tinystr::tinystr;
2591
+ /// use icu::locale::locale;
2592
+ /// use writeable::assert_try_writeable_eq;
2593
+ ///
2594
+ /// let datetime = DateTime::try_new_gregorian(2024, 10, 18, 0, 0, 0).unwrap();
2595
+ /// let utc_offset = UtcOffset::from_eighths_of_hour(-6 * 8);
2596
+ /// let time_zone_basic = utc_offset.with_id(TimeZoneBcp47Id(tinystr!(8, "uschi")));
2597
+ /// let time_zone_at_time = time_zone_basic.at_time((datetime.date.to_iso(), datetime.time));
2598
+ ///
2599
+ /// let formatter = TypedNeoFormatter::try_new(
2600
+ /// &locale!("en-US").into(),
2601
+ /// NeoTimeZoneSpecificShortMarker::with_length(NeoSkeletonLength::Medium),
2602
+ /// )
2603
+ /// .unwrap();
2604
+ ///
2605
+ /// // error[E0271]: type mismatch resolving `<AtTime as TimeZoneModel>::ZoneVariant == ZoneVariant`
2606
+ /// // note: required by a bound in `TypedNeoFormatter::<C, FSet>::format`
2607
+ /// formatter.format(&time_zone_at_time);
2608
+ /// ```
2537
2609
NeoTimeZoneSpecificShortMarker ,
2538
2610
NeoTimeZoneStyle :: Specific ,
2539
2611
description = "specific time zone (only short), or raw offset if unavailable" ,
@@ -2542,11 +2614,104 @@ impl_zone_marker!(
2542
2614
zone_essentials = yes,
2543
2615
zone_specific_short = yes,
2544
2616
metazone_periods = yes,
2617
+ input_tzid = yes,
2545
2618
input_variant = yes,
2546
2619
input_localtime = yes,
2547
2620
) ;
2548
2621
2549
2622
impl_zone_marker ! (
2623
+ /// All shapes of time zones can be formatted with this style.
2624
+ ///
2625
+ /// ```
2626
+ /// use icu::calendar::{DateTime, Iso};
2627
+ /// use icu::datetime::neo::TypedNeoFormatter;
2628
+ /// use icu::datetime::neo_marker::NeoTimeZoneOffsetMarker;
2629
+ /// use icu::datetime::neo_skeleton::NeoSkeletonLength;
2630
+ /// use icu::timezone::{TimeZoneBcp47Id, UtcOffset, ZoneVariant, CustomZonedDateTime};
2631
+ /// use tinystr::tinystr;
2632
+ /// use icu::locale::locale;
2633
+ /// use writeable::assert_try_writeable_eq;
2634
+ ///
2635
+ /// let datetime = DateTime::try_new_gregorian(2024, 10, 18, 0, 0, 0).unwrap();
2636
+ ///
2637
+ /// let utc_offset = UtcOffset::from_eighths_of_hour(-6 * 8);
2638
+ ///
2639
+ /// let zdt_utc_offset = CustomZonedDateTime {
2640
+ /// date: datetime.date,
2641
+ /// time: datetime.time,
2642
+ /// zone: utc_offset
2643
+ /// };
2644
+ ///
2645
+ /// let time_zone_basic = utc_offset.with_id(TimeZoneBcp47Id(tinystr!(8, "uschi")));
2646
+ ///
2647
+ /// let zdt_time_zone_basic = CustomZonedDateTime {
2648
+ /// date: datetime.date,
2649
+ /// time: datetime.time,
2650
+ /// zone: time_zone_basic
2651
+ /// };
2652
+ ///
2653
+ /// let time_zone_at_time = time_zone_basic.at_time((datetime.date.to_iso(), datetime.time));
2654
+ ///
2655
+ /// let zdt_time_zone_at_time = CustomZonedDateTime {
2656
+ /// date: datetime.date,
2657
+ /// time: datetime.time,
2658
+ /// zone: time_zone_at_time
2659
+ /// };
2660
+ ///
2661
+ /// let time_zone_full = time_zone_at_time.with_zone_variant(ZoneVariant::standard());
2662
+ ///
2663
+ /// let zdt_time_zone_full = CustomZonedDateTime {
2664
+ /// date: datetime.date,
2665
+ /// time: datetime.time,
2666
+ /// zone: time_zone_full
2667
+ /// };
2668
+ ///
2669
+ /// let formatter = TypedNeoFormatter::try_new(
2670
+ /// &locale!("en-US").into(),
2671
+ /// NeoTimeZoneOffsetMarker::with_length(NeoSkeletonLength::Medium),
2672
+ /// )
2673
+ /// .unwrap();
2674
+ ///
2675
+ /// assert_try_writeable_eq!(
2676
+ /// formatter.format(&utc_offset),
2677
+ /// "GMT-6"
2678
+ /// );
2679
+ ///
2680
+ /// assert_try_writeable_eq!(
2681
+ /// formatter.format(&zdt_utc_offset),
2682
+ /// "GMT-6"
2683
+ /// );
2684
+ ///
2685
+ /// assert_try_writeable_eq!(
2686
+ /// formatter.format(&time_zone_basic),
2687
+ /// "GMT-6"
2688
+ /// );
2689
+ ///
2690
+ /// assert_try_writeable_eq!(
2691
+ /// formatter.format(&zdt_time_zone_basic),
2692
+ /// "GMT-6"
2693
+ /// );
2694
+ ///
2695
+ /// assert_try_writeable_eq!(
2696
+ /// formatter.format(&time_zone_at_time),
2697
+ /// "GMT-6"
2698
+ /// );
2699
+ ///
2700
+ /// assert_try_writeable_eq!(
2701
+ /// formatter.format(&zdt_time_zone_at_time),
2702
+ /// "GMT-6"
2703
+ /// );
2704
+ ///
2705
+ /// assert_try_writeable_eq!(
2706
+ /// formatter.format(&time_zone_full),
2707
+ /// "GMT-6"
2708
+ /// );
2709
+ ///
2710
+ /// assert_try_writeable_eq!(
2711
+ /// formatter.format(&zdt_time_zone_full),
2712
+ /// "GMT-6"
2713
+ /// );
2714
+ /// ```
2550
2715
NeoTimeZoneOffsetMarker ,
2551
2716
NeoTimeZoneStyle :: Offset ,
2552
2717
description = "UTC offset time zone" ,
@@ -2588,6 +2753,32 @@ impl_zone_marker!(
2588
2753
/// "Sao Paulo Time"
2589
2754
/// );
2590
2755
/// ```
2756
+ ///
2757
+ /// A time zone requires a reference time to be formatted with this style.
2758
+ ///
2759
+ /// ```compile_fail
2760
+ /// use icu::calendar::{DateTime, Iso};
2761
+ /// use icu::datetime::neo::TypedNeoFormatter;
2762
+ /// use icu::datetime::neo_marker::NeoTimeZoneGenericMarker;
2763
+ /// use icu::datetime::neo_skeleton::NeoSkeletonLength;
2764
+ /// use icu::timezone::{TimeZoneBcp47Id, UtcOffset};
2765
+ /// use tinystr::tinystr;
2766
+ /// use icu::locale::locale;
2767
+ /// use writeable::assert_try_writeable_eq;
2768
+ ///
2769
+ /// let utc_offset = UtcOffset::from_eighths_of_hour(-6 * 8);
2770
+ /// let time_zone_basic = utc_offset.with_id(TimeZoneBcp47Id(tinystr!(8, "uschi")));
2771
+ ///
2772
+ /// let formatter = TypedNeoFormatter::try_new(
2773
+ /// &locale!("en-US").into(),
2774
+ /// NeoTimeZoneGenericMarker::with_length(NeoSkeletonLength::Medium),
2775
+ /// )
2776
+ /// .unwrap();
2777
+ ///
2778
+ /// // error[E0271]: type mismatch resolving `<Base as TimeZoneModel>::LocalTime == (Date<Iso>, Time)`
2779
+ /// // note: required by a bound in `TypedNeoFormatter::<C, FSet>::format`
2780
+ /// formatter.format(&time_zone_basic);
2781
+ /// ```
2591
2782
NeoTimeZoneGenericMarker ,
2592
2783
NeoTimeZoneStyle :: Generic ,
2593
2784
description = "generic time zone, or location if unavailable" ,
@@ -2598,6 +2789,7 @@ impl_zone_marker!(
2598
2789
zone_generic_long = yes,
2599
2790
zone_generic_short = yes,
2600
2791
metazone_periods = yes,
2792
+ input_tzid = yes,
2601
2793
input_localtime = yes,
2602
2794
) ;
2603
2795
@@ -2655,6 +2847,32 @@ impl_zone_marker!(
2655
2847
///
2656
2848
/// assert!(matches!(result, Err(LoadError::TypeTooNarrow(_))));
2657
2849
/// ```
2850
+ ///
2851
+ /// A time zone requires a reference time to be formatted with this style.
2852
+ ///
2853
+ /// ```compile_fail
2854
+ /// use icu::calendar::{DateTime, Iso};
2855
+ /// use icu::datetime::neo::TypedNeoFormatter;
2856
+ /// use icu::datetime::neo_marker::NeoTimeZoneGenericShortMarker;
2857
+ /// use icu::datetime::neo_skeleton::NeoSkeletonLength;
2858
+ /// use icu::timezone::{TimeZoneBcp47Id, UtcOffset};
2859
+ /// use tinystr::tinystr;
2860
+ /// use icu::locale::locale;
2861
+ /// use writeable::assert_try_writeable_eq;
2862
+ ///
2863
+ /// let utc_offset = UtcOffset::from_eighths_of_hour(-6 * 8);
2864
+ /// let time_zone_basic = utc_offset.with_id(TimeZoneBcp47Id(tinystr!(8, "uschi")));
2865
+ ///
2866
+ /// let formatter = TypedNeoFormatter::try_new(
2867
+ /// &locale!("en-US").into(),
2868
+ /// NeoTimeZoneGenericShortMarker::with_length(NeoSkeletonLength::Medium),
2869
+ /// )
2870
+ /// .unwrap();
2871
+ ///
2872
+ /// // error[E0271]: type mismatch resolving `<Base as TimeZoneModel>::LocalTime == (Date<Iso>, Time)`
2873
+ /// // note: required by a bound in `TypedNeoFormatter::<C, FSet>::format`
2874
+ /// formatter.format(&time_zone_basic);
2875
+ /// ```
2658
2876
NeoTimeZoneGenericShortMarker ,
2659
2877
NeoTimeZoneStyle :: Generic ,
2660
2878
description = "generic time zone (only short), or location if unavailable" ,
@@ -2664,17 +2882,44 @@ impl_zone_marker!(
2664
2882
zone_locations = yes,
2665
2883
zone_generic_short = yes,
2666
2884
metazone_periods = yes,
2885
+ input_tzid = yes,
2667
2886
input_localtime = yes,
2668
2887
) ;
2669
2888
2670
2889
impl_zone_marker ! (
2890
+ /// A time zone requires a time zone ID to be formatted with this style.
2891
+ /// For example, a raw [`UtcOffset`] cannot be used here.
2892
+ ///
2893
+ /// ```compile_fail
2894
+ /// use icu::calendar::{DateTime, Iso};
2895
+ /// use icu::datetime::neo::TypedNeoFormatter;
2896
+ /// use icu::datetime::neo_marker::NeoTimeZoneLocationMarker;
2897
+ /// use icu::datetime::neo_skeleton::NeoSkeletonLength;
2898
+ /// use icu::timezone::UtcOffset;
2899
+ /// use tinystr::tinystr;
2900
+ /// use icu::locale::locale;
2901
+ /// use writeable::assert_try_writeable_eq;
2902
+ ///
2903
+ /// let utc_offset = UtcOffset::from_eighths_of_hour(-6 * 8);
2904
+ ///
2905
+ /// let formatter = TypedNeoFormatter::try_new(
2906
+ /// &locale!("en-US").into(),
2907
+ /// NeoTimeZoneLocationMarker::with_length(NeoSkeletonLength::Medium),
2908
+ /// )
2909
+ /// .unwrap();
2910
+ ///
2911
+ /// // error[E0277]: the trait bound `UtcOffset: AllInputMarkers<NeoTimeZoneLocationMarker>` is not satisfied
2912
+ /// // note: required by a bound in `TypedNeoFormatter::<C, FSet>::format`
2913
+ /// formatter.format(&utc_offset);
2914
+ /// ```
2671
2915
NeoTimeZoneLocationMarker ,
2672
2916
NeoTimeZoneStyle :: Location ,
2673
2917
description = "location time zone" ,
2674
2918
sample_length = Long ,
2675
2919
sample = "Chicago Time" ,
2676
2920
zone_essentials = yes,
2677
2921
zone_locations = yes,
2922
+ input_tzid = yes,
2678
2923
) ;
2679
2924
2680
2925
// TODO: Type aliases like this are excessive; make a curated set
0 commit comments