datetime.datetime.utcnow()にタイムゾーン情報が含まれていないのはなぜですか?


285
datetime.datetime.utcnow()

datetime明示的にUTCであることを考えると、なぜタイムゾーン情報がないのdatetimeですか?

これは含まれていると思いますtzinfo


文字列型の通常のiso形式の日付フィールドをutc形式に変換する方法は?
ナビ

回答:


192

つまり、それはタイムゾーンナイーブであるため、次のものでは使用できません。 datetime.astimezone

このようなタイムゾーンを与えることができます

import pytz  # 3rd party: $ pip install pytz

u = datetime.utcnow()
u = u.replace(tzinfo=pytz.utc) #NOTE: it works only with a fixed utc offset

タイムゾーンを変更できるようになりました

print(u.astimezone(pytz.timezone("America/New_York")))

特定のタイムゾーンの現在の時刻を取得するには、tzinfoをdatetime.now()直接渡すことができます。

#!/usr/bin/env python
from datetime import datetime
import pytz # $ pip install pytz

print(datetime.now(pytz.timezone("America/New_York")))

これは、夏時間(DST)を監視するタイムゾーンを含むすべてのタイムゾーンで機能します。つまり、異なる時間で異なるutcオフセット(非固定utcオフセット)を持つ可能性があるタイムゾーンで機能します。使用しないでくださいtz.localize(datetime.now())。ローカル時間が不明確な場合、DST終了時の移行中に失敗する可能性があります。


216
しかし、それがタイムゾーンナイーブである正当な理由はありません-UTCに指定されています。サードパーティのライブラリを検索して、ライブラリを適切に機能させる必要があるのはなぜですか?
Mark Ransom、2010

4
同意する; 私にとって「ナイーブ」な時間は完全に役に立たない。現在、pythonリストでpytzをstdlibに追加することについての議論があります。問題はライセンスではなく、タイムゾーンデータが頻繁に更新されることです(Python自体は更新できません)。また、pytzはtzinfoインターフェースを想定どおりに実装していないため、で都市のタイムゾーンの一部を使用しようとするとエラーが発生する可能性がありますastimezone。したがって、datetimeにはネイティブのタイムゾーンがないだけでなく、広く利用可能な唯一のtzinfoの実装は、想定されている標準に準拠していません。
ボビンス、

5
@bobince pytzと標準の日時ライブラリが機能しないのはなぜですか?独立したプロジェクトとして進化するPythonコアとpytzは、コアチームのロジスティックな複雑さを軽減します。はい、Pythonコアチームの複雑さを軽減すると、タイムゾーンを処理する必要があるすべてのPythonユーザーの複雑さが増しますが、正当な理由でこの決定を下したと私は信じています。「標準ライブラリにはtzinfoインスタンスがありません...」というルールは簡単です。なぜここで例外を設けるのですか?
Derek Litz、2013

15
いかがですかu=datetime.now(pytz.utc)
Craig McQueen 2014

4
@bain:使用しないでくださいtz.localize(datetime.now())datetime.now(tz)代わりに使用してください。
jfs

142

Python 3.2以降の場合、datetimeモジュールにはが含まれていることに注意してくださいdatetime.timezone。のドキュメントはdatetime.utcnow()言う:

を呼び出すことで、現在のUTCの日時を知ることができます。datetime.now(timezone.utc)

だからあなたはできる:

>>> import datetime
>>> datetime.datetime.now(datetime.timezone.utc)
datetime.datetime(2014, 7, 10, 2, 43, 55, 230107, tzinfo=datetime.timezone.utc)

2
どちらが好まれますか?datetime.now(timezone.utc)またはdatetime.utcnow(timezone.utc)
Jesse Webb

8
datetime.utcnow()引数は取りません。だからそれはする必要がありますdatetime.now(timezone.utc)
Craig McQueen

1
datetime.now()マシン時刻datetime.utcnow()を返しますが、実際のUTC時刻を返します。
Babu

13
@Babu:UTCであることを示すようにdatetime.utcnow()設定されtzinfoていません。しかしセットでdatetime.now(datetime.timezone.utc)UTC時間 返しtzinfoます。
Craig McQueen

