Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 3eaf027

Browse files
committed
datetime: Optimize for code size.
Optimizations applied here are: - writing once-used helper functions inline in their place of use - writing once-used constant tuples inline in their place of use (I would have used `from micropython import const` but that renders the code not runnable under CPython for testing, and also increases code size itself for the import) - renamed _tmod to _t - renamed _format to _fmt - optimised timedelta._tuple() slightly Reduces datetime.mpy by: 8897 -> 8728, so saves 169 bytes. Signed-off-by: Damien George <damien@micropython.org>
1 parent 656f420 commit 3eaf027

File tree

1 file changed

+31
-40
lines changed

1 file changed

+31
-40
lines changed

‎python-stdlib/datetime/datetime.py‎

Lines changed: 31 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,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,18 +624,18 @@ def fromtimestamp(cls, ts, tz=None):
633624
else:
634625
us = 0
635626
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]):
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]):
639630
dt._fd = 1
640631
else:
641-
dt = cls(*_tmod.gmtime(ts)[:6], microsecond=us, tzinfo=tz)
632+
dt = cls(*_t.gmtime(ts)[:6], microsecond=us, tzinfo=tz)
642633
dt = tz.fromutc(dt)
643634
return dt
644635

645636
@classmethod
646637
def now(cls, tz=None):
647-
return cls.fromtimestamp(_tmod.time(), tz)
638+
return cls.fromtimestamp(_t.time(), tz)
648639

649640
@classmethod
650641
def fromordinal(cls, n):
@@ -814,7 +805,7 @@ def astimezone(self, tz=None):
814805
_tz = self._tz
815806
if _tz is None:
816807
ts = int(self._mktime())
817-
os = datetime(*_tmod.localtime(ts)[:6]) - datetime(*_tmod.gmtime(ts)[:6])
808+
os = datetime(*_t.localtime(ts)[:6]) - datetime(*_t.gmtime(ts)[:6])
818809
else:
819810
os = _tz.utcoffset(self)
820811
utc = self - os
@@ -823,7 +814,7 @@ def astimezone(self, tz=None):
823814

824815
def _mktime(self):
825816
def local(u):
826-
return (datetime(*_tmod.localtime(u)[:6]) - epoch)._us // 1_000_000
817+
return (datetime(*_t.localtime(u)[:6]) - epoch)._us // 1_000_000
827818

828819
epoch = datetime.EPOCH.replace(tzinfo=None)
829820
t, us = divmod((self - epoch)._us, 1_000_000)
@@ -863,10 +854,10 @@ def tzname(self):
863854

864855
def timetuple(self):
865856
if self._tz is None:
866-
conv = _tmod.gmtime
857+
conv = _t.gmtime
867858
epoch = datetime.EPOCH.replace(tzinfo=None)
868859
else:
869-
conv = _tmod.localtime
860+
conv = _t.localtime
870861
epoch = datetime.EPOCH
871862
return conv(round((self - epoch).total_seconds()))
872863

@@ -909,4 +900,4 @@ def tuple(self):
909900
return d + t + (self._tz, self._fd)
910901

911902

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

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /