Skip to content

Commit bf52092

Browse files
authored
Merge branch 'micropython:master' into patch-1
2 parents 746059e + 3eaf027 commit bf52092

File tree

7 files changed

+162
-216
lines changed

7 files changed

+162
-216
lines changed

python-stdlib/datetime/datetime.py

Lines changed: 64 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,22 @@
11
# datetime.py
22

3-
import time as _tmod
4-
5-
_DBM = (0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334)
6-
_DIM = (0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31)
7-
_TIME_SPEC = ("auto", "hours", "minutes", "seconds", "milliseconds", "microseconds")
3+
import time as _t
84

95

106
def _leap(y):
117
return y % 4 == 0 and (y % 100 != 0 or y % 400 == 0)
128

139

14-
def _dby(y):
15-
# year -> number of days before January 1st of year.
16-
Y = y - 1
17-
return Y * 365 + Y // 4 - Y // 100 + Y // 400
18-
19-
2010
def _dim(y, m):
2111
# year, month -> number of days in that month in that year.
2212
if m == 2 and _leap(y):
2313
return 29
24-
return _DIM[m]
14+
return (0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31)[m]
2515

2616

2717
def _dbm(y, m):
2818
# year, month -> number of days in year preceding first day of month.
29-
return _DBM[m] + (m > 2 and _leap(y))
30-
31-
32-
def _ymd2o(y, m, d):
33-
# y, month, day -> ordinal, considering 01-Jan-0001 as day 1.
34-
return _dby(y) + _dbm(y, m) + d
19+
return (0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334)[m] + (m > 2 and _leap(y))
3520

3621

3722
def _o2ymd(n):
@@ -73,7 +58,7 @@ def total_seconds(self):
7358

7459
@property
7560
def days(self):
76-
return self._tuple(2)[0]
61+
return self._tuple(1)
7762

7863
@property
7964
def seconds(self):
@@ -145,17 +130,17 @@ def __bool__(self):
145130
return self._us != 0
146131

147132
def __str__(self):
148-
return self._format(0x40)
133+
return self._fmt(0x40)
149134

150135
def __hash__(self):
151136
if not hasattr(self, "_hash"):
152137
self._hash = hash(self._us)
153138
return self._hash
154139

155140
def isoformat(self):
156-
return self._format(0)
141+
return self._fmt(0)
157142

158-
def _format(self, spec=0):
143+
def _fmt(self, spec=0):
159144
if self._us >= 0:
160145
td = self
161146
g = ""
@@ -201,8 +186,8 @@ def tuple(self):
201186

202187
def _tuple(self, n):
203188
d, us = divmod(self._us, 86_400_000_000)
204-
if n == 2:
205-
return d, us
189+
if n == 1:
190+
return d
206191
s, us = divmod(us, 1_000_000)
207192
if n == 3:
208193
return d, s, us
@@ -241,7 +226,7 @@ def fromutc(self, dt):
241226
return dt + dtdst
242227

243228
def isoformat(self, dt):
244-
return self.utcoffset(dt)._format(0x12)
229+
return self.utcoffset(dt)._fmt(0x12)
245230

246231

247232
class timezone(tzinfo):
@@ -276,7 +261,7 @@ def dst(self, dt):
276261
def tzname(self, dt):
277262
if self._name:
278263
return self._name
279-
return self._offset._format(0x22)
264+
return self._offset._fmt(0x22)
280265

281266
def fromutc(self, dt):
282267
return dt + self._offset
@@ -287,7 +272,11 @@ def fromutc(self, dt):
287272

288273
def _date(y, m, d):
289274
if MINYEAR <= y <= MAXYEAR and 1 <= m <= 12 and 1 <= d <= _dim(y, m):
290-
return _ymd2o(y, m, d)
275+
# year -> number of days before January 1st of year.
276+
Y = y - 1
277+
_dby = Y * 365 + Y // 4 - Y // 100 + Y // 400
278+
# y, month, day -> ordinal, considering 01-Jan-0001 as day 1.
279+
return _dby + _dbm(y, m) + d
291280
elif y == 0 and m == 0 and 1 <= d <= 3_652_059:
292281
return d
293282
else:
@@ -310,11 +299,11 @@ def __init__(self, year, month, day):
310299

311300
@classmethod
312301
def fromtimestamp(cls, ts):
313-
return cls(*_tmod.localtime(ts)[:3])
302+
return cls(*_t.localtime(ts)[:3])
314303

315304
@classmethod
316305
def today(cls):
317-
return cls(*_tmod.localtime()[:3])
306+
return cls(*_t.localtime()[:3])
318307

