44//! Date and time formatting routines.
55
66#[ cfg( all( feature = "alloc" , not( feature = "std" ) , not( test) ) ) ]
7- use alloc:: string:: { String , ToString } ;
7+ use alloc:: string:: String ;
88#[ cfg( feature = "alloc" ) ]
99use core:: borrow:: Borrow ;
1010#[ cfg( feature = "alloc" ) ]
@@ -16,7 +16,7 @@ use crate::offset::Offset;
1616#[ cfg( any( feature = "alloc" , feature = "serde" ) ) ]
1717use crate :: { Datelike , FixedOffset , NaiveDateTime , Timelike } ;
1818#[ cfg( feature = "alloc" ) ]
19- use crate :: { NaiveDate , NaiveTime , Weekday } ;
19+ use crate :: { NaiveDate , NaiveTime , Utc , Weekday } ;
2020
2121#[ cfg( feature = "alloc" ) ]
2222use super :: locales;
@@ -31,13 +31,13 @@ use locales::*;
3131/// This is normally constructed via `format` methods of each date and time type.
3232#[ cfg( feature = "alloc" ) ]
3333#[ derive( Debug ) ]
34- pub struct DelayedFormat < I > {
34+ pub struct DelayedFormat < I , Off = Utc > {
3535 /// The date view, if any.
3636 date : Option < NaiveDate > ,
3737 /// The time view, if any.
3838 time : Option < NaiveTime > ,
39- /// The name and local-to- UTC difference for the offset (timezone) , if any.
40- off : Option < ( String , FixedOffset ) > ,
39+ /// The offset from UTC, if any
40+ off : Option < Off > ,
4141 /// An iterator returning formatting items.
4242 items : I ,
4343 /// Locale used for text.
@@ -46,28 +46,17 @@ pub struct DelayedFormat<I> {
4646}
4747
4848#[ cfg( feature = "alloc" ) ]
49- impl < ' a , I : Iterator < Item = B > + Clone , B : Borrow < Item < ' a > > > DelayedFormat < I > {
49+ impl < ' a , I , B > DelayedFormat < I >
50+ where
51+ I : Iterator < Item = B > + Clone ,
52+ B : Borrow < Item < ' a > > ,
53+ {
5054 /// Makes a new `DelayedFormat` value out of local date and time.
5155 #[ must_use]
5256 pub fn new ( date : Option < NaiveDate > , time : Option < NaiveTime > , items : I ) -> DelayedFormat < I > {
5357 DelayedFormat { date, time, off : None , items, locale : default_locale ( ) }
5458 }
5559
56- /// Makes a new `DelayedFormat` value out of local date and time and UTC offset.
57- #[ must_use]
58- pub fn new_with_offset < Off > (
59- date : Option < NaiveDate > ,
60- time : Option < NaiveTime > ,
61- offset : & Off ,
62- items : I ,
63- ) -> DelayedFormat < I >
64- where
65- Off : Offset + Display ,
66- {
67- let name_and_diff = ( offset. to_string ( ) , offset. fix ( ) ) ;
68- DelayedFormat { date, time, off : Some ( name_and_diff) , items, locale : default_locale ( ) }
69- }
70-
7160 /// Makes a new `DelayedFormat` value out of local date and time and locale.
7261 #[ cfg( feature = "unstable-locales" ) ]
7362 #[ must_use]
@@ -79,22 +68,40 @@ impl<'a, I: Iterator<Item = B> + Clone, B: Borrow<Item<'a>>> DelayedFormat<I> {
7968 ) -> DelayedFormat < I > {
8069 DelayedFormat { date, time, off : None , items, locale }
8170 }
71+ }
72+
73+ #[ cfg( feature = "alloc" ) ]
74+ impl < ' a , I , B , Off > DelayedFormat < I , Off >
75+ where
76+ I : Iterator < Item = B > + Clone ,
77+ B : Borrow < Item < ' a > > ,
78+ Off : Offset + Display ,
79+ {
80+ /// Makes a new `DelayedFormat` value out of local date and time and UTC offset.
81+ #[ must_use]
82+ pub fn new_with_offset (
83+ date : Option < NaiveDate > ,
84+ time : Option < NaiveTime > ,
85+ offset : & Off ,
86+ items : I ,
87+ ) -> DelayedFormat < I , Off > {
88+ DelayedFormat { date, time, off : Some ( offset. clone ( ) ) , items, locale : default_locale ( ) }
89+ }
8290
8391 /// Makes a new `DelayedFormat` value out of local date and time, UTC offset and locale.
8492 #[ cfg( feature = "unstable-locales" ) ]
8593 #[ must_use]
86- pub fn new_with_offset_and_locale < Off > (
94+ pub fn new_with_offset_and_locale (
8795 date : Option < NaiveDate > ,
8896 time : Option < NaiveTime > ,
8997 offset : & Off ,
9098 items : I ,
9199 locale : Locale ,
92- ) -> DelayedFormat < I >
100+ ) -> DelayedFormat < I , Off >
93101 where
94102 Off : Offset + Display ,
95103 {
96- let name_and_diff = ( offset. to_string ( ) , offset. fix ( ) ) ;
97- DelayedFormat { date, time, off : Some ( name_and_diff) , items, locale }
104+ DelayedFormat { date, time, off : Some ( offset. clone ( ) ) , items, locale }
98105 }
99106
100107 fn format ( & self , w : & mut impl Write ) -> fmt:: Result {
@@ -191,7 +198,7 @@ impl<'a, I: Iterator<Item = B> + Clone, B: Borrow<Item<'a>>> DelayedFormat<I> {
191198 write_n ( w, 9 , ( t. nanosecond ( ) % 1_000_000_000 ) as i64 , pad, false )
192199 }
193200 ( Timestamp , Some ( d) , Some ( t) ) => {
194- let offset = self . off . as_ref ( ) . map ( |( _ , o ) | i64:: from ( o. local_minus_utc ( ) ) ) ;
201+ let offset = self . off . as_ref ( ) . map ( |o | i64:: from ( o. fix ( ) . local_minus_utc ( ) ) ) ;
195202 let timestamp = d. and_time ( t) . and_utc ( ) . timestamp ( ) - offset. unwrap_or ( 0 ) ;
196203 write_n ( w, 9 , timestamp, pad, false )
197204 }
@@ -265,50 +272,50 @@ impl<'a, I: Iterator<Item = B> + Clone, B: Borrow<Item<'a>>> DelayedFormat<I> {
265272 ( Internal ( InternalFixed { val : Nanosecond9NoDot } ) , _, Some ( t) , _) => {
266273 write ! ( w, "{:09}" , t. nanosecond( ) % 1_000_000_000 )
267274 }
268- ( TimezoneName , _, _, Some ( ( tz_name , _ ) ) ) => write ! ( w, "{}" , tz_name ) ,
269- ( TimezoneOffset | TimezoneOffsetZ , _, _, Some ( ( _ , off) ) ) => {
275+ ( TimezoneName , _, _, Some ( off ) ) => write ! ( w, "{}" , off ) ,
276+ ( TimezoneOffset | TimezoneOffsetZ , _, _, Some ( off) ) => {
270277 let offset_format = OffsetFormat {
271278 precision : OffsetPrecision :: Minutes ,
272279 colons : Colons :: Maybe ,
273280 allow_zulu : * spec == TimezoneOffsetZ ,
274281 padding : Pad :: Zero ,
275282 } ;
276- offset_format. format ( w, * off)
283+ offset_format. format ( w, off. fix ( ) )
277284 }
278- ( TimezoneOffsetColon | TimezoneOffsetColonZ , _, _, Some ( ( _ , off) ) ) => {
285+ ( TimezoneOffsetColon | TimezoneOffsetColonZ , _, _, Some ( off) ) => {
279286 let offset_format = OffsetFormat {
280287 precision : OffsetPrecision :: Minutes ,
281288 colons : Colons :: Colon ,
282289 allow_zulu : * spec == TimezoneOffsetColonZ ,
283290 padding : Pad :: Zero ,
284291 } ;
285- offset_format. format ( w, * off)
292+ offset_format. format ( w, off. fix ( ) )
286293 }
287- ( TimezoneOffsetDoubleColon , _, _, Some ( ( _ , off) ) ) => {
294+ ( TimezoneOffsetDoubleColon , _, _, Some ( off) ) => {
288295 let offset_format = OffsetFormat {
289296 precision : OffsetPrecision :: Seconds ,
290297 colons : Colons :: Colon ,
291298 allow_zulu : false ,
292299 padding : Pad :: Zero ,
293300 } ;
294- offset_format. format ( w, * off)
301+ offset_format. format ( w, off. fix ( ) )
295302 }
296- ( TimezoneOffsetTripleColon , _, _, Some ( ( _ , off) ) ) => {
303+ ( TimezoneOffsetTripleColon , _, _, Some ( off) ) => {
297304 let offset_format = OffsetFormat {
298305 precision : OffsetPrecision :: Hours ,
299306 colons : Colons :: None ,
300307 allow_zulu : false ,
301308 padding : Pad :: Zero ,
302309 } ;
303- offset_format. format ( w, * off)
310+ offset_format. format ( w, off. fix ( ) )
304311 }
305- ( RFC2822 , Some ( d) , Some ( t) , Some ( ( _ , off) ) ) => {
306- write_rfc2822 ( w, crate :: NaiveDateTime :: new ( d, t) , * off)
312+ ( RFC2822 , Some ( d) , Some ( t) , Some ( off) ) => {
313+ write_rfc2822 ( w, crate :: NaiveDateTime :: new ( d, t) , off. fix ( ) )
307314 }
308- ( RFC3339 , Some ( d) , Some ( t) , Some ( ( _ , off) ) ) => write_rfc3339 (
315+ ( RFC3339 , Some ( d) , Some ( t) , Some ( off) ) => write_rfc3339 (
309316 w,
310317 crate :: NaiveDateTime :: new ( d, t) ,
311- * off,
318+ off. fix ( ) ,
312319 SecondsFormat :: AutoSi ,
313320 false ,
314321 ) ,
@@ -318,7 +325,12 @@ impl<'a, I: Iterator<Item = B> + Clone, B: Borrow<Item<'a>>> DelayedFormat<I> {
318325}
319326
320327#[ cfg( feature = "alloc" ) ]
321- impl < ' a , I : Iterator < Item = B > + Clone , B : Borrow < Item < ' a > > > Display for DelayedFormat < I > {
328+ impl < ' a , I , B , Off > Display for DelayedFormat < I , Off >
329+ where
330+ I : Iterator < Item = B > + Clone ,
331+ B : Borrow < Item < ' a > > ,
332+ Off : Offset + Display ,
333+ {
322334 fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
323335 let mut result = String :: new ( ) ;
324336 self . format ( & mut result) ?;
@@ -344,7 +356,7 @@ where
344356 DelayedFormat {
345357 date : date. copied ( ) ,
346358 time : time. copied ( ) ,
347- off : off. cloned ( ) ,
359+ off : off. cloned ( ) . map ( | ( tz_name , offset ) | OffsetWrapper { offset , tz_name } ) ,
348360 items,
349361 locale : default_locale ( ) ,
350362 }
@@ -364,13 +376,35 @@ pub fn format_item(
364376 DelayedFormat {
365377 date : date. copied ( ) ,
366378 time : time. copied ( ) ,
367- off : off. cloned ( ) ,
379+ off : off. cloned ( ) . map ( | ( tz_name , offset ) | OffsetWrapper { offset , tz_name } ) ,
368380 items : [ item] . into_iter ( ) ,
369381 locale : default_locale ( ) ,
370382 }
371383 . fmt ( w)
372384}
373385
386+ /// Only used by the deprecated `format` and `format_item` functions.
387+ #[ cfg( feature = "alloc" ) ]
388+ #[ derive( Clone , Debug ) ]
389+ struct OffsetWrapper {
390+ offset : FixedOffset ,
391+ tz_name : String ,
392+ }
393+
394+ #[ cfg( feature = "alloc" ) ]
395+ impl Offset for OffsetWrapper {
396+ fn fix ( & self ) -> FixedOffset {
397+ self . offset
398+ }
399+ }
400+
401+ #[ cfg( feature = "alloc" ) ]
402+ impl Display for OffsetWrapper {
403+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
404+ f. write_str ( & self . tz_name )
405+ }
406+ }
407+
374408#[ cfg( any( feature = "alloc" , feature = "serde" ) ) ]
375409impl OffsetFormat {
376410 /// Writes an offset from UTC with the format defined by `self`.
0 commit comments