Skip to content

Commit 20e0cbc

Browse files
committed
datetime: Optimize for code size.
Reduces datetime.mpy by: 8897 -> 8728, so saves 169 bytes. Signed-off-by: Damien George <damien@micropython.org>
1 parent 61a8090 commit 20e0cbc

File tree

1 file changed

+29
-40
lines changed

1 file changed

+29
-40
lines changed

python-stdlib/datetime/datetime.py

Lines changed: 29 additions & 40 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,7 @@ def _iso2t(s):
490479

491480

492481
def _t2iso(td, timespec, dt, tz):
493-
s = td._format(_TIME_SPEC.index(timespec))
482+
s = td._fmt(("auto", "hours", "minutes", "seconds", "milliseconds", "microseconds").index(timespec))
494483
if tz is not None:
495484
s += tz.isoformat(dt)
496485
return s
@@ -633,18 +622,18 @@ def fromtimestamp(cls, ts, tz=None):
633622
else:
634623
us = 0
635624
if tz is None:
636-
dt = cls(*_tmod.localtime(ts)[:6], microsecond=us, tzinfo=tz)
637-
s = (dt - datetime(*_tmod.localtime(ts - 86400)[:6]))._us // 1_000_000 - 86400
638-
if s < 0 and dt == datetime(*_tmod.localtime(ts + s)[:6]):
625+
dt = cls(*_t.localtime(ts)[:6], microsecond=us, tzinfo=tz)
626+
s = (dt - datetime(*_t.localtime(ts - 86400)[:6]))._us // 1_000_000 - 86400
627+
if s < 0 and dt == datetime(*_t.localtime(ts + s)[:6]):
639628
dt._fd = 1
640629
else:
641-
dt = cls(*_tmod.gmtime(ts)[:6], microsecond=us, tzinfo=tz)
630+
dt = cls(*_t.gmtime(ts)[:6], microsecond=us, tzinfo=tz)
642631
dt = tz.fromutc(dt)
643632
return dt
644633

645634
@classmethod
646635
def now(cls, tz=None):
647-
return cls.fromtimestamp(_tmod.time(), tz)
636+
return cls.fromtimestamp(_t.time(), tz)
648637

649638
@classmethod
650639
def fromordinal(cls, n):
@@ -814,7 +803,7 @@ def astimezone(self, tz=None):
814803
_tz = self._tz
815804
if _tz is None:
816805
ts = int(self._mktime())
817-
os = datetime(*_tmod.localtime(ts)[:6]) - datetime(*_tmod.gmtime(ts)[:6])
806+
os = datetime(*_t.localtime(ts)[:6]) - datetime(*_t.gmtime(ts)[:6])
818807
else:
819808
os = _tz.utcoffset(self)
820809
utc = self - os
@@ -823,7 +812,7 @@ def astimezone(self, tz=None):
823812

824813
def _mktime(self):
825814
def local(u):
826-
return (datetime(*_tmod.localtime(u)[:6]) - epoch)._us // 1_000_000
815+
return (datetime(*_t.localtime(u)[:6]) - epoch)._us // 1_000_000
827816

828817
epoch = datetime.EPOCH.replace(tzinfo=None)
829818
t, us = divmod((self - epoch)._us, 1_000_000)
@@ -863,10 +852,10 @@ def tzname(self):
863852

864853
def timetuple(self):
865854
if self._tz is None:
866-
conv = _tmod.gmtime
855+
conv = _t.gmtime
867856
epoch = datetime.EPOCH.replace(tzinfo=None)
868857
else:
869-
conv = _tmod.localtime
858+
conv = _t.localtime
870859
epoch = datetime.EPOCH
871860
return conv(round((self - epoch).total_seconds()))
872861

@@ -909,4 +898,4 @@ def tuple(self):
909898
return d + t + (self._tz, self._fd)
910899

911900

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

0 commit comments

Comments
 (0)