datetime、Timestamp、datetime64間の変換


290

numpy.datetime64オブジェクトをdatetime.datetime(またはTimestamp)に変換するにはどうすればよいですか?

次のコードでは、datetime、timestamp、およびdatetime64オブジェクトを作成しています。

import datetime
import numpy as np
import pandas as pd
dt = datetime.datetime(2012, 5, 1)
# A strange way to extract a Timestamp object, there's surely a better way?
ts = pd.DatetimeIndex([dt])[0]
dt64 = np.datetime64(dt)

In [7]: dt
Out[7]: datetime.datetime(2012, 5, 1, 0, 0)

In [8]: ts
Out[8]: <Timestamp: 2012-05-01 00:00:00>

In [9]: dt64
Out[9]: numpy.datetime64('2012-05-01T01:00:00.000000+0100')

注:タイムスタンプから日時を取得するのは簡単です。

In [10]: ts.to_datetime()
Out[10]: datetime.datetime(2012, 5, 1, 0, 0)

しかし、()から、datetimeまたはをどのように抽出しますか?Timestampnumpy.datetime64dt64

更新:データセットのやや厄介な例(おそらく動機付けの例)は次のように見えます。

dt64 = numpy.datetime64('2002-06-28T01:00:00.000000000+0100')

datetime.datetime(2002, 6, 28, 1, 0)長いはずです(!)(1025222400000000000L)...


2
あなたはおそらく受け入れるべき@Wesマッキニーの答えずっと短く、最近で動作するはずnumpypandasバージョンを。
JFS

@JFSebastianうーん、それは答えが「np.datetimeからdatetimeに移動しないでください」ということですか?(とにかくdatetimeのサブクラスであるため)pd.Timestampを使用するか、本当にを使用する必要がある場合pd.Timestamp(dt64).to_datetime()。私はまだこれに少し満足していませんが、確かにWesは私の古い問題にそれほど限定的ではありません(そして世界にとってはより良い)回答に時間を割いていただきありがとうございます。:)
アンディ・ヘイデン、

あなたの質問は「またはTimestampTimestampあり、datetimeとにかく(のサブクラス)です:)
jfs '20

3
2017年以降にこの質問に回答する方は、以下の私の回答で、datetime、datetime64、およびTimestampsの詳細なチュートリアルをご覧ください:stackoverflow.com/a/46921593/3707607
Ted Petrou

回答:


132

numpy.datetime64時刻をUTCで表すdatetimeオブジェクトに変換するにはnumpy-1.8

>>> from datetime import datetime
>>> import numpy as np
>>> dt = datetime.utcnow()
>>> dt
datetime.datetime(2012, 12, 4, 19, 51, 25, 362455)
>>> dt64 = np.datetime64(dt)
>>> ts = (dt64 - np.datetime64('1970-01-01T00:00:00Z')) / np.timedelta64(1, 's')
>>> ts
1354650685.3624549
>>> datetime.utcfromtimestamp(ts)
datetime.datetime(2012, 12, 4, 19, 51, 25, 362455)
>>> np.__version__
'1.8.0.dev-7b75899'

上記の例は、ナイーブなdatetimeオブジェクトがnp.datetime64UTCの時刻として解釈されることを前提としています。


日時をnp.datetime64に変換して戻すには(numpy-1.6):

>>> np.datetime64(datetime.utcnow()).astype(datetime)
datetime.datetime(2012, 12, 4, 13, 34, 52, 827542)

単一のnp.datetime64オブジェクトとnp.datetime64のnumpy配列の両方で機能します。

np.datetime64は、np.int8、np.int16などと同じように考え、同じメソッドを適用して、int、datetime、対応するnumpyオブジェクトなどのPythonオブジェクトを変換します。

あなたの「厄介な例」は正しく動作します:

>>> from datetime import datetime
>>> import numpy 
>>> numpy.datetime64('2002-06-28T01:00:00.000000000+0100').astype(datetime)
datetime.datetime(2002, 6, 28, 0, 0)
>>> numpy.__version__
'1.6.2' # current version available via pip install numpy

