Estoy tratando de escribir un par de funciones, plottm y unixtm, que convertir de ida y vuelta entre la normal de unix tiempo (segundos desde 1970-01-01) y Matplotlib la fecha de representación (días desde el último día de -1BC o algo, un float).

Si plottm y unixtm fueron adecuados inversas, entonces este código de impresión de la misma fecha/hora dos veces:

import time, datetime
import matplotlib.dates as dt

# Convert a unix time u to plot time p, and vice versa
def plottm(u): return dt.date2num(datetime.datetime.fromtimestamp(u))
def unixtm(p): return time.mktime(dt.num2date(p).timetuple())

u = 1270000000
print datetime.datetime.fromtimestamp(u), "-->", \
      datetime.datetime.fromtimestamp(unixtm(plottm(u)))

Por desgracia, fuera por una hora (lo que sólo ocurre para algunas marcas de tiempo, de lo contrario me gustaría insertar un desplazamiento y hacer con ella).

Probablemente relacionados con: Problemas con Localtime

ACTUALIZACIÓN: Relacionados con la cuestión de que no es específico para Matplotlib: Convertir un unixtime a un objeto datetime y de vuelta otra vez (un par de tiempo de las funciones de conversión que son inversos)

InformationsquelleAutor dreeves | 2012-11-06

3 Comentarios

  1. 3

    Basa en @dreeves respuesta, una solución adaptada para trabajar con la zona horaria en cuenta datetimes:

    import matplotlib.dates as dt
    
    from calendar import timegm
    from datetime import datetime
    
    from pytz import utc
    
    
    # Convert a unix time u to plot time p, 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)

    de salida (probado por varias zonas horarias):

    2010-03-31 01:46:40+00:00 --> 2010-03-31 01:46:40+00:00
    • Cuando ejecuto este mi salida es 2010-03-31 01:46:40+00:00 --> 2010-03-31 06:46:40+00:00 (1270000000 --> 1270018000)
    • El problema es que mi zona horaria es actualmente UTC, y que debería haber probado con diferentes localtimes… ahora las Pruebas.
    • Puedes intentar el ejemplo corregido? Probado con varios locales de las zonas horarias de modo que una debe ser correcto ahora.
    • Muchas gracias, Pedro! En el ínterin me pidió una versión más general de esta cuestión, que llevó a lo que yo creo que es un enfoque mejor que jugar con tzlocal. Me acaba de publicar una respuesta que ahora está trabajando para mí.
  2. 2

    Hay matplotlib.las fechas.epoch2num()/num2epoch funciones que hacer exactamente eso:

    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  # seconds
    
    
    def plottm(u):
        """posix timestamp -> plot time"""
        td = (datetime.utcfromtimestamp(u) - matplotlib_epoch)
        return td.days + 1 + (1000000 * td.seconds + td.microseconds) / 1e6 / DAY
    
    
    def unixtm(p):
        """plot time -> posix timestamp"""
        td = timedelta(days=p-1)
        return (matplotlib_epoch + td - posix_epoch).total_seconds()
    
    
    def main():
        f = datetime.utcfromtimestamp
        u = 1270000000.1234567890
        print(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))))
    
        assert abs(mpl_dt.epoch2num(u) - plottm(u)) < 1e-5
    
        p = 86401.234567890 / DAY
        print(f(mpl_dt.num2epoch(p)))
        print(f(unixtm(p)))
        assert abs(mpl_dt.num2epoch(p) - unixtm(p)) < 1e-5
    
    main()

    De salida

    2010-03-31 01:46:40.123457
    733862.074076
    733862.074076
    2010-03-31 01:46:40.123453
    2010-03-31 01:46:40.123453
    2010-03-31 01:46:40.123453
    2010-03-31 01:46:40.123453
    0001-01-01 00:00:01.234566
    0001-01-01 00:00:01.234566
    • Gracias J. F.! ¿Ve usted alguna razón para preferir esta solución sobre la que he publicado (basado, de manera confusa, en F. J. la respuesta)?
    • sí. El código podría ser incorrecta. Me he dejado a comentario apropiado en su respuesta. epoch2num/num2epoch debe ser utilizado a menos que tenga razones para no utilizarlos. También puedes probar de veces alrededor de datetime.min, datetime.max a ver si la precisión se pierde o no funciona en absoluto.
  3. 1

    Gracias a F. J.‘s respuesta a una pregunta similar, yo creo que el siguiente puede ser la mejor manera de lidiar con esto:

    import datetime, calendar
    import matplotlib.dates as dt
    
    def plottm(u): return dt.date2num(datetime.datetime.utcfromtimestamp(u))
    def unixtm(p): return calendar.timegm(dt.num2date(p).timetuple())
    • Sin duda, la mejor solución: +1 de mí! 🙂 Yo estaba seguro de que hubo un UTC equivalente para time.mktime pero para la vida de mí, no podía recordar dónde (y estaba mirándome a la cara unas líneas más arriba en la time.gmtime documentación)! Uno debe de siempre trabajar internamente en UTC y a/a partir de la hora local debe ocurrir sólo en la interfaz de usuario.
    • num2date depende de la tz que puede ser configurado para ser cualquier zona horaria, timegm esperar la hora utc para num2date siempre debe volver el tiempo en utc. No sé de qué zona horaria date2num espera (si es que no siempre utc; el código puede fallar).

Dejar respuesta

Please enter your comment!
Please enter your name here