@@ -6,15 +6,15 @@ use crate::sync::GILOnceCell;
6
6
#[ cfg( not( Py_LIMITED_API ) ) ]
7
7
use crate :: types:: datetime:: timezone_from_offset;
8
8
#[ cfg( Py_LIMITED_API ) ]
9
- use crate :: types:: datetime_abi:: { check_type, DatetimeTypes } ;
9
+ use crate :: types:: datetime_abi:: { check_type, timezone_utc , DatetimeTypes } ;
10
10
#[ cfg( Py_LIMITED_API ) ]
11
11
use crate :: types:: IntoPyDict ;
12
- use crate :: types:: { PyAnyMethods , PyNone , PyType } ;
13
12
#[ cfg( not( Py_LIMITED_API ) ) ]
14
13
use crate :: types:: {
15
- PyDate , PyDateAccess , PyDateTime , PyDelta , PyDeltaAccess , PyTime , PyTimeAccess , PyTzInfo ,
16
- PyTzInfoAccess ,
14
+ timezone_utc , PyDate , PyDateAccess , PyDateTime , PyDelta , PyDeltaAccess , PyTime , PyTimeAccess ,
15
+ PyTzInfo , PyTzInfoAccess ,
17
16
} ;
17
+ use crate :: types:: { PyAnyMethods , PyNone , PyType } ;
18
18
use crate :: { intern, Bound , FromPyObject , IntoPyObject , Py , PyAny , PyErr , PyResult , Python } ;
19
19
use jiff:: civil:: { Date , DateTime , Time } ;
20
20
use jiff:: tz:: { AmbiguousOffset , Offset , TimeZone } ;
@@ -410,7 +410,9 @@ impl<'py> IntoPyObject<'py> for &TimeZone {
410
410
type Error = PyErr ;
411
411
412
412
fn into_pyobject ( self , py : Python < ' py > ) -> Result < Self :: Output , Self :: Error > {
413
- if let Some ( iana_name) = self . iana_name ( ) {
413
+ if self == & TimeZone :: UTC {
414
+ Ok ( timezone_utc ( py) )
415
+ } else if let Some ( iana_name) = self . iana_name ( ) {
414
416
static ZONE_INFO : GILOnceCell < Py < PyType > > = GILOnceCell :: new ( ) ;
415
417
let tz = ZONE_INFO
416
418
. import ( py, "zoneinfo" , "ZoneInfo" )
@@ -433,6 +435,12 @@ impl<'py> IntoPyObject<'py> for &TimeZone {
433
435
434
436
impl < ' py > FromPyObject < ' py > for TimeZone {
435
437
fn extract_bound ( ob : & Bound < ' py , PyAny > ) -> PyResult < Self > {
438
+ #[ cfg( not( Py_LIMITED_API ) ) ]
439
+ let ob = ob. downcast :: < PyTzInfo > ( ) ?;
440
+
441
+ #[ cfg( Py_LIMITED_API ) ]
442
+ check_type ( ob, & DatetimeTypes :: get ( ob. py ( ) ) . tzinfo , "PyTzInfo" ) ?;
443
+
436
444
let attr = intern ! ( ob. py( ) , "key" ) ;
437
445
if ob. hasattr ( attr) ? {
438
446
Ok ( TimeZone :: get ( & ob. getattr ( attr) ?. extract :: < PyBackedStr > ( ) ?) ?)
@@ -451,6 +459,10 @@ impl<'py> IntoPyObject<'py> for &Offset {
451
459
type Error = PyErr ;
452
460
453
461
fn into_pyobject ( self , py : Python < ' py > ) -> Result < Self :: Output , Self :: Error > {
462
+ if self == & Offset :: UTC {
463
+ return Ok ( timezone_utc ( py) ) ;
464
+ }
465
+
454
466
let delta = self . duration_since ( Offset :: UTC ) . into_pyobject ( py) ?;
455
467
456
468
#[ cfg( not( Py_LIMITED_API ) ) ]
@@ -587,6 +599,7 @@ impl<'py> IntoPyObject<'py> for Span {
587
599
type Error = PyErr ;
588
600
589
601
fn into_pyobject ( self , py : Python < ' py > ) -> Result < Self :: Output , Self :: Error > {
602
+ // This can fail if this Span contains units greater than days.
590
603
let duration: SignedDuration = self . try_into ( ) ?;
591
604
duration. into_pyobject ( py)
592
605
}
0 commit comments