インストールしたlong値を次のように再現できますnumpy-1.8.0

pip install git+https://github.com/numpy/numpy.git#egg=numpy-dev

同じ例:

>>> from datetime import datetime
>>> import numpy
>>> numpy.datetime64('2002-06-28T01:00:00.000000000+0100').astype(datetime)
1025222400000000000L
>>> numpy.__version__
'1.8.0.dev-7b75899'

これは、戻りlong用のでnumpy.datetime64タイプ.astype(datetime)と同等である.astype(object)こと戻りPythonの整数(long上)numpy-1.8

日時オブジェクトを取得するには、次のことができます。

>>> dt64.dtype
dtype('<M8[ns]')
>>> ns = 1e-9 # number of seconds in a nanosecond
>>> datetime.utcfromtimestamp(dt64.astype(int) * ns)
datetime.datetime(2002, 6, 28, 0, 0)

秒を直接使用するdatetime64を取得するには:

>>> dt64 = numpy.datetime64('2002-06-28T01:00:00.000000000+0100', 's')
>>> dt64.dtype
dtype('<M8[s]')
>>> datetime.utcfromtimestamp(dt64.astype(int))
datetime.datetime(2002, 6, 28, 0, 0)

numpyのドキュメントは日時APIは実験的であり、将来のnumpyのバージョンで変更される可能性があることを言います。


1
これは常に機能するとは限らないようです。例:dt64 = numpy.datetime64('2002-06-28T01:00:00.000000000+0100')長い(1025222400000000000L)(!)
Andy Hayden

@hayden:試してくださいtype(dt64)dt64.astype(datetime) == datetime.utcfromtimestamp(dt64.astype(int)*1e-6)
jfs

@JFSebastian type(dt64)はこれまでnumpy.datetime64dt64.astype(datetime)同じlong intです...:s
Andy Hayden

@hayden:あなたの派手なバージョンは何ですか?鉱山:numpy.__version__->'1.6.1'
jfs

バージョン1.8.0(Python 2.7.3)、それが動作する場合、それは私のシステムのバグであることを示唆しています!
アンディヘイデン

212

単にpd.Timestampコンストラクターを使用できます。次の図は、この質問と関連する質問に役立つ場合があります。

時間表現間の変換


2
いいね!!! (この質問を書いてから状況が改善されたことに言及する価値があるので、多くの作業がここで行われました:))
Andy Hayden

107
この図を見ただけで、今回の問題には根本的に何か問題があることがわかります。
認知症のハリネズミ

4
msまたはnsの数が指定されている場合、pd.to_datetimeがTimeStampを生成し、np.datetime64が指定されている場合、datetime.datetimeまたはnp.datetime64が指定されている場合、datetime.datetimeを生成することは非常に混乱します。これは妥当だと思いますか?
Mr.WorshipMe 2017

7
@ Mr.WorshipMeこの図は更新する必要があります。pd.to_datetimeすべてをに変換しますpd.Timestamppd.Timestampオブジェクトは、メソッド有しto_pydatetimeに戻すためのdatetime.datetimeオブジェクトとto_datetime64に変換する方法np.datetime64
Ted Petrou 2017

2
この写真の解像度を上げるにはどうすればよいですか?
user3226167

137

地獄へようこそ。

あなただけにdatetime64オブジェクトを渡すことができますpandas.Timestamp

In [16]: Timestamp(numpy.datetime64('2012-05-01T01:00:00.000000'))
Out[16]: <Timestamp: 2012-05-01 01:00:00>

私はこれがNumPy 1.6.1では正しく機能しないことに気づきました:

numpy.datetime64('2012-05-01T01:00:00.000000+0100')

また、pandas.to_datetime使用することもできます(これはdevバージョンの外にあり、v0.9.1をチェックしていません):

In [24]: pandas.to_datetime('2012-05-01T01:00:00.000000+0100')
Out[24]: datetime.datetime(2012, 5, 1, 1, 0, tzinfo=tzoffset(None, 3600))

