Skip to content Skip to sidebar Skip to footer

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"