@CraigMcQueenではtz、現在のコンストラクタでオブジェクトを渡すと、そのタイムゾーンの時刻が返されますか?OK!ご指摘ありがとうございます。
Babu

71

標準のPythonライブラリには、tzinfoクラスは含まれていません(ただし、pep 431を参照してください)。私はその理由を推測することしかできません。個人的には、UTCのtzinfoクラスを含めないのは間違いだったと思います。標準の実装を実装するのに十分な議論の余地があるからです。

編集:ライブラリには実装はありませんが、tzinfoドキュメントに例として記載されているものがあります

from datetime import timedelta, tzinfo

ZERO = timedelta(0)

# A UTC class.

class UTC(tzinfo):
    """UTC"""

    def utcoffset(self, dt):
        return ZERO

    def tzname(self, dt):
        return "UTC"

    def dst(self, dt):
        return ZERO

utc = UTC()

これを使用するには、現在の時刻を認識できる日時オブジェクトとして取得します。

from datetime import datetime 

now = datetime.now(utc)

ありdatetime.timezone.utc3.2+ Pythonで:

from datetime import datetime, timezone 

now = datetime.now(timezone.utc)

8
このクラスは(そして、もっと重要なのは、のために使用された最初の場所で提供されていなかった理由として囲碁の図datetimeによって作成されたオブジェクトutcnow())...
アンドレ・キャノン

17
タイムゾーンオブジェクトtimezone.utcがPython 3.2に追加されました。下位互換性のためにutcnow()、タイムゾーンのない時間オブジェクトを返しますが、を呼び出すことで必要なものを取得できますnow(timezone.utc)
mhsmith 2013年

4
@rgove、それはPython 3の公正なゲームであると想定されていた一種の誤りの正しさです。下位互換性について心配するべきではありませんでした。私が過去数日以内に読んだ別の例がありstructます- モジュールはUnicodeからバイト文字列への自動変換を行い、最終的な決定は以前のPython 3バージョンとの互換性を壊して先の悪い決定を防ぐことでした。
Mark Ransom 2013年

2
Pythonのtzinfoドキュメントにはそれを実装するためのコードの例が含まれていることに戸惑っていますが、datetime自体にはその機能が含まれていません。 docs.python.org/2/library/datetime.html#datetime.tzinfo.fromutc
LS

1
@LSはい、pytz素晴らしいリソースです。回答を編集してサンプルコードを挿入するまでに、他の誰かがすでにそれを提案しており、私は彼らの雷を盗んだくありませんでした。
Mark Ransom

20

pytzモジュールは一つの選択肢であり、別の存在であるpython-dateutilが、また、サードパーティ製のパッケージであるが、すでに他の依存関係およびオペレーティング・システムに応じて利用できます。

参照用にこの方法論を含めたかっただけです。すでにpython-dateutil他の目的でインストールしている場合は、次の方法tzinfoで複製する代わりに、この方法を使用できます。pytz

import datetime
import dateutil.tz

# Get the UTC time with datetime.now:
utcdt = datetime.datetime.now(dateutil.tz.tzutc())

# Get the UTC time with datetime.utcnow:
utcdt = datetime.datetime.utcnow()
utcdt = utcdt.replace(tzinfo=dateutil.tz.tzutc())

# For fun- get the local time
localdt = datetime.datetime.now(dateutil.tz.tzlocal())

への呼び出しにutcnowUTCタイムゾーン情報を含める必要があることに同意します。ネイティブの日時ライブラリはデフォルトで相互互換性のために単純な日時に設定されているため、これは含まれていないと思います。


1
NameError:名前「dt」は定義されていません
xApple

datetime.datetime.utcfromtimestamp()コールを使用していて、tzinfoを追加する必要がありました。2番目の解決策は私にとってうまくいきました: utcdt = datetime.datetime.utcfromtimestamp(1234567890).replace(dateutil.tz.tzutc())
Ian Lee

1
注:それとは異なりdatetime.now(pytz_tz)、常に機能します。datetime.now(dateutil.tz.tzlocal())DSTの移行中に失敗することがあります。PEP 495-現地時間の明確化dateutilにより、将来状況が改善される可能性があります。
jfs