5
あなたはそれissubclass(pd.Timestamp, datetime)がであることに言及する必要がありTrueます。そしてTimestampクラス自体にto_datetime()メソッドがあります。
jfs

7
pd.to_datetime('2012-05-01T01:00:00.000000+0100')Timestamp('2012-05-01 00:00:00')少なくともpandasで戻ります0.17.1
アントンプロトポポフ2016年

96

Pythonのdatetimeモジュール、numpyのdatetime64 / timedelta64、およびpandasのTimestamp / Timedeltaオブジェクトの間の関係をよりよく説明するために、回答にさらに統合された努力があると思います。

Pythonの日時標準ライブラリ

日時標準ライブラリには4つの主要なオブジェクトがあります

  • 時間-時間のみ、時間、分、秒、マイクロ秒で測定
  • 日付-年、月、日のみ
  • datetime-時間と日付のすべてのコンポーネント
  • timedelta-最大日数単位の時間

これらの4つのオブジェクトを作成する

>>> import datetime
>>> datetime.time(hour=4, minute=3, second=10, microsecond=7199)
datetime.time(4, 3, 10, 7199)

>>> datetime.date(year=2017, month=10, day=24)
datetime.date(2017, 10, 24)

>>> datetime.datetime(year=2017, month=10, day=24, hour=4, minute=3, second=10, microsecond=7199)
datetime.datetime(2017, 10, 24, 4, 3, 10, 7199)

>>> datetime.timedelta(days=3, minutes = 55)
datetime.timedelta(3, 3300)

>>> # add timedelta to datetime
>>> datetime.timedelta(days=3, minutes = 55) + \
    datetime.datetime(year=2017, month=10, day=24, hour=4, minute=3, second=10, microsecond=7199)
datetime.datetime(2017, 10, 27, 4, 58, 10, 7199)

NumPyのdatetime64およびtimedelta64オブジェクト

NumPyには個別の日付と時刻オブジェクトはなく、単一の日付時刻オブジェクトを表す単一のdatetime64オブジェクトがあります。datetimeモジュールのdatetimeオブジェクトはマイクロ秒の精度(100万分の1秒)です。NumPyのdatetime64オブジェクトを使用すると、時間の精度をアト秒(10 ^ -18)に設定できます。コンストラクタはより柔軟で、さまざまな入力を受け取ることができます。

NumPyのdatetime64およびtimedelta64オブジェクトを作成します

単位の文字列とともに整数を渡します。ここですべてのユニットを参照してください。UNIXエポックの後、それは多くの単位に変換されます:1970年1月1日

>>> np.datetime64(5, 'ns') 
numpy.datetime64('1970-01-01T00:00:00.000000005')

>>> np.datetime64(1508887504, 's')
numpy.datetime64('2017-10-24T23:25:04')

ISO 8601形式の文字列を使用することもできます。

>>> np.datetime64('2017-10-24')
numpy.datetime64('2017-10-24')

Timedeltaには単一の単位があります

>>> np.timedelta64(5, 'D') # 5 days
>>> np.timedelta64(10, 'h') 10 hours

2つのdatetime64オブジェクトを減算して作成することもできます

>>> np.datetime64('2017-10-24T05:30:45.67') - np.datetime64('2017-10-22T12:35:40.123')
numpy.timedelta64(147305547,'ms')

Pandas TimestampとTimedeltaはNumPyの上にさらに多くの機能を構築します

パンダのタイムスタンプは、日時と非常によく似ていますが、より多くの機能を備えています。pd.Timestampまたはで構築できますpd.to_datetime

>>> pd.Timestamp(1239.1238934) #defautls to nanoseconds
Timestamp('1970-01-01 00:00:00.000001239')

>>> pd.Timestamp(1239.1238934, unit='D') # change units
Timestamp('1973-05-24 02:58:24.355200')

>>> pd.Timestamp('2017-10-24 05') # partial strings work
Timestamp('2017-10-24 05:00:00')

