2

通常のUNIX時間(1970-01-01からの秒数)とMatplotlibの日付表現(-1BCまたは何かの最後の日からの日数、float)の間で前後に変換するplottm関数のペアを作成しようとしていますunixtm.

plottmとが適切な逆数である場合unixtm、このコードは同じ日付/時刻を 2 回出力します。

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)))

残念ながら、それは 1 時間ずれています (これは一部のタイムスタンプでのみ発生します。それ以外の場合は、オフセットを挿入して処理します)。

おそらく関連:Localtimeの問題

更新: Matplotlib に固有ではない関連する質問: unixtime を datetime オブジェクトに変換してから再度戻す (逆の時間変換関数のペア)

4

3 に答える 3

3

@dreevesの回答に基づいて、タイムゾーン対応の日時で動作するように適合されたソリューション:

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)

出力 (複数のタイムゾーンでテスト済み):

2010-03-31 01:46:40+00:00 --> 2010-03-31 01:46:40+00:00
于 2012-11-06T22:00:58.590 に答える
3

まさにそれを行うmatplotlib.dates.epoch2num()/num2epoch 関数があります。

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()

出力

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
于 2012-11-07T00:00:08.040 に答える
1

同様の質問に対するFJの回答のおかげで、これに対処するには次の方法が最善の方法であると思います。

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())
于 2012-11-06T23:33:06.620 に答える