@IanLee:使用できますutc_dt = datetime.fromtimestamp(1234567890, dateutil.tz.tzutc())(注:dateutil固定されていないutcオフセット(などdateutil.tz.tzlocal())を使用するとpytzここ失敗する可能性があります代わりに - ベースのソリューションを使用してください)。
jfs

私のプログラムは既ににインポートさdateutilれていたので、dateutil.parserこのソリューションが一番気に入りました。それは次のように単純utcCurrentTime = datetime.datetime.now(tz=dateutil.tz.tzutc())でした。ビオラ!!
LS

11

Julien Danjouが、タイムゾーンに対処してはならない理由を説明する優れた記事を書きました。抜粋:

実際、Python datetime APIは常に認識されないdatetimeオブジェクトを返しますが、これは非常に残念です。実際、このオブジェクトの1つを取得するとすぐに、タイムゾーンが何であるかを知る方法がなくなります。したがって、これらのオブジェクトは、それ自体ではかなり「役に立たない」ものです。

残念ながら、を使用しても、utcnow()発見したようにタイムゾーン情報は表示されません。

推奨事項:

  • 常に認識しているdatetimeオブジェクト、つまりタイムゾーン情報を使用します。これにより、それらを直接比較でき(認識datetime オブジェクトと非認識オブジェクトは比較できません)、ユーザーに正しく返されます。活用pytzタイムゾーンオブジェクトを持っています。

  • 入力および出力文字列形式としてISO 8601を使用します。使用datetime.datetime.isoformat()列はタイムゾーン情報が含まれていることをフォーマットを使用してフォーマットとしてタイムスタンプを返します。

  • ISO 8601形式のタイムスタンプを含む文字列を解析する必要がある場合は、に依存できiso8601ます。これは、正しいタイムゾーン情報を含むタイムスタンプを返します。これにより、タイムスタンプを直接比較できます。


1
これは少し誤解を招く推奨事項です。経験則として、タイムゾーンを処理しないでください。tzアンウェアutcオブジェクト(エポックオブジェクト)を常に格納して送信します。タイムゾーンは、UIでの表示時にのみ計算する必要があります
nehem

1
それはすでにジュリアンの考えにかなり一致しているように思えます。彼の特定の推奨事項(上記で参照したもの)のうち、どれが誤解を招くものですか。
Joe D'Andrea

10

timezonePython 3.2以降で情報を追加するには

import datetime

>>> d = datetime.datetime.now(tz=datetime.timezone.utc)
>>> print(d.tzinfo)
'UTC+00:00'

1
AttributeError: 'module' object has no attribute 'timezone' Python 2.7.13(デフォルト、2017年1月19日、14:48:08)
Marcin Owsiany

-6
from datetime import datetime 
from dateutil.relativedelta import relativedelta
d = datetime.now()
date = datetime.isoformat(d).split('.')[0]
d_month = datetime.today() + relativedelta(months=1)
next_month = datetime.isoformat(d_month).split('.')[0]

-13

UTC日付はUTCであるため、タイムゾーン情報を必要としません。これは、定義上、オフセットがないことを意味します。


10
docs.python.org/library/datetime.htmlからわかる限り、tzinfoのないdatetimeはタイムゾーンが指定されていない日付時刻です。ここではタイムゾーン指定されいるため、論理的には存在する必要があります。関連付けられたタイムゾーンがない日付/時刻と、明らかにUTCの日付/時刻には大きな違いがあります。(理想的には、それらは異なるタイプのIMOであるべきですが、それは別の問題です...)
Jon Skeet

@JonSkeet UTCはタイムゾーンではないというイグナシオの見方が欠けていると思います。私がこれを入力すると、この回答のスコアが-9になるのは素晴らしい...
CS

3
@CS:まあ、イグナシオはそれを明言したことはありません...厳密に言えばUTCはタイムゾーンではありませんが、通常は生活をかなり単純にするために1つとして扱われます(Pythonを含む、たとえばpytz.utc)。UTCからのオフセットが不明な値と、0であることがわかっている値との間には大きな違いがあることに注意してください。後者はIMO utcnow() 返す必要があります。これは、ドキュメンテーションによると、「解釈に開かれていない特定の瞬間を表すために、認識されたオブジェクトが使用される」と一致します。
Jon Skeet、2016年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.