pd.to_datetime (いくつかのオプションを追加しても)非常によく似ており、文字列のリストをタイムスタンプに変換できます。

>>> pd.to_datetime('2017-10-24 05')
Timestamp('2017-10-24 05:00:00')

>>> pd.to_datetime(['2017-1-1', '2017-1-2'])
DatetimeIndex(['2017-01-01', '2017-01-02'], dtype='datetime64[ns]', freq=None)

Pythonのdatetimeをdatetime64およびTimestampに変換する

>>> dt = datetime.datetime(year=2017, month=10, day=24, hour=4, 
                   minute=3, second=10, microsecond=7199)
>>> np.datetime64(dt)
numpy.datetime64('2017-10-24T04:03:10.007199')

>>> pd.Timestamp(dt) # or pd.to_datetime(dt)
Timestamp('2017-10-24 04:03:10.007199')

numpy datetime64をdatetimeおよびTimestampに変換する

>>> dt64 = np.datetime64('2017-10-24 05:34:20.123456')
>>> unix_epoch = np.datetime64(0, 's')
>>> one_second = np.timedelta64(1, 's')
>>> seconds_since_epoch = (dt64 - unix_epoch) / one_second
>>> seconds_since_epoch
1508823260.123456

>>> datetime.datetime.utcfromtimestamp(seconds_since_epoch)
>>> datetime.datetime(2017, 10, 24, 5, 34, 20, 123456)

タイムスタンプに変換

>>> pd.Timestamp(dt64)
Timestamp('2017-10-24 05:34:20.123456')

Timestampからdatetimeおよびdatetime64への変換

パンダのタイムスタンプは非常に強力なので、これは非常に簡単です

>>> ts = pd.Timestamp('2017-10-24 04:24:33.654321')

>>> ts.to_pydatetime()   # Python's datetime
datetime.datetime(2017, 10, 24, 4, 24, 33, 654321)

>>> ts.to_datetime64()
numpy.datetime64('2017-10-24T04:24:33.654321000')

3
datetimeへのnumpyがいかに難しいかハックであるかは狂っています...本当に良い方法はありませんか?これは良い答えです。私はそれをトップレベルに移動することを受け入れることを考えています。コンピュータで他の人を一度深く読む必要があります。
アンディヘイデン

それについて何が変わっているのですか?パンダのタイムスタンプはうまく機能し、かなり単純です。
Ted Petrou 2017年

2
Numpyからdatetimeへ。
アンディヘイデン

1
これが今まで見た中で最高の答えだと思います。Excel、VBA、SAS、またはSQLから来たPythonは、日付/時刻を操作するための「単一の方法」しか存在しないため、奇妙に見えます。PythonやRの多くのことと同様に、好きなメソッド/モジュール/クラスを選択してそれに固執する必要があるようです。
Sean McCarthy

素晴らしいアンセワー
gioxc88

29
>>> dt64.tolist()
datetime.datetime(2012, 5, 1, 0, 0)

の場合DatetimeIndextolistdatetimeオブジェクトのリストを返します。単一のdatetime64オブジェクトの場合、単一のオブジェクトを返しdatetimeます。


私は本当にすべての方法を試してみるべきだった:)(私がこれにどれだけ取り組んでいるのかにショックを受けた)ありがとう
Andy Hayden

5
@haydenそのスカラー/ 0-d配列がわかっている場合.item()は、もっと明示的な方を使用したほうがよい(そして、リストを返す必要があると主張し始めることができない)。
Seberg、

1
これは常に機能するとは限らないようです。例:dt64 = numpy.datetime64('2002-06-28T01:00:00.000000000+0100')長い(1025222400000000000L)(!)
Andy Hayden

4
@hayden:.item()(@sebergが推奨)が返す型は、.tolist()datetime64が使用する単位に依存します。たとえば、Dproduces datetime.date()us(microseconds )produce datetime.datetime()ns(nanoseconds)produceなどlongです。また、単位numpy.datetime64('2012-05-01')'D'numpy.datetime64('2012-05-01T00:00:00.000')使用msnumpy.datetime64('2012-05-01T00:00:00.000000000')使用、使用などの 入力値に応じて変化しますns。混乱を招く場合は、問題を開く可能性があります。
jfs

