@@ -1365,56 +1365,64 @@ Examples of working with datetime objects:
13651365
13661366Using datetime with tzinfo:
13671367
1368- >>> from datetime import timedelta, datetime, tzinfo
1369- >>> class GMT1 (tzinfo ):
1368+ >>> from datetime import timedelta, datetime, tzinfo, timezone
1369+ >>> class KabulTz (tzinfo ):
1370+ ... # Kabul used +4 until 1945, when they moved to +4:30
1371+ ... UTC_MOVE_DATE = datetime(1944 , 12 , 31 , 20 , tzinfo = timezone.utc)
13701372 ... def utcoffset (self , dt ):
1371- ... return timedelta(hours = 1 ) + self .dst(dt)
1372- ... def dst (self , dt ):
1373- ... # DST starts last Sunday in March
1374- ... d = datetime(dt.year, 4 , 1 ) # ends last Sunday in October
1375- ... self .dston = d - timedelta(days = d.weekday() + 1 )
1376- ... d = datetime(dt.year, 11 , 1 )
1377- ... self .dstoff = d - timedelta(days = d.weekday() + 1 )
1378- ... if self .dston <= dt.replace(tzinfo = None ) < self .dstoff:
1379- ... return timedelta(hours = 1 )
1373+ ... if dt.year < 1945 :
1374+ ... return timedelta(hours = 4 )
1375+ ... elif (1945 , 1 , 1 , 0 , 0 ) <= dt.timetuple()[:5 ] < (1945 , 1 , 1 , 0 , 30 ):
1376+ ... # If dt falls in the imaginary range, use fold to decide how
1377+ ... # to resolve. See PEP495
1378+ ... return timedelta(hours = 4 , minutes = (30 if dt.fold else 0 ))
13801379 ... else :
1381- ... return timedelta(0 )
1382- ... def tzname (self ,dt ):
1383- ... return " GMT +1"
1380+ ... return timedelta(hours = 4 , minutes = 30 )
1381+ ...
1382+ ... def fromutc (self , dt ):
1383+ ... # A custom implementation is required for fromutc as
1384+ ... # the input to this function is a datetime with utc values
1385+ ... # but with a tzinfo set to self
1386+ ... # See datetime.astimezone or fromtimestamp
1387+ ...
1388+ ... # Follow same validations as in datetime.tzinfo
1389+ ... if not isinstance (dt, datetime):
1390+ ... raise TypeError (" fromutc() requires a datetime argument" )
1391+ ... if dt.tzinfo is not self :
1392+ ... raise ValueError (" dt.tzinfo is not self" )
1393+ ...
1394+ ... if dt.replace(tzinfo = timezone.utc) >= self .UTC_MOVE_DATE :
1395+ ... return dt + timedelta(hours = 4 , minutes = 30 )
1396+ ... else :
1397+ ... return dt + timedelta(hours = 4 )
13841398 ...
1385- >>> class GMT2 (tzinfo ):
1386- ... def utcoffset (self , dt ):
1387- ... return timedelta(hours = 2 ) + self .dst(dt)
13881399 ... def dst (self , dt ):
1389- ... d = datetime(dt.year, 4 , 1 )
1390- ... self .dston = d - timedelta(days = d.weekday() + 1 )
1391- ... d = datetime(dt.year, 11 , 1 )
1392- ... self .dstoff = d - timedelta(days = d.weekday() + 1 )
1393- ... if self .dston <= dt.replace(tzinfo = None ) < self .dstoff:
1394- ... return timedelta(hours = 1 )
1400+ ... return timedelta(0 )
1401+ ...
1402+ ... def tzname (self , dt ):
1403+ ... if dt >= self .UTC_MOVE_DATE :
1404+ ... return " +04:30"
13951405 ... else :
1396- ... return timedelta(0 )
1397- ... def tzname (self ,dt ):
1398- ... return " GMT +2"
1406+ ... return " +04"
13991407 ...
1400- >>> gmt1 = GMT1()
1401- >>> # Daylight Saving Time
1402- >>> dt1 = datetime( 2006 , 11 , 21 , 16 , 30 , tzinfo = gmt1)
1403- >>> dt1.dst ()
1404- datetime.timedelta(0)
1405- >>> dt1.utcoffset( )
1406- datetime.timedelta(seconds=3600 )
1407- >>> dt2 = datetime( 2006 , 6 , 14 , 13 , 0 , tzinfo = gmt1)
1408- >>> dt2.dst()
1409- datetime.timedelta(seconds=3600 )
1410- >>> dt2.utcoffset()
1411- datetime.timedelta(seconds=7200)
1408+ ... def __repr__ ( self ):
1409+ ... return f " { self . __class__ . __name__ } () "
1410+ ...
1411+ >>> tz1 = KabulTz ()
1412+ >>> # Datetime before the change
1413+ >>> dt1 = datetime( 1900 , 11 , 21 , 16 , 30 , tzinfo = tz1 )
1414+ >>> print (dt1.utcoffset() )
1415+ 4:00:00
1416+ >>> # Datetime after the change
1417+ >>> dt2 = datetime( 2006 , 6 , 14 , 13 , 0 , tzinfo = tz1 )
1418+ >>> print ( dt2.utcoffset() )
1419+ 4:30:00
14121420 >>> # Convert datetime to another time zone
1413- >>> dt3 = dt2.astimezone(GMT2() )
1414- >>> dt3 # doctest: +ELLIPSIS
1415- datetime.datetime(2006, 6, 14, 14, 0 , tzinfo=<GMT2 object at 0x...> )
1416- >>> dt2 # doctest: +ELLIPSIS
1417- datetime.datetime(2006, 6, 14, 13, 0, tzinfo=<GMT1 object at 0x...> )
1421+ >>> dt3 = dt2.astimezone(timezone.utc )
1422+ >>> dt3
1423+ datetime.datetime(2006, 6, 14, 8, 30 , tzinfo=datetime.timezone.utc )
1424+ >>> dt2
1425+ datetime.datetime(2006, 6, 14, 13, 0, tzinfo=KabulTz() )
14181426 >>> dt2.utctimetuple() == dt3.utctimetuple()
14191427 True
14201428
@@ -1656,26 +1664,27 @@ Instance methods:
16561664Example:
16571665
16581666 >>> from datetime import time, tzinfo, timedelta
1659- >>> class GMT1 (tzinfo ):
1667+ >>> class TZ1 (tzinfo ):
16601668 ... def utcoffset (self , dt ):
16611669 ... return timedelta(hours = 1 )
16621670 ... def dst (self , dt ):
16631671 ... return timedelta(0 )
16641672 ... def tzname (self ,dt ):
1665- ... return " Europe/Prague"
1673+ ... return " +01:00"
1674+ ... def __repr__ (self ):
1675+ ... return f " { self .__class__ .__name__ } () "
16661676 ...
1667- >>> t = time(12 , 10 , 30 , tzinfo = GMT1())
1668- >>> t # doctest: +ELLIPSIS
1669- datetime.time(12, 10, 30, tzinfo=<GMT1 object at 0x...>)
1670- >>> gmt = GMT1()
1677+ >>> t = time(12 , 10 , 30 , tzinfo = TZ1())
1678+ >>> t
1679+ datetime.time(12, 10, 30, tzinfo=TZ1())
16711680 >>> t.isoformat()
16721681 '12:10:30+01:00'
16731682 >>> t.dst()
16741683 datetime.timedelta(0)
16751684 >>> t.tzname()
1676- 'Europe/Prague '
1685+ '+01:00 '
16771686 >>> t.strftime(" %H:%M:%S %Z" )
1678- '12:10:30 Europe/Prague '
1687+ '12:10:30 +01:00 '
16791688 >>> ' The {} is {: %H:%M} .' .format(" time" , t)
16801689 'The time is 12:10.'
16811690
0 commit comments