Skip to content

Commit f688c13

Browse files
committed
New datetime_timestamp_floating_point_behavior.py with output.
1 parent ad67881 commit f688c13

File tree

2 files changed

+256
-0
lines changed

2 files changed

+256
-0
lines changed
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
"""Show datetime.datetime.timestamp() floating-point behavior.
2+
3+
Please review the output of this code first, then look back here.
4+
5+
* https://docs.python.org/3/library/datetime.html
6+
* https://en.wikipedia.org/wiki/IEEE_754
7+
"""
8+
9+
import datetime
10+
import sys
11+
12+
13+
def annotate_behavior(t_int, t_flt):
14+
if int(t_flt) == t_int:
15+
return "truncating"
16+
if int(t_flt) == t_int + 1:
17+
return "ROUNDING UP"
18+
return "LOSSY"
19+
20+
21+
def dt_strftime(dt):
22+
return ("000" + dt.strftime("%Y-%m-%d %H:%M:%S.%f"))[-26:]
23+
24+
25+
def run(args):
26+
"""Please review the output of this code first, then look back here."""
27+
28+
assert len(args) == 1, "sample_max_exponent (e.g. 53 for IEEE 754)"
29+
30+
sample_max_exponent = int(args[0])
31+
32+
resolution_exponent = 6
33+
resolution_num = 10**resolution_exponent # 1000000
34+
resolution_nines = resolution_num - 1 # 999999
35+
resolution_nines_over_num = resolution_nines / resolution_num # 0.999999
36+
37+
tz_utc = datetime.timezone.utc
38+
dt_min = datetime.datetime.min.replace(tzinfo=tz_utc)
39+
dt_max = datetime.datetime.max.replace(tzinfo=tz_utc)
40+
dt_min_t = dt_min.timestamp()
41+
dt_max_t = dt_max.timestamp()
42+
43+
print("datetime.min.timestamp()", dt_min_t, "", dt_strftime(dt_min))
44+
print("datetime.max.timestamp()", dt_max_t, "", dt_strftime(dt_max))
45+
print()
46+
47+
print(" offset t_int t_int+0.999999")
48+
49+
def print_mm(name, t, offset):
50+
t_int = int(t) + offset
51+
t_flt = t_int + resolution_nines_over_num
52+
print(
53+
f"{name} {offset:6} {t_int:13} {t_flt:15}"
54+
f" {annotate_behavior(t_int, t_flt)}"
55+
)
56+
57+
for offset in (0, 1):
58+
print_mm("datetime.min", dt_min_t, offset)
59+
for offset in (-1, 0):
60+
print_mm("datetime.max", dt_max_t, offset)
61+
print()
62+
63+
print("2**e offset t_int t_int+0.999999")
64+
t_int_done = set()
65+
for exponent in range(sample_max_exponent + 1):
66+
ip2 = 2**exponent
67+
for offset in (-1, 0, 1):
68+
t_int = ip2 + offset
69+
if t_int in t_int_done:
70+
continue
71+
t_int_done.add(t_int)
72+
t_flt = t_int + resolution_nines_over_num
73+
if t_flt < dt_max_t:
74+
dt_utc = datetime.datetime.fromtimestamp(t_int, tz=tz_utc)
75+
dt_fmt = dt_strftime(dt_utc)
76+
else:
77+
dt_fmt = "out of datetime range"
78+
print(
79+
f"{exponent:4} {offset:6} {t_int:16} {t_flt:20}"
80+
f" {annotate_behavior(t_int, t_flt):11} {dt_fmt}"
81+
)
82+
print()
83+
84+
85+
if __name__ == "__main__":
86+
run(args=sys.argv[1:])
Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
datetime.min.timestamp() -62135596800.0 0001-01-01 00:00:00.000000
2+
datetime.max.timestamp() 253402300800.0 9999-12-31 23:59:59.999999
3+
4+
offset t_int t_int+0.999999
5+
datetime.min 0 -62135596800 -62135596799.0 ROUNDING UP
6+
datetime.min 1 -62135596799 -62135596798.0 ROUNDING UP
7+
datetime.max -1 253402300799 253402300800.0 ROUNDING UP
8+
datetime.max 0 253402300800 253402300801.0 ROUNDING UP
9+
10+
2**e offset t_int t_int+0.999999
11+
0 -1 0 0.999999 truncating 1970-01-01 00:00:00.000000
12+
0 0 1 1.9999989999999999 truncating 1970-01-01 00:00:01.000000
13+
0 1 2 2.999999 truncating 1970-01-01 00:00:02.000000
14+
1 1 3 3.999999 truncating 1970-01-01 00:00:03.000000
15+
2 0 4 4.999999 truncating 1970-01-01 00:00:04.000000
16+
2 1 5 5.999999 truncating 1970-01-01 00:00:05.000000
17+
3 -1 7 7.999999 truncating 1970-01-01 00:00:07.000000
18+
3 0 8 8.999999 truncating 1970-01-01 00:00:08.000000
19+
3 1 9 9.999999 truncating 1970-01-01 00:00:09.000000
20+
4 -1 15 15.999999 truncating 1970-01-01 00:00:15.000000
21+
4 0 16 16.999999 truncating 1970-01-01 00:00:16.000000
22+
4 1 17 17.999999 truncating 1970-01-01 00:00:17.000000
23+
5 -1 31 31.999999 truncating 1970-01-01 00:00:31.000000
24+
5 0 32 32.999999 truncating 1970-01-01 00:00:32.000000
25+
5 1 33 33.999999 truncating 1970-01-01 00:00:33.000000
26+
6 -1 63 63.999999 truncating 1970-01-01 00:01:03.000000
27+
6 0 64 64.999999 truncating 1970-01-01 00:01:04.000000
28+
6 1 65 65.999999 truncating 1970-01-01 00:01:05.000000
29+
7 -1 127 127.999999 truncating 1970-01-01 00:02:07.000000
30+
7 0 128 128.999999 truncating 1970-01-01 00:02:08.000000
31+
7 1 129 129.999999 truncating 1970-01-01 00:02:09.000000
32+
8 -1 255 255.999999 truncating 1970-01-01 00:04:15.000000
33+
8 0 256 256.999999 truncating 1970-01-01 00:04:16.000000
34+
8 1 257 257.999999 truncating 1970-01-01 00:04:17.000000
35+
9 -1 511 511.999999 truncating 1970-01-01 00:08:31.000000
36+
9 0 512 512.999999 truncating 1970-01-01 00:08:32.000000
37+
9 1 513 513.999999 truncating 1970-01-01 00:08:33.000000
38+
10 -1 1023 1023.999999 truncating 1970-01-01 00:17:03.000000
39+
10 0 1024 1024.999999 truncating 1970-01-01 00:17:04.000000
40+
10 1 1025 1025.999999 truncating 1970-01-01 00:17:05.000000
41+
11 -1 2047 2047.999999 truncating 1970-01-01 00:34:07.000000
42+
11 0 2048 2048.999999 truncating 1970-01-01 00:34:08.000000
43+
11 1 2049 2049.999999 truncating 1970-01-01 00:34:09.000000
44+
12 -1 4095 4095.999999 truncating 1970-01-01 01:08:15.000000
45+
12 0 4096 4096.999999 truncating 1970-01-01 01:08:16.000000
46+
12 1 4097 4097.999999 truncating 1970-01-01 01:08:17.000000
47+
13 -1 8191 8191.999999 truncating 1970-01-01 02:16:31.000000
48+
13 0 8192 8192.999999 truncating 1970-01-01 02:16:32.000000
49+
13 1 8193 8193.999999 truncating 1970-01-01 02:16:33.000000
50+
14 -1 16383 16383.999999 truncating 1970-01-01 04:33:03.000000
51+
14 0 16384 16384.999999 truncating 1970-01-01 04:33:04.000000
52+
14 1 16385 16385.999999 truncating 1970-01-01 04:33:05.000000
53+
15 -1 32767 32767.999999 truncating 1970-01-01 09:06:07.000000
54+
15 0 32768 32768.999999 truncating 1970-01-01 09:06:08.000000
55+
15 1 32769 32769.999999 truncating 1970-01-01 09:06:09.000000
56+
16 -1 65535 65535.999999 truncating 1970-01-01 18:12:15.000000
57+
16 0 65536 65536.999999 truncating 1970-01-01 18:12:16.000000
58+
16 1 65537 65537.999999 truncating 1970-01-01 18:12:17.000000
59+
17 -1 131071 131071.999999 truncating 1970-01-02 12:24:31.000000
60+
17 0 131072 131072.999999 truncating 1970-01-02 12:24:32.000000
61+
17 1 131073 131073.999999 truncating 1970-01-02 12:24:33.000000
62+
18 -1 262143 262143.999999 truncating 1970-01-04 00:49:03.000000
63+
18 0 262144 262144.999999 truncating 1970-01-04 00:49:04.000000
64+
18 1 262145 262145.999999 truncating 1970-01-04 00:49:05.000000
65+
19 -1 524287 524287.999999 truncating 1970-01-07 01:38:07.000000
66+
19 0 524288 524288.999999 truncating 1970-01-07 01:38:08.000000
67+
19 1 524289 524289.999999 truncating 1970-01-07 01:38:09.000000
68+
20 -1 1048575 1048575.999999 truncating 1970-01-13 03:16:15.000000
69+
20 0 1048576 1048576.999999 truncating 1970-01-13 03:16:16.000000
70+
20 1 1048577 1048577.999999 truncating 1970-01-13 03:16:17.000000
71+
21 -1 2097151 2097151.999999 truncating 1970-01-25 06:32:31.000000
72+
21 0 2097152 2097152.999999 truncating 1970-01-25 06:32:32.000000
73+
21 1 2097153 2097153.999999 truncating 1970-01-25 06:32:33.000000
74+
22 -1 4194303 4194303.999999 truncating 1970-02-18 13:05:03.000000
75+
22 0 4194304 4194304.999999 truncating 1970-02-18 13:05:04.000000
76+
22 1 4194305 4194305.999999 truncating 1970-02-18 13:05:05.000000
77+
23 -1 8388607 8388607.999999 truncating 1970-04-08 02:10:07.000000
78+
23 0 8388608 8388608.999999 truncating 1970-04-08 02:10:08.000000
79+
23 1 8388609 8388609.999999 truncating 1970-04-08 02:10:09.000000
80+
24 -1 16777215 16777215.999999 truncating 1970-07-14 04:20:15.000000
81+
24 0 16777216 16777216.999999 truncating 1970-07-14 04:20:16.000000
82+
24 1 16777217 16777217.999999 truncating 1970-07-14 04:20:17.000000
83+
25 -1 33554431 33554431.999999 truncating 1971-01-24 08:40:31.000000
84+
25 0 33554432 33554432.999999 truncating 1971-01-24 08:40:32.000000
85+
25 1 33554433 33554433.999999 truncating 1971-01-24 08:40:33.000000
86+
26 -1 67108863 67108863.999999 truncating 1972-02-16 17:21:03.000000
87+
26 0 67108864 67108864.999999 truncating 1972-02-16 17:21:04.000000
88+
26 1 67108865 67108865.999999 truncating 1972-02-16 17:21:05.000000
89+
27 -1 134217727 134217727.999999 truncating 1974-04-03 10:42:07.000000
90+
27 0 134217728 134217728.999999 truncating 1974-04-03 10:42:08.000000
91+
27 1 134217729 134217729.999999 truncating 1974-04-03 10:42:09.000000
92+
28 -1 268435455 268435455.999999 truncating 1978-07-04 21:24:15.000000
93+
28 0 268435456 268435456.999999 truncating 1978-07-04 21:24:16.000000
94+
28 1 268435457 268435457.999999 truncating 1978-07-04 21:24:17.000000
95+
29 -1 536870911 536870911.999999 truncating 1987-01-05 18:48:31.000000
96+
29 0 536870912 536870912.999999 truncating 1987-01-05 18:48:32.000000
97+
29 1 536870913 536870913.999999 truncating 1987-01-05 18:48:33.000000
98+
30 -1 1073741823 1073741823.999999 truncating 2004-01-10 13:37:03.000000
99+
30 0 1073741824 1073741824.999999 truncating 2004-01-10 13:37:04.000000
100+
30 1 1073741825 1073741825.999999 truncating 2004-01-10 13:37:05.000000
101+
31 -1 2147483647 2147483647.999999 truncating 2038-01-19 03:14:07.000000
102+
31 0 2147483648 2147483648.999999 truncating 2038-01-19 03:14:08.000000
103+
31 1 2147483649 2147483649.999999 truncating 2038-01-19 03:14:09.000000
104+
32 -1 4294967295 4294967295.999999 truncating 2106-02-07 06:28:15.000000
105+
32 0 4294967296 4294967296.999999 truncating 2106-02-07 06:28:16.000000
106+
32 1 4294967297 4294967297.999999 truncating 2106-02-07 06:28:17.000000
107+
33 -1 8589934591 8589934591.999999 truncating 2242-03-16 12:56:31.000000
108+
33 0 8589934592 8589934592.999998 truncating 2242-03-16 12:56:32.000000
109+
33 1 8589934593 8589934593.999998 truncating 2242-03-16 12:56:33.000000
110+
34 -1 17179869183 17179869183.999998 truncating 2514-05-30 01:53:03.000000
111+
34 0 17179869184 17179869185.0 ROUNDING UP 2514-05-30 01:53:04.000000
112+
34 1 17179869185 17179869186.0 ROUNDING UP 2514-05-30 01:53:05.000000
113+
35 -1 34359738367 34359738368.0 ROUNDING UP 3058-10-26 03:46:07.000000
114+
35 0 34359738368 34359738369.0 ROUNDING UP 3058-10-26 03:46:08.000000
115+
35 1 34359738369 34359738370.0 ROUNDING UP 3058-10-26 03:46:09.000000
116+
36 -1 68719476735 68719476736.0 ROUNDING UP 4147-08-20 07:32:15.000000
117+
36 0 68719476736 68719476737.0 ROUNDING UP 4147-08-20 07:32:16.000000
118+
36 1 68719476737 68719476738.0 ROUNDING UP 4147-08-20 07:32:17.000000
119+
37 -1 137438953471 137438953472.0 ROUNDING UP 6325-04-08 15:04:31.000000
120+
37 0 137438953472 137438953473.0 ROUNDING UP 6325-04-08 15:04:32.000000
121+
37 1 137438953473 137438953474.0 ROUNDING UP 6325-04-08 15:04:33.000000
122+
38 -1 274877906943 274877906944.0 ROUNDING UP out of datetime range
123+
38 0 274877906944 274877906945.0 ROUNDING UP out of datetime range
124+
38 1 274877906945 274877906946.0 ROUNDING UP out of datetime range
125+
39 -1 549755813887 549755813888.0 ROUNDING UP out of datetime range
126+
39 0 549755813888 549755813889.0 ROUNDING UP out of datetime range
127+
39 1 549755813889 549755813890.0 ROUNDING UP out of datetime range
128+
40 -1 1099511627775 1099511627776.0 ROUNDING UP out of datetime range
129+
40 0 1099511627776 1099511627777.0 ROUNDING UP out of datetime range
130+
40 1 1099511627777 1099511627778.0 ROUNDING UP out of datetime range
131+
41 -1 2199023255551 2199023255552.0 ROUNDING UP out of datetime range
132+
41 0 2199023255552 2199023255553.0 ROUNDING UP out of datetime range
133+
41 1 2199023255553 2199023255554.0 ROUNDING UP out of datetime range
134+
42 -1 4398046511103 4398046511104.0 ROUNDING UP out of datetime range
135+
42 0 4398046511104 4398046511105.0 ROUNDING UP out of datetime range
136+
42 1 4398046511105 4398046511106.0 ROUNDING UP out of datetime range
137+
43 -1 8796093022207 8796093022208.0 ROUNDING UP out of datetime range
138+
43 0 8796093022208 8796093022209.0 ROUNDING UP out of datetime range
139+
43 1 8796093022209 8796093022210.0 ROUNDING UP out of datetime range
140+
44 -1 17592186044415 17592186044416.0 ROUNDING UP out of datetime range
141+
44 0 17592186044416 17592186044417.0 ROUNDING UP out of datetime range
142+
44 1 17592186044417 17592186044418.0 ROUNDING UP out of datetime range
143+
45 -1 35184372088831 35184372088832.0 ROUNDING UP out of datetime range
144+
45 0 35184372088832 35184372088833.0 ROUNDING UP out of datetime range
145+
45 1 35184372088833 35184372088834.0 ROUNDING UP out of datetime range
146+
46 -1 70368744177663 70368744177664.0 ROUNDING UP out of datetime range
147+
46 0 70368744177664 70368744177665.0 ROUNDING UP out of datetime range
148+
46 1 70368744177665 70368744177666.0 ROUNDING UP out of datetime range
149+
47 -1 140737488355327 140737488355328.0 ROUNDING UP out of datetime range
150+
47 0 140737488355328 140737488355329.0 ROUNDING UP out of datetime range
151+
47 1 140737488355329 140737488355330.0 ROUNDING UP out of datetime range
152+
48 -1 281474976710655 281474976710656.0 ROUNDING UP out of datetime range
153+
48 0 281474976710656 281474976710657.0 ROUNDING UP out of datetime range
154+
48 1 281474976710657 281474976710658.0 ROUNDING UP out of datetime range
155+
49 -1 562949953421311 562949953421312.0 ROUNDING UP out of datetime range
156+
49 0 562949953421312 562949953421313.0 ROUNDING UP out of datetime range
157+
49 1 562949953421313 562949953421314.0 ROUNDING UP out of datetime range
158+
50 -1 1125899906842623 1125899906842624.0 ROUNDING UP out of datetime range
159+
50 0 1125899906842624 1125899906842625.0 ROUNDING UP out of datetime range
160+
50 1 1125899906842625 1125899906842626.0 ROUNDING UP out of datetime range
161+
51 -1 2251799813685247 2251799813685248.0 ROUNDING UP out of datetime range
162+
51 0 2251799813685248 2251799813685249.0 ROUNDING UP out of datetime range
163+
51 1 2251799813685249 2251799813685250.0 ROUNDING UP out of datetime range
164+
52 -1 4503599627370495 4503599627370496.0 ROUNDING UP out of datetime range
165+
52 0 4503599627370496 4503599627370497.0 ROUNDING UP out of datetime range
166+
52 1 4503599627370497 4503599627370498.0 ROUNDING UP out of datetime range
167+
53 -1 9007199254740991 9007199254740992.0 ROUNDING UP out of datetime range
168+
53 0 9007199254740992 9007199254740992.0 truncating out of datetime range
169+
53 1 9007199254740993 9007199254740992.0 LOSSY out of datetime range
170+

0 commit comments

Comments
 (0)