@AndyHaydenまた、追加の引数「us」または「ms」を追加して、同じフォーマットが適用され、同じdatetime要素がtolist()で生成されるようにすることもできます
NM

11

日付時刻のパンダシリーズ全体を通常のPython日付時刻に変換する場合は、も使用できます.to_pydatetime()

pd.date_range('20110101','20110102',freq='H').to_pydatetime()

> [datetime.datetime(2011, 1, 1, 0, 0) datetime.datetime(2011, 1, 1, 1, 0)
   datetime.datetime(2011, 1, 1, 2, 0) datetime.datetime(2011, 1, 1, 3, 0)
   ....

また、タイムゾーンもサポートしています。

pd.date_range('20110101','20110102',freq='H').tz_localize('UTC').tz_convert('Australia/Sydney').to_pydatetime()

[ datetime.datetime(2011, 1, 1, 11, 0, tzinfo=<DstTzInfo 'Australia/Sydney' EST+11:00:00 DST>)
 datetime.datetime(2011, 1, 1, 12, 0, tzinfo=<DstTzInfo 'Australia/Sydney' EST+11:00:00 DST>)
....

:Pandasシリーズで操作している場合to_pydatetime()、シリーズ全体を呼び出すことはできません。.to_pydatetime()リスト内包表記などを使用して、個々のdatetime64を呼び出す必要があります。

datetimes = [val.to_pydatetime() for val in df.problem_datetime_column]

10

1つのオプションは、を使用strしてからto_datetime(または同様に)使用することです。

In [11]: str(dt64)
Out[11]: '2012-05-01T01:00:00.000000+0100'

In [12]: pd.to_datetime(str(dt64))
Out[12]: datetime.datetime(2012, 5, 1, 1, 0, tzinfo=tzoffset(None, 3600))

注:「オフセット対応」にdtなっているため、これは等しくありません。

In [13]: pd.to_datetime(str(dt64)).replace(tzinfo=None)
Out[13]: datetime.datetime(2012, 5, 1, 1, 0)

これは洗練されていないようです。

更新:これは「厄介な例」に対処できます。

In [21]: dt64 = numpy.datetime64('2002-06-28T01:00:00.000000000+0100')

In [22]: pd.to_datetime(str(dt64)).replace(tzinfo=None)
Out[22]: datetime.datetime(2002, 6, 28, 1, 0)

このヒントを共有してくれたAndyに感謝します。何らかの理由で、ここで説明するように、それを機能させることができません。stackoverflow.com
questions

@ user815423426これは決して非常に堅牢なソリューションではありませんでした。より一般的に機能するように、日時コンストラクターにフォーマットを渡すことができると思います。それほどパンダスティックではありませんが!
Andy Hayden 14

8

この投稿は4年間続いており、私はまだこの変換の問題に苦労していました。そのため、この問題はある意味で2017年にもまだアクティブです。派手なドキュメントが簡単な変換アルゴリズムを簡単に提供しないが、それはまた別の話です。

私は唯一のモジュールを含むこと変換を行うために別の方法に遭遇しているnumpydatetime、それはこのような単純な変換のために輸入に多くのコードであることを私には思われるインポートするパンダを必要としませんが。他のユニットが整数のタイムスタンプを返す一方で、オリジナルがマイクロ秒単位である場合、オブジェクトdatetime64.astype(datetime.datetime)が返されることに気付きました。最初にマイクロ秒単位に変換しない限り、ナノ秒単位で変換を失敗させるNetcdfファイルからのデータI / Oにモジュールを使用しています。以下は変換コードの例です。datetime.datetimedatetime64xarraydatetime64

import numpy as np
import datetime

def convert_datetime64_to_datetime( usert: np.datetime64 )->datetime.datetime:
    t = np.datetime64( usert, 'us').astype(datetime.datetime)
return t

これは私のマシンでのみテストされています。これは、最近の2017 Anacondaディストリビューションを備えたPython 3.6です。私はスカラー変換のみを見て、配列ベースの変換をチェックしていませんが、それは良いと思います。また、numpyのdatetime64ソースコードを見て、操作が意味があるかどうかも確認していません。


これは素晴らしい。これを作ってくれてありがとう。
Yu Chen

いい物。ありがとうございました。
misantroop

1

私は数え切れないほど何度もこの答えに戻ってきたので、Numpy datetime64値をPython datetime値に変換する簡単なクラスを一緒に投げることに決めました。それが他の人の役に立つことを願っています。

from datetime import datetime
import pandas as pd

class NumpyConverter(object):
    @classmethod
    def to_datetime(cls, dt64, tzinfo=None):
        """
        Converts a Numpy datetime64 to a Python datetime.
        :param dt64: A Numpy datetime64 variable
        :type dt64: numpy.datetime64
        :param tzinfo: The timezone the date / time value is in
        :type tzinfo: pytz.timezone
        :return: A Python datetime variable
        :rtype: datetime
        """
        ts = pd.to_datetime(dt64)
        if tzinfo is not None:
            return datetime(ts.year, ts.month, ts.day, ts.hour, ts.minute, ts.second, tzinfo=tzinfo)
        return datetime(ts.year, ts.month, ts.day, ts.hour, ts.minute, ts.second)

私はこれを私のツールバッグに入れておきます、何かが私にそれが再び必要になると教えてくれます。


2
あなたはただすることができますts.to_pydatetime()
Ted Petrou 2017年

0
import numpy as np
import pandas as pd 

def np64toDate(np64):
    return pd.to_datetime(str(np64)).replace(tzinfo=None).to_datetime()

この関数を使用してPythonネイティブのdatetimeオブジェクトを取得します


私はというエラーましたreplace() got an unexpected keyword argument 'tzinfo'
ogogmad

使用しているパンダのバージョンを教えてください。バージョンは0.18.1(pip show pandas)
Crystal

あなたと同じ。。。
ogogmad 2016年

私はその時知りませんが、それは私にとって魅力のように機能します。pix.toile-libre.org/upload/original/1475645621.png
Crystal

0

いくつかの解決策は私にとってうまくいきますが、numpyはいくつかのパラメータを廃止します。私にとってより効果的な解決策は、日付をパンダの日時として読み取り、パンダオブジェクトの年、月、日を明示的に実行することです。次のコードは、最も一般的な状況で機能します。

def format_dates(dates):
    dt = pd.to_datetime(dates)
    try: return [datetime.date(x.year, x.month, x.day) for x in dt]    
    except TypeError: return datetime.date(dt.year, dt.month, dt.day)

-1

実際、これらの日時タイプはすべて難しく、潜在的に問題がある可能性があります(タイムゾーン情報を注意深く追跡する必要があります)。ここに私がやったことがありますが、少なくともその一部が「意図的ではない」ことを心配していることは認めます。また、必要に応じてこれをもう少しコンパクトにすることもできます。numpy.datetime64 dt_aで始まる:

dt_a

numpy.datetime64( '2015-04-24T23:11:26.270000-0700')

dt_a1 = dt_a.tolist()#UTCで日付時刻オブジェクトを生成しますが、tzinfoはありません

dt_a1

datetime.datetime(2015、4、25、6、11、26、270000)

# now, make your "aware" datetime:

dt_a2 = datetime.datetime(* list(dt_a1.timetuple()[:6])+ [dt_a1.microsecond]、tzinfo = pytz.timezone( 'UTC'))

...そしてもちろん、必要に応じて1行に圧縮できます。


docs.scipy.org/doc/numpy/reference/…タイムゾーン処理の変更について。
hpaulj

してくださいeditコードのフォーマット、引用書式設定、およびテキストの書式:適切に準拠します。また、SOのガイドラインに従って、適切な大文字、文法を
守り
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.