Making Matplotlib's Date2num And Num2date Perfect Inverses
I'm trying to write a pair of functions, plottm and unixtm, which convert back and forth between normal unix time (seconds since 1970-01-01) and Matplotlib's date representation (d
Solution 1:
Based on @dreeves answer, a solution adapted to work with timezone aware datetimes:
import matplotlib.dates as dtfrom calendar import timegm
from datetime import datetime
from pytz import utc
# Convert a unix time u to plot timep, and vice versa
def plottm(u):
return dt.date2num(datetime.fromtimestamp(u, utc))
def unixtm(p):
return timegm(dt.num2date(p, utc).utctimetuple())
u = 1270000000
print datetime.fromtimestamp(u, utc), "-->", \
datetime.fromtimestamp(unixtm(plottm(u)), utc)
output (tested for several timezones):
2010-03-31 01:46:40+00:00-->2010-03-31 01:46:40+00:00
Solution 2:
There are matplotlib.dates.epoch2num()/num2epoch functions that do exactly that:
from datetime import datetime, timedelta
import matplotlib.dates as mpl_dt
matplotlib_epoch = datetime(1, 1, 1) # utc
posix_epoch = datetime(1970, 1, 1) # utc
DAY = 86400# secondsdefplottm(u):
"""posix timestamp -> plot time"""
td = (datetime.utcfromtimestamp(u) - matplotlib_epoch)
return td.days + 1 + (1000000 * td.seconds + td.microseconds) / 1e6 / DAY
defunixtm(p):
"""plot time -> posix timestamp"""
td = timedelta(days=p-1)
return (matplotlib_epoch + td - posix_epoch).total_seconds()
defmain():
f = datetime.utcfromtimestamp
u = 1270000000.1234567890print(f(u))
print(mpl_dt.epoch2num(u))
print(plottm(u))
print(f(mpl_dt.num2epoch(mpl_dt.epoch2num(u))))
print(f(mpl_dt.num2epoch(plottm(u))))
print(f(unixtm(mpl_dt.epoch2num(u))))
print(f(unixtm(plottm(u))))
assertabs(mpl_dt.epoch2num(u) - plottm(u)) < 1e-5
p = 86401.234567890 / DAY
print(f(mpl_dt.num2epoch(p)))
print(f(unixtm(p)))
assertabs(mpl_dt.num2epoch(p) - unixtm(p)) < 1e-5
main()
Output
2010-03-31 01:46:40.123457733862.074076733862.0740762010-03-31 01:46:40.1234532010-03-31 01:46:40.1234532010-03-31 01:46:40.1234532010-03-31 01:46:40.1234530001-01-01 00:00:01.2345660001-01-01 00:00:01.234566
Solution 3:
Thanks to F.J.'s answer to a similar question, I believe the following may be the best way to deal with this:
import datetime, calendar
import matplotlib.dates as dt
defplottm(u): return dt.date2num(datetime.datetime.utcfromtimestamp(u))
defunixtm(p): return calendar.timegm(dt.num2date(p).timetuple())
Post a Comment for "Making Matplotlib's Date2num And Num2date Perfect Inverses"