@@ -19,6 +19,25 @@ impl crate::Time {
1919 pub fn into_civil_time ( self ) -> Option < jiff:: civil:: Time > {
2020 jiff:: civil:: Time :: try_from ( self ) . ok ( )
2121 }
22+
23+ pub fn jiff_fixed_tz ( o : Option < crate :: Offset > ) -> Result < jiff:: tz:: TimeZone , jiff:: Error > {
24+ let o_seconds = if let Some ( o) = o {
25+ match o {
26+ Offset :: Fixed {
27+ hours,
28+ minutes,
29+ critical : _,
30+ } => hours * 3600 + minutes * 60 ,
31+ Offset :: LocalUnknown { critical : _ } => 0 ,
32+ }
33+ } else {
34+ 0
35+ } ;
36+
37+ Ok ( jiff:: tz:: TimeZone :: fixed ( jiff:: tz:: Offset :: from_seconds (
38+ o_seconds. try_into ( ) . unwrap ( ) ,
39+ ) ?) )
40+ }
2241}
2342
2443impl TryFrom < crate :: Date > for jiff:: civil:: Date {
@@ -86,21 +105,19 @@ impl TryFrom<crate::DateTime> for jiff::Zoned {
86105 let naive_time = jiff:: civil:: Time :: try_from ( dt. time . clone ( ) ) ?;
87106 let naive_datetime = naive_date. to_datetime ( naive_time) ;
88107
89- let o_seconds = match dt. time . offset {
90- Some ( o) => match o {
91- Offset :: Fixed {
92- hours,
93- minutes,
94- critical : _,
95- } => hours * 3600 + minutes * 60 ,
96- Offset :: LocalUnknown { critical : _ } => 0 ,
97- } ,
98- None => 0 ,
99- } ;
108+ let mut tz = crate :: Time :: jiff_fixed_tz ( dt. time . offset ) ?;
100109
101- let offset = jiff:: tz:: Offset :: from_seconds ( o_seconds. try_into ( ) . unwrap ( ) ) ?;
110+ if let Some ( z) = dt. time . time_zone {
111+ match z {
112+ crate :: TimeZone :: Named { zone } => {
113+ tz = jiff:: tz:: TimeZone :: get ( & zone. identifier ) ?;
114+ }
115+ crate :: TimeZone :: Fixed { offset } => {
116+ tz = crate :: Time :: jiff_fixed_tz ( Some ( offset) ) ?;
117+ }
118+ }
119+ }
102120
103- let tz = jiff:: tz:: TimeZone :: fixed ( offset) ;
104121 naive_datetime. to_zoned ( tz)
105122 }
106123}
@@ -138,6 +155,8 @@ impl TryFrom<crate::Duration> for jiff::Span {
138155
139156#[ cfg( test) ]
140157mod date_and_time {
158+ use crate :: Offset ;
159+ use crate :: TimeZone ;
141160 use core:: convert:: TryFrom ;
142161
143162 #[ test]
@@ -190,13 +209,129 @@ mod date_and_time {
190209 } ,
191210 } ;
192211
193- let datetime = time:: PrimitiveDateTime :: try_from ( dt) . unwrap ( ) ;
212+ let datetime = jiff:: Zoned :: try_from ( dt) . unwrap ( ) ;
213+ assert_eq ! ( datetime. year( ) , 2024 ) ;
214+ assert_eq ! ( datetime. month( ) as u8 , 3 ) ;
215+ assert_eq ! ( datetime. day( ) , 9 ) ;
216+ assert_eq ! ( datetime. hour( ) , 23 ) ;
217+ assert_eq ! ( datetime. minute( ) , 40 ) ;
218+ assert_eq ! ( datetime. second( ) , 0 ) ;
219+ }
220+
221+ #[ test]
222+ fn datetime_from_ymd_hms_with_offset ( ) {
223+ let dt = crate :: DateTime {
224+ date : crate :: Date :: YMD {
225+ year : 2024 ,
226+ month : 3 ,
227+ day : 9 ,
228+ } ,
229+ time : crate :: Time {
230+ hour : 23 ,
231+ minute : 40 ,
232+ second : 0 ,
233+ millisecond : 0 ,
234+ offset : Some ( Offset :: Fixed {
235+ hours : 2 ,
236+ minutes : 0 ,
237+ critical : false ,
238+ } ) ,
239+ time_zone : None ,
240+ calendar : None ,
241+ } ,
242+ } ;
243+
244+ let datetime = jiff:: Zoned :: try_from ( dt) . unwrap ( ) ;
245+ assert_eq ! ( datetime. year( ) , 2024 ) ;
246+ assert_eq ! ( datetime. month( ) as u8 , 3 ) ;
247+ assert_eq ! ( datetime. day( ) , 9 ) ;
248+ assert_eq ! ( datetime. hour( ) , 23 ) ;
249+ assert_eq ! ( datetime. minute( ) , 40 ) ;
250+ assert_eq ! ( datetime. second( ) , 0 ) ;
251+ assert_eq ! (
252+ datetime. time_zone( ) . to_fixed_offset( ) . unwrap( ) . seconds( ) ,
253+ 2 * 3600
254+ ) ;
255+ }
256+
257+ #[ test]
258+ fn datetime_from_ymd_hms_with_matching_offset ( ) {
259+ let dt = crate :: DateTime {
260+ date : crate :: Date :: YMD {
261+ year : 2024 ,
262+ month : 3 ,
263+ day : 9 ,
264+ } ,
265+ time : crate :: Time {
266+ hour : 23 ,
267+ minute : 40 ,
268+ second : 0 ,
269+ millisecond : 0 ,
270+ offset : Some ( Offset :: Fixed {
271+ hours : 2 ,
272+ minutes : 0 ,
273+ critical : false ,
274+ } ) ,
275+ time_zone : Some ( TimeZone :: Fixed {
276+ offset : Offset :: Fixed {
277+ hours : 3 ,
278+ minutes : 0 ,
279+ critical : false ,
280+ } ,
281+ } ) ,
282+ calendar : None ,
283+ } ,
284+ } ;
285+
286+ let datetime = jiff:: Zoned :: try_from ( dt) . unwrap ( ) ;
287+ assert_eq ! ( datetime. year( ) , 2024 ) ;
288+ assert_eq ! ( datetime. month( ) as u8 , 3 ) ;
289+ assert_eq ! ( datetime. day( ) , 9 ) ;
290+ assert_eq ! ( datetime. hour( ) , 23 ) ;
291+ assert_eq ! ( datetime. minute( ) , 40 ) ;
292+ assert_eq ! ( datetime. second( ) , 0 ) ;
293+ assert_eq ! (
294+ datetime. time_zone( ) . to_fixed_offset( ) . unwrap( ) . seconds( ) ,
295+ 3 * 3600
296+ ) ;
297+ }
298+
299+ #[ test]
300+ fn datetime_from_ymd_hms_with_named_zone ( ) {
301+ let dt = crate :: DateTime {
302+ date : crate :: Date :: YMD {
303+ year : 2024 ,
304+ month : 3 ,
305+ day : 9 ,
306+ } ,
307+ time : crate :: Time {
308+ hour : 23 ,
309+ minute : 40 ,
310+ second : 0 ,
311+ millisecond : 0 ,
312+ offset : Some ( Offset :: Fixed {
313+ hours : 2 ,
314+ minutes : 0 ,
315+ critical : false ,
316+ } ) ,
317+ time_zone : Some ( TimeZone :: Named {
318+ zone : crate :: NamedTimeZone {
319+ identifier : "Europe/Berlin" . to_string ( ) ,
320+ critical : false ,
321+ } ,
322+ } ) ,
323+ calendar : None ,
324+ } ,
325+ } ;
326+
327+ let datetime = jiff:: Zoned :: try_from ( dt) . unwrap ( ) ;
194328 assert_eq ! ( datetime. year( ) , 2024 ) ;
195329 assert_eq ! ( datetime. month( ) as u8 , 3 ) ;
196330 assert_eq ! ( datetime. day( ) , 9 ) ;
197331 assert_eq ! ( datetime. hour( ) , 23 ) ;
198332 assert_eq ! ( datetime. minute( ) , 40 ) ;
199333 assert_eq ! ( datetime. second( ) , 0 ) ;
334+ assert_eq ! ( datetime. time_zone( ) . iana_name( ) . unwrap( ) , "Europe/Berlin" ) ;
200335 }
201336
202337 #[ test]
0 commit comments