@@ -49,41 +49,78 @@ pub enum FormatSystemTimeFallback {
4949 Float , // Just print seconds+nanoseconds since epoch (`stat`)
5050}
5151
52+ /// Write the seconds-since-epoch fallback used when a `SystemTime` is out of
53+ /// the range representable by `jiff::Zoned`.
54+ fn write_fallback_seconds < W : Write > (
55+ out : & mut W ,
56+ time : SystemTime ,
57+ mode : FormatSystemTimeFallback ,
58+ ) -> UResult < ( ) > {
59+ // TODO: The range allowed by jiff is different from what GNU accepts,
60+ // but it still far enough in the future/past to be unlikely to matter:
61+ // jiff: Year between -9999 to 9999 (UTC) [-377705023201..=253402207200]
62+ // GNU: Year fits in signed 32 bits (timezone dependent)
63+ let ( mut secs, mut nsecs) = system_time_to_sec ( time) ;
64+ match mode {
65+ FormatSystemTimeFallback :: Integer => out. write_all ( secs. to_string ( ) . as_bytes ( ) ) ?,
66+ FormatSystemTimeFallback :: IntegerError => {
67+ let str = secs. to_string ( ) ;
68+ show_error ! ( "time '{str}' is out of range" ) ;
69+ out. write_all ( str. as_bytes ( ) ) ?;
70+ }
71+ FormatSystemTimeFallback :: Float => {
72+ if secs < 0 && nsecs != 0 {
73+ secs -= 1 ;
74+ nsecs = 1_000_000_000 - nsecs;
75+ }
76+ out. write_fmt ( format_args ! ( "{secs}.{nsecs:09}" ) ) ?;
77+ }
78+ }
79+ Ok ( ( ) )
80+ }
81+
5282/// Format a `SystemTime` according to given fmt, and append to vector out.
5383pub fn format_system_time < W : Write > (
5484 out : & mut W ,
5585 time : SystemTime ,
5686 fmt : & str ,
5787 mode : FormatSystemTimeFallback ,
5888) -> UResult < ( ) > {
59- let zoned: Result < Zoned , _ > = time. try_into ( ) ;
60- if let Ok ( zoned) = zoned {
61- format_zoned ( out, zoned, fmt)
62- } else {
89+ match time. try_into ( ) {
90+ Ok ( zoned) => format_zoned ( out, zoned, fmt) ,
6391 // Assume that if we cannot build a Zoned element, the timestamp is
6492 // out of reasonable range, just print it then.
65- // TODO: The range allowed by jiff is different from what GNU accepts,
66- // but it still far enough in the future/past to be unlikely to matter:
67- // jiff: Year between -9999 to 9999 (UTC) [-377705023201..=253402207200]
68- // GNU: Year fits in signed 32 bits (timezone dependent)
69- let ( mut secs, mut nsecs) = system_time_to_sec ( time) ;
70- match mode {
71- FormatSystemTimeFallback :: Integer => out. write_all ( secs. to_string ( ) . as_bytes ( ) ) ?,
72- FormatSystemTimeFallback :: IntegerError => {
73- let str = secs. to_string ( ) ;
74- show_error ! ( "time '{str}' is out of range" ) ;
75- out. write_all ( str. as_bytes ( ) ) ?;
76- }
77- FormatSystemTimeFallback :: Float => {
78- if secs < 0 && nsecs != 0 {
79- secs -= 1 ;
80- nsecs = 1_000_000_000 - nsecs;
81- }
82- out. write_fmt ( format_args ! ( "{secs}.{nsecs:09}" ) ) ?;
93+ Err ( _) => write_fallback_seconds ( out, time, mode) ,
94+ }
95+ }
96+
97+ /// Like [`format_system_time`], but when built with the `i18n-datetime`
98+ /// feature and a non-C `LC_TIME` locale is active, rewrites locale-dependent
99+ /// strftime directives (`%b`, `%B`, `%a`, `%A`, and `%Y`/`%m`/`%d`/`%e` for
100+ /// non-Gregorian calendars) to their localized values before formatting.
101+ /// For Gregorian locales, `%Y`/`%m`/`%d`/`%e` are unaffected (e.g. `en_US`
102+ /// still renders 2025 as `2025`).
103+ ///
104+ /// With the feature disabled or a C/POSIX locale, this is identical to
105+ /// `format_system_time`.
106+ pub fn format_system_time_locale_aware < W : Write > (
107+ out : & mut W ,
108+ time : SystemTime ,
109+ fmt : & str ,
110+ mode : FormatSystemTimeFallback ,
111+ ) -> UResult < ( ) > {
112+ #[ cfg( feature = "i18n-datetime" ) ]
113+ {
114+ use crate :: i18n:: datetime:: { localize_format_string, should_use_icu_locale} ;
115+ if should_use_icu_locale ( ) {
116+ if let Ok ( zoned) = <SystemTime as TryInto < Zoned > >:: try_into ( time) {
117+ let localized = localize_format_string ( fmt, zoned. date ( ) ) ;
118+ return format_zoned ( out, zoned, & localized) ;
83119 }
120+ // Out-of-range: fall through to the plain fallback below.
84121 }
85- Ok ( ( ) )
86122 }
123+ format_system_time ( out, time, fmt, mode)
87124}
88125
89126#[ cfg( test) ]
0 commit comments