319308
@classmethod
320309
def fromordinal(cls, n):
@@ -490,7 +479,9 @@ def _iso2t(s):
490479

491480

492481
def _t2iso(td, timespec, dt, tz):
493-
s = td._format(_TIME_SPEC.index(timespec))
482+
s = td._fmt(
483+
("auto", "hours", "minutes", "seconds", "milliseconds", "microseconds").index(timespec)
484+
)
494485
if tz is not None:
495486
s += tz.isoformat(dt)
496487
return s
@@ -633,15 +624,18 @@ def fromtimestamp(cls, ts, tz=None):
633624
else:
634625
us = 0
635626
if tz is None:
636-
raise NotImplementedError
627+
dt = cls(*_t.localtime(ts)[:6], microsecond=us, tzinfo=tz)
628+
s = (dt - datetime(*_t.localtime(ts - 86400)[:6]))._us // 1_000_000 - 86400
629+
if s < 0 and dt == datetime(*_t.localtime(ts + s)[:6]):
630+
dt._fd = 1
637631
else:
638-
dt = cls(*_tmod.gmtime(ts)[:6], microsecond=us, tzinfo=tz)
632+
dt = cls(*_t.gmtime(ts)[:6], microsecond=us, tzinfo=tz)
639633
dt = tz.fromutc(dt)
640634
return dt
641635

642636
@classmethod
643637
def now(cls, tz=None):
644-
return cls.fromtimestamp(_tmod.time(), tz)
638+
return cls.fromtimestamp(_t.time(), tz)
645639

646640
@classmethod
647641
def fromordinal(cls, n):
@@ -810,13 +804,45 @@ def astimezone(self, tz=None):
810804
return self
811805
_tz = self._tz
812806
if _tz is None:
813-
raise NotImplementedError
807+
ts = int(self._mktime())
808+
os = datetime(*_t.localtime(ts)[:6]) - datetime(*_t.gmtime(ts)[:6])
814809
else:
815810
os = _tz.utcoffset(self)
816811
utc = self - os
817812
utc = utc.replace(tzinfo=tz)
818813
return tz.fromutc(utc)
819814

815+
def _mktime(self):
816+
def local(u):
817+
return (datetime(*_t.localtime(u)[:6]) - epoch)._us // 1_000_000
818+
819+
epoch = datetime.EPOCH.replace(tzinfo=None)
820+
t, us = divmod((self - epoch)._us, 1_000_000)
821+
ts = None
822+
823+
a = local(t) - t
824+
u1 = t - a
825+
t1 = local(u1)
826+
if t1 == t:
827+
u2 = u1 + (86400 if self.fold else -86400)
828+
b = local(u2) - u2
829+
if a == b:
830+
ts = u1
831+
else:
832+
b = t1 - u1
833+
if ts is None:
834+
u2 = t - b
835+
t2 = local(u2)
836+
if t2 == t:
837+
ts = u2
838+
elif t1 == t:
839+
ts = u1
840+
elif self.fold:
841+
ts = min(u1, u2)
842+
else:
843+
ts = max(u1, u2)
844+
return ts + us / 1_000_000
845+
820846
def utcoffset(self):
821847
return None if self._tz is None else self._tz.utcoffset(self)
822848

@@ -828,10 +854,10 @@ def tzname(self):
828854

829855
def timetuple(self):
830856
if self._tz is None:
831-
conv = _tmod.gmtime
857+
conv = _t.gmtime
832858
epoch = datetime.EPOCH.replace(tzinfo=None)
833859
else:
834-
conv = _tmod.localtime
860+
conv = _t.localtime
835861
epoch = datetime.EPOCH
836862
return conv(round((self - epoch).total_seconds()))
837863

@@ -840,7 +866,7 @@ def toordinal(self):
840866

841867
def timestamp(self):
842868
if self._tz is None:
843-
raise NotImplementedError
869+
return self._mktime()
844870
else:
845871
return (self - datetime.EPOCH).total_seconds()
846872

@@ -874,4 +900,4 @@ def tuple(self):
874900
return d + t + (self._tz, self._fd)
875901

876902

877-
datetime.EPOCH = datetime(*_tmod.gmtime(0)[:6], tzinfo=timezone.utc)
903+
datetime.EPOCH = datetime(*_t.gmtime(0)[:6], tzinfo=timezone.utc)

python-stdlib/datetime/localtz.patch

Lines changed: 0 additions & 84 deletions
This file was deleted.

python-stdlib/datetime/manifest.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
metadata(version="4.0.0")
1+
metadata(version="4.1.0")
22

33
# Originally written by Lorenzo Cappelletti.
44

0 commit comments

Comments
 (0)