Skip to content

Commit 8419417

Browse files
committed
ENH: add ability to change matplotlib epoch
1 parent e86c9cd commit 8419417

File tree

3 files changed

+233
-77
lines changed

3 files changed

+233
-77
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
"""
2+
=========================
3+
Date Precision and Epochs
4+
=========================
5+
6+
Matplotlib can handle `.datetime` objects and `numpy.datetime64` objects using
7+
a unit converter that recognizes these dates and converts them to floating
8+
point numbers. By deafult this conversion returns a float that is days
9+
since "0000-01-01T00:00:00". This has resolution implications for modern
10+
dates: "2000-01-01" in this time frame is 730120, and a 64-bit floating point
11+
number has a resolution of 2^{-52}, or approximately 14 microseconds.
12+
13+
"""
14+
import datetime
15+
import dateutil
16+
import numpy as np
17+
18+
import matplotlib
19+
import matplotlib.pyplot as plt
20+
import matplotlib.dates as mdates
21+
22+
#############################################################################
23+
# Datetime
24+
# --------
25+
#
26+
# Python `.datetime` objects have microsecond reesolution, so by default
27+
# matplotlib dates cannot round-trip full-resolution datetime objects:
28+
29+
date1 = datetime.datetime(2000, 1, 1, 0, 10, 0, 12,
30+
tzinfo=dateutil.tz.gettz('UTC'))
31+
mdate1 = mdates.date2num(date1)
32+
print('Before Roundtrip: ', date1, 'Matplotlib date:', mdate1)
33+
date2 = mdates.num2date(mdate1)
34+
print('After Roundtrip: ', date2)
35+
36+
#############################################################################
37+
# Note this is only a round-off error, and there is no problem for
38+
# dates closer to the epoch:
39+
40+
date1 = datetime.datetime(10, 1, 1, 0, 10, 0, 12,
41+
tzinfo=dateutil.tz.gettz('UTC'))
42+
mdate1 = mdates.date2num(date1)
43+
print('Before Roundtrip: ', date1, 'Matplotlib date:', mdate1)
44+
date2 = mdates.num2date(mdate1)
45+
print('After Roundtrip: ', date2)
46+
47+
#############################################################################
48+
# If a user wants to use modern dates at micro-second precision, they
49+
# can change the epoch.
50+
51+
mdates.set_epoch('1990-01-01')
52+
53+
date1 = datetime.datetime(2000, 1, 1, 0, 10, 0, 12,
54+
tzinfo=dateutil.tz.gettz('UTC'))
55+
mdate1 = mdates.date2num(date1)
56+
print('Before Roundtrip: ', date1, 'Matplotlib date:', mdate1)
57+
date2 = mdates.num2date(mdate1)
58+
print('After Roundtrip: ', date2)
59+
60+
#############################################################################
61+
# datetime64
62+
# ----------
63+
#
64+
# `numpy.datetime64` objects have micro-second precision for a much larger
65+
# timespace than `.datetime` objects. However, currently Matplotlib time is
66+
# only converted back to datetime objects, which have microsecond resolution,
67+
# and years that only span 0000 to 9999.
68+
69+
mdates.set_epoch('1990-01-01')
70+
71+
date1 = np.datetime64('2000-01-01T00:10:00.000012')
72+
mdate1 = mdates.date2num(date1)
73+
print('Before Roundtrip: ', date1, 'Matplotlib date:', mdate1)
74+
date2 = mdates.num2date(mdate1)
75+
print('After Roundtrip: ', date2)
76+
77+
#############################################################################
78+
# Plotting
79+
# --------
80+
#
81+
# This all of course has an effect on plotting. With the default epoch
82+
# the times are rounded, leading to jumps in the data:
83+
84+
mdates.set_epoch('0000-01-01')
85+
x = np.arange('2000-01-01T00:00:00.0', '2000-01-01T00:00:00.000100',
86+
dtype='datetime64[us]')
87+
y = np.arange(0, len(x))
88+
fig, ax = plt.subplots(constrained_layout=True)
89+
ax.plot(x, y)
90+
plt.setp(ax.xaxis.get_majorticklabels(), rotation=40)
91+
plt.show()
92+
93+
#############################################################################
94+
# For a more recent epoch, the plot is smooth:
95+
96+
mdates.set_epoch('1999-01-01')
97+
fig, ax = plt.subplots(constrained_layout=True)
98+
ax.plot(x, y)
99+
plt.setp(ax.xaxis.get_majorticklabels(), rotation=40)
100+
plt.show()
101+
102+
103+
#############################################################################
104+
# ------------
105+
#
106+
# References
107+
# """"""""""
108+
#
109+
# The use of the following functions, methods and classes is shown
110+
# in this example:
111+
112+
matplotlib.dates.num2date
113+
matplotlib.dates.date2num
114+
matplotlib.dates.set_epoch

0 commit comments

Comments
 (0)