@@ -161,13 +161,14 @@ def _build_struct_time(y, m, d, hh, mm, ss, dstflag):
161161 dnum = _days_before_month (y , m ) + d
162162 return _time .struct_time ((y , m , d , hh , mm , ss , wday , dnum , dstflag ))
163163
164- def _format_time (hh , mm , ss , us , timespec = 'auto' ):
164+ def _format_time (hh , mm , ss , us , sus , timespec = 'auto' ):
165165 specs = {
166166 'hours' : '{:02d}' ,
167167 'minutes' : '{:02d}:{:02d}' ,
168168 'seconds' : '{:02d}:{:02d}:{:02d}' ,
169169 'milliseconds' : '{:02d}:{:02d}:{:02d}.{:03d}' ,
170- 'microseconds' : '{:02d}:{:02d}:{:02d}.{:06d}'
170+ 'microseconds' : '{:02d}:{:02d}:{:02d}.{:06d}' ,
171+ 'submicroseconds' : '{:02d}:{:02d}:{:02d}.{:06d}{:03d}' ,
171172 }
172173
173174 if timespec == 'auto' :
@@ -180,7 +181,7 @@ def _format_time(hh, mm, ss, us, timespec='auto'):
180181 except KeyError :
181182 raise ValueError ('Unknown timespec value' )
182183 else :
183- return fmt .format (hh , mm , ss , us )
184+ return fmt .format (hh , mm , ss , us , sus )
184185
185186def _format_offset (off , sep = ':' ):
186187 s = ''
@@ -578,11 +579,12 @@ def _check_date_fields(year, month, day):
578579 raise ValueError ('day must be in 1..%d' % dim , day )
579580 return year , month , day
580581
581- def _check_time_fields (hour , minute , second , microsecond , fold ):
582+ def _check_time_fields (hour , minute , second , microsecond , submicrosecond , fold ):
582583 hour = _index (hour )
583584 minute = _index (minute )
584585 second = _index (second )
585586 microsecond = _index (microsecond )
587+ submicrosecond = _index (submicrosecond )
586588 if not 0 <= hour <= 23 :
587589 raise ValueError ('hour must be in 0..23' , hour )
588590 if not 0 <= minute <= 59 :
@@ -591,9 +593,11 @@ def _check_time_fields(hour, minute, second, microsecond, fold):
591593 raise ValueError ('second must be in 0..59' , second )
592594 if not 0 <= microsecond <= 999999 :
593595 raise ValueError ('microsecond must be in 0..999999' , microsecond )
596+ if not 0 <= submicrosecond <= 999 :
597+ raise ValueError ('Currently submicrosecond must be in 0..999' , submicrosecond )
594598 if fold not in (0 , 1 ):
595599 raise ValueError ('fold must be either 0 or 1' , fold )
596- return hour , minute , second , microsecond , fold
600+ return hour , minute , second , microsecond , submicrosecond , fold
597601
598602def _check_tzinfo_arg (tz ):
599603 if tz is not None and not isinstance (tz , tzinfo ):
@@ -1350,7 +1354,15 @@ def __reduce__(self):
13501354 args = getinitargs ()
13511355 else :
13521356 args = ()
1353- return (self .__class__ , args , self .__getstate__ ())
1357+ getstate = getattr (self , "__getstate__" , None )
1358+ if getstate :
1359+ state = getstate ()
1360+ else :
1361+ state = getattr (self , "__dict__" , None )
1362+ if state is None :
1363+ return (self .__class__ , args )
1364+ else :
1365+ return (self .__class__ , args , state )
13541366
13551367
13561368class IsoCalendarDate (tuple ):
@@ -1408,9 +1420,9 @@ class time:
14081420 Properties (readonly):
14091421 hour, minute, second, microsecond, tzinfo, fold
14101422 """
1411- __slots__ = '_hour' , '_minute' , '_second' , '_microsecond' , '_tzinfo' , '_hashcode' , '_fold'
1423+ __slots__ = '_hour' , '_minute' , '_second' , '_microsecond' , '_submicrosecond' , ' _tzinfo' , '_hashcode' , '_fold'
14121424
1413- def __new__ (cls , hour = 0 , minute = 0 , second = 0 , microsecond = 0 , tzinfo = None , * , fold = 0 ):
1425+ def __new__ (cls , hour = 0 , minute = 0 , second = 0 , microsecond = 0 , tzinfo = None , * , fold = 0 , submicrosecond = 0 ):
14141426 """Constructor.
14151427
14161428 Arguments:
@@ -1436,14 +1448,15 @@ def __new__(cls, hour=0, minute=0, second=0, microsecond=0, tzinfo=None, *, fold
14361448 self .__setstate (hour , minute or None )
14371449 self ._hashcode = - 1
14381450 return self
1439- hour , minute , second , microsecond , fold = _check_time_fields (
1440- hour , minute , second , microsecond , fold )
1451+ hour , minute , second , microsecond , submicrosecond , fold = _check_time_fields (
1452+ hour , minute , second , microsecond , submicrosecond , fold )
14411453 _check_tzinfo_arg (tzinfo )
14421454 self = object .__new__ (cls )
14431455 self ._hour = hour
14441456 self ._minute = minute
14451457 self ._second = second
14461458 self ._microsecond = microsecond
1459+ self ._submicrosecond = submicrosecond
14471460 self ._tzinfo = tzinfo
14481461 self ._hashcode = - 1
14491462 self ._fold = fold
@@ -1476,6 +1489,11 @@ def microsecond(self):
14761489 """microsecond (0-999999)"""
14771490 return self ._microsecond
14781491
1492+ @property
1493+ def submicrosecond (self ):
1494+ """submicrosecond (0-999)"""
1495+ return self ._submicrosecond
1496+
14791497 @property
14801498 def tzinfo (self ):
14811499 """timezone info object"""
@@ -1563,9 +1581,9 @@ def __hash__(self):
15631581 assert not m % timedelta (minutes = 1 ), "whole minute"
15641582 m //= timedelta (minutes = 1 )
15651583 if 0 <= h < 24 :
1566- self ._hashcode = hash (time (h , m , self .second , self .microsecond ))
1584+ self ._hashcode = hash (time (h , m , self .second , self .microsecond , self . submicrosecond ))
15671585 else :
1568- self ._hashcode = hash ((h , m , self .second , self .microsecond ))
1586+ self ._hashcode = hash ((h , m , self .second , self .microsecond , self . submicrosecond ))
15691587 return self ._hashcode
15701588
15711589 # Conversion to string
@@ -1605,7 +1623,7 @@ def isoformat(self, timespec='auto'):
16051623 'minutes', 'seconds', 'milliseconds' and 'microseconds'.
16061624 """
16071625 s = _format_time (self ._hour , self ._minute , self ._second ,
1608- self ._microsecond , timespec )
1626+ self ._microsecond , self . _submicrosecond , timespec )
16091627 tz = self ._tzstr ()
16101628 if tz :
16111629 s += tz
@@ -1755,7 +1773,7 @@ class datetime(date):
17551773 __slots__ = time .__slots__
17561774
17571775 def __new__ (cls , year , month = None , day = None , hour = 0 , minute = 0 , second = 0 ,
1758- microsecond = 0 , tzinfo = None , * , fold = 0 ):
1776+ microsecond = 0 , tzinfo = None , * , fold = 0 , submicrosecond = 0 ):
17591777 if (isinstance (year , (bytes , str )) and len (year ) == 10 and
17601778 1 <= ord (year [2 :3 ])& 0x7F <= 12 ):
17611779 # Pickle support
@@ -1773,8 +1791,8 @@ def __new__(cls, year, month=None, day=None, hour=0, minute=0, second=0,
17731791 self ._hashcode = - 1
17741792 return self
17751793 year , month , day = _check_date_fields (year , month , day )
1776- hour , minute , second , microsecond , fold = _check_time_fields (
1777- hour , minute , second , microsecond , fold )
1794+ hour , minute , second , microsecond , submicrosecond , fold = _check_time_fields (
1795+ hour , minute , second , microsecond , submicrosecond , fold )
17781796 _check_tzinfo_arg (tzinfo )
17791797 self = object .__new__ (cls )
17801798 self ._year = year
@@ -1784,6 +1802,7 @@ def __new__(cls, year, month=None, day=None, hour=0, minute=0, second=0,
17841802 self ._minute = minute
17851803 self ._second = second
17861804 self ._microsecond = microsecond
1805+ self ._submicrosecond = submicrosecond
17871806 self ._tzinfo = tzinfo
17881807 self ._hashcode = - 1
17891808 self ._fold = fold
@@ -1825,19 +1844,13 @@ def _fromtimestamp(cls, t, utc, tz):
18251844
18261845 A timezone info object may be passed in as well.
18271846 """
1828- frac , t = _math .modf (t )
1829- us = round (frac * 1e6 )
1830- if us >= 1000000 :
1831- t += 1
1832- us -= 1000000
1833- elif us < 0 :
1834- t -= 1
1835- us += 1000000
18361847
1848+ t = str (t )
1849+ t , us , sus = map (int , [t [:- 9 ], t [- 9 :- 3 ], t [- 3 :]])
18371850 converter = _time .gmtime if utc else _time .localtime
18381851 y , m , d , hh , mm , ss , weekday , jday , dst = converter (t )
18391852 ss = min (ss , 59 ) # clamp out leap seconds if the platform has them
1840- result = cls (y , m , d , hh , mm , ss , us , tz )
1853+ result = cls (y , m , d , hh , mm , ss , us , tz , submicrosecond = sus )
18411854 if tz is None and not utc :
18421855 # As of version 2015f max fold in IANA database is
18431856 # 23 hours at 1969-09-30 13:00:00 in Kwajalein.
@@ -1852,11 +1865,11 @@ def _fromtimestamp(cls, t, utc, tz):
18521865 return result
18531866
18541867 y , m , d , hh , mm , ss = converter (t - max_fold_seconds )[:6 ]
1855- probe1 = cls (y , m , d , hh , mm , ss , us , tz )
1868+ probe1 = cls (y , m , d , hh , mm , ss , us , tz , submicrosecond = sus )
18561869 trans = result - probe1 - timedelta (0 , max_fold_seconds )
18571870 if trans .days < 0 :
18581871 y , m , d , hh , mm , ss = converter (t + trans // timedelta (0 , 1 ))[:6 ]
1859- probe2 = cls (y , m , d , hh , mm , ss , us , tz )
1872+ probe2 = cls (y , m , d , hh , mm , ss , us , tz , submicrosecond = sus )
18601873 if probe2 == result :
18611874 result ._fold = 1
18621875 elif tz is not None :
@@ -1888,7 +1901,7 @@ def utcfromtimestamp(cls, t):
18881901 @classmethod
18891902 def now (cls , tz = None ):
18901903 "Construct a datetime from time.time() and optional time zone info."
1891- t = _time .time ()
1904+ t = _time .time_ns ()
18921905 return cls .fromtimestamp (t , tz )
18931906
18941907 @classmethod
@@ -1901,7 +1914,7 @@ def utcnow(cls):
19011914 "datetime.datetime.now(datetime.UTC)." ,
19021915 DeprecationWarning ,
19031916 stacklevel = 2 )
1904- t = _time .time ()
1917+ t = _time .time_ns ()
19051918 return cls ._fromtimestamp (t , True , None )
19061919
19071920 @classmethod
@@ -2142,7 +2155,7 @@ def isoformat(self, sep='T', timespec='auto'):
21422155 """
21432156 s = ("%04d-%02d-%02d%c" % (self ._year , self ._month , self ._day , sep ) +
21442157 _format_time (self ._hour , self ._minute , self ._second ,
2145- self ._microsecond , timespec ))
2158+ self ._microsecond , self . _submicrosecond , timespec ))
21462159
21472160 off = self .utcoffset ()
21482161 tz = _format_offset (off )
0 commit comments