「タイムゾーン対応」のPythonでdatetime.today()の値を取得するにはどうすればよいですか?


310

私はの値から1つの日付の値を減算して、datetime.today()何かがどれくらい前にあったかを計算しようとしています。しかしそれは不平を言う:

TypeError: can't subtract offset-naive and offset-aware datetimes

この値datetime.today()は「タイムゾーンに対応」していないようですが、他の日付の値は対応しています。datetime.today()タイムゾーンに対応した値を取得するにはどうすればよいですか?

今、それは私に現地時間で時間を与えています、それはたまたまPST、すなわちUTC-8時間です。最悪の場合、datetimeによって返されたオブジェクトにタイムゾーン値を手動で入力datetime.today()してUTC-8に設定する方法はありますか?

もちろん、理想的な解決策は、タイムゾーンを自動的に知ることです。



10
datetime.now().astimezone()Python 3.6以降で使用できるようです
johnchen902 '28 / 07/28

回答:


362

標準ライブラリでは、独自のタイムゾーンクラスを作成せずに、対応するタイムゾーンを作成するためのクロスプラットフォームの方法はありません。

Windowsにはがありますが、それwin32timezone.utcnow()はpywin32の一部です。ほとんどのタイムゾーンのデータベースが常に更新されているpytzライブラリを使用することをお勧めします。

ローカルタイムゾーンでの作業は非常にトリッキーになる可能性があるため(下記の「参考文献」のリンクを参照)、アプリケーション全体でUTCを使用することをお勧めします。

次のように現在の日付/時刻を取得できます:

import pytz
from datetime import datetime
datetime.utcnow().replace(tzinfo=pytz.utc)

それを気にしてUTC時間ではなく現地時間datetime.today()datetime.now()返すので、それらに適用することは正しくありません。.replace(tzinfo=pytz.utc)

それを行う別の良い方法は次のとおりです。

datetime.now(pytz.utc)

これは少し短く、同じことをします。


多くの場合にUTCを選ぶ理由をさらに読む/見る:


75
どの程度datetime.now(pytz.utc)の代わりにdatetime.utcnow().replace(tzinfo = pytz.utc)
eumiro 2010

5
now(utc)今日(UTCの午前0時でない限り)は戻りませんが、現在時刻をUTCで返します。また.replace(hour=0, minute=0, ...)、(のようなdatetime.today())1日の始まりを取得
jfs '21

1
ドキュメントは、その言うtoday()深夜、現在の時刻を返しません。真夜中が必要なユースケースがある場合、はい、それに応じて交換を行う必要があります。元々の質問は日時の違いについてだったので、真夜中は必要ないと思います。
AndiDog 14

1
@AndiDog:私のコメントは、私が(誤って)そうだと思ったことを暗示してdatetime.today()combine(date.today(), time())ます。と、(正しく指摘したように)同じものを(ほぼ)返すメソッドとメソッドのdatetime両方が.now()あり.today()ます。date.now()方法はありません。dateそしてdatetimeオブジェクトは互換性がありません。オブジェクトの代わりに日時オブジェクトを使用すると、date微妙なバグが発生する可能性があります。とdatetime.today()ほぼ同じであれば、存在する理由は何もありませんdatetime.now()
jfs 14

6
この答えに加えて、あなたがたまたまdjango を使用している場合は、UTCを自動的に使用するため、timezone.now()代わりに常に使用しdatetime.now()ますUSE_TZ = Truetimezonedjango.utils.timezoneドキュメントにあります: docs.djangoproject.com/en/1.11/topics/i18n/timezones
Ryan

107

特定のタイムゾーンで現在の時刻を取得します。

import datetime
import pytz
my_date = datetime.datetime.now(pytz.timezone('US/Pacific'))

2
参照してくださいこれを
2017

1
出力以外のローカライズされた時間を使用しないでください。タイムゾーンベースの日時を使用すると、多くの点で問題が発生します。単純なtimedeltaでは、最初にUTC時間にならない限り、夏時間は考慮されません。常にUTCに基づくタイムゾーン対応を使用します。必要に応じて、出力時にローカルタイムゾーンに変換します。
MrE、

4
受け入れられた回答のコメントで以前に述べた@MrEとの不一致を繰り返します。ローカライズされた日時を操作するのには完全に正当な理由があり、「出力以外にローカライズされた時間を使用しないでください」というのは過度に広いアドバイスです。時計が1時間戻る夏時間の境界の数時間前の日時に1日を追加するとします。どんな結果が欲しいですか?時間が同じであると思われる場合は、ローカライズされた日時を使用してください。1時間早くする必要がある場合は、UTCまたはタイムゾーンナイーブの日時を使用してください。これはドメインに依存します。
マークアメリー2018年

@MarkAmeryは、日数または時間数を追加または減算し、タイムゾーンの問題(例のように)を気にしないことを同意できる限り、このコメントはタイムゾーン修正時刻をクライアントに渡すことに関するものです。Pythonは主にバックエンドプロセスに使用されるため、クライアントに時間を渡します。サーバーは常にUTCで日付と時刻を渡す必要があり、クライアントはそれを独自のローカルの日付/時刻/タイムゾーンに変換する必要があります。それ以外の場合、悪い結果が発生します。出力を確認し、それdatetime.datetime(2016, 11, 5, 9, 43, 45, tzinfo=pytz.timezone('US/Pacific'))が期待どおりかどうかを確認してください
MrE

「サーバーは常にUTCで日付/時刻を渡し、クライアントはそれを独自のローカル日付/時刻/タイムゾーンに変換する必要があります」 -いいえ、これは普遍的には当てはまりません。クライアントのタイムゾーンの使用は不適切な場合があり、適切なタイムゾーンをデータの一部として送信する必要があります。ロンドン市民として、サンフランシスコのチェスクラブのミーティング時間を彼らのウェブサイトで見ると、彼らはロンドン時間ではなく、サンフランシスコ時間で見るべきです。
マークアメリー2018年

69

Python 3では、標準ライブラリにより、UTCをタイムゾーンとして指定することがはるかに簡単になります。

>>> import datetime
>>> datetime.datetime.now(datetime.timezone.utc)
datetime.datetime(2016, 8, 26, 14, 34, 34, 74823, tzinfo=datetime.timezone.utc)

標準ライブラリのみを使用し、Python 2とPython 3の両方で機能するソリューションが必要な場合は、jfsの回答を参照してください。

UTCではなくローカルタイムゾーンが必要な場合は、MihaiCapotăの回答を参照してください


19

Python 2と3の両方で機能するstdlibソリューションを次に示します。

from datetime import datetime

now = datetime.now(utc) # Timezone-aware datetime.utcnow()
today = datetime(now.year, now.month, now.day, tzinfo=utc) # Midnight

どこtodayUTCでの日(深夜)の始まりを表す意識日時インスタンスであるとutctzinfoのオブジェクト(あるドキュメントからの例):

from datetime import tzinfo, timedelta

ZERO = timedelta(0)

class UTC(tzinfo):
    def utcoffset(self, dt):
        return ZERO

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

    def dst(self, dt):
        return ZERO

utc = UTC()

関連:指定されたUTC時間の真夜中(1日の始まり)を取得するいくつかの方法のパフォーマンス比較。注:UTCオフセットが固定されていないタイムゾーンの真夜中取得するのは、より複雑です。


16

現在の時間を表すタイムゾーン対応のdatetimeオブジェクトを作成する別のメソッド:

import datetime
import pytz

pytz.utc.localize( datetime.datetime.utcnow() )  

pytz.utcとのpytz.UTC両方が定義されている(そして同じである)
ことに

2
この答えはよりreplace()一般的であるため、受け入れられた答えよりも優れています。タイムゾーンを他のほとんどの用途で使用localize()するとエラーが発生しやすくなりますが、ナイーブなタイムスタンプにタイムゾーンを割り当てるにはingが推奨されます。
アントニーハッチキンス2014

@AntonyHatchkins:.localize()あいまいな現地時間でメソッドが失敗する(非UTC入力)。を使用する@philfreoの回答は.now(pytz_timezone)、このような場合でも機能し続けます。
jfs 2015

python docsで指定され.now(pytz_timezone)ているとおり、まったく同じです。localize(utcnow)最初にUTCで現在の時刻を生成し、次にタイムゾーンを割り当てます。 "<...>この場合、結果はtz.fromutc(datetime.utcnow().replace(tzinfo=tz))" と同等です。どちらの答えも正しく、常に機能します。
アントニーハッチキンズ2015

1
タイムゾーンを安全に認識できる唯一のナイーブ(非UTC)時間はです。基盤となるシステムはUTC値を知っているはずでありpytz、OLSON dbはそれを世界の任意のタイムゾーンに変換する方法を知っているはずです。夏時間シフト中のあいまいさのため、他のナイーブ(非UTC)タイムゾーンを認識させることは困難です。それは問題ではありません.localizeis_dst値を入力すると、どの日付でも機能します)。これは、夏時間調整の固有の問題です。
アントニーハッチキンズ

16

標準ライブラリのみを使用するワンライナーは、Python 3.3以降で機能します。(johnchen902で提案されているようにdatetimeを使用して、ローカルタイムゾーン対応オブジェクトを取得できます。astimezone

from datetime import datetime, timezone

aware_local_now = datetime.now(timezone.utc).astimezone()

print(aware_local_now)
# 2020-03-03 09:51:38.570162+01:00

print(repr(aware_local_now))
# datetime.datetime(2020, 3, 3, 9, 51, 38, 570162, tzinfo=datetime.timezone(datetime.timedelta(0, 3600), 'CET'))

2
ドキュメントは大きな助けであり、docs.python.org / 3.8 / library / …にあります。この信じられないほど基本的な機能はドキュメントのあいまいな段落の奥深くに埋め込まれているため、このスタックオーバーフローの回答は、この情報を含むインターネット全体で事実上唯一の場所です。ドキュメントでは、Python 3.6以降datetime.now()、引数なしで呼び出すことができ、正しいローカル結果を返すことができることもわかります(ナイーブdatetimeはローカルタイムゾーンにあると想定されています)。
atimholt

8

Djangoを使用している場合は、tz非対応の日付を設定できます(UTCのみ)。

settings.pyで次の行をコメント化します。

USE_TZ = True

8
この質問でジャンゴが言及されているのをどこで見ましたか?
vonPetrushev 2013

1
親切な魂が私の以前のコメント謝罪をここで削除したので、もう一度言ってください:私は恥ずかしいです、質問はDjango固有ではないので間違った答えです。とにかく一部のユーザーに役立つ可能性があるので残しましたが、スコアが0に近づいたら削除します。この回答が不適切な場合は、遠慮なく投票してください。
laffuste

6

pytzは、Python 2.3以降を使用して正確でクロスプラットフォームのタイムゾーン計算を可能にするPythonライブラリです。

stdlibでは、これは不可能です。

SOで同様の質問を参照してください。


6

stdlibで生成する1つの方法を次に示します。

import time
from datetime import datetime

FORMAT='%Y-%m-%dT%H:%M:%S%z'
date=datetime.strptime(time.strftime(FORMAT, time.localtime()),FORMAT)

dateは、UTCタイムゾーンの日付ではなく、ローカル日付とUTCからオフセットを格納するため、日付が生成されるタイムゾーンを特定する必要がある場合は、このソリューションを使用できます。この例と私のローカルタイムゾーンでは:

date
datetime.datetime(2017, 8, 1, 12, 15, 44, tzinfo=datetime.timezone(datetime.timedelta(0, 7200)))

date.tzname()
'UTC+02:00'

重要なのは%z、生成された時間構造体のUTCオフセットを示すために、ディレクティブを表現FORMATに追加することです。その他の表現形式は、datetimeモジュールのドキュメントで参照できます

UTCタイムゾーンの日付が必要な場合は、time.localtime()time.gmtime()に置き換えることができます。

date=datetime.strptime(time.strftime(FORMAT, time.gmtime()),FORMAT)

date    
datetime.datetime(2017, 8, 1, 10, 23, 51, tzinfo=datetime.timezone.utc)

date.tzname()
'UTC'

編集する

これはpython3でのみ機能します。zディレクティブはpython 2 _strptime.pyコードでは使用できません


ValueError:「z」は、「%Y-%m-%dT%H:%M:%S%z」の形式の悪いディレクティブです
jno

あなたはPython 2を使っていますよね?残念ながら、zディレクティブはpython 2では使用できないようです
。_strptime.py

6

タイムゾーンを認識するPythonのdatetime.datetime.now()で説明されているように、dateutilを使用ます。

from dateutil.tz import tzlocal
# Get the current date/time with the timezone.
now = datetime.datetime.now(tzlocal())

1
これが誤った結果をもたらす状況については、JF Sebastianによるこの回答を参照してください。
アントニーハッチキンズ

2
他の投稿のエラーは特定のユースケースにのみ関連すると思います。tzlocal()この関数は、まだ最も簡単な解決策の一つであり、間違いなく、ここで言及されるべきです。
user8162 2018年

2

タイムゾーンでタイムゾーン対応の日付を取得utcすれば、日付の減算が機能します。

しかし、現在のタイムゾーンでタイムゾーン対応の日付が必要な場合tzlocalは、次のようにします。

from tzlocal import get_localzone  # pip install tzlocal
from datetime import datetime
datetime.now(get_localzone())

PS dateutilにも同様の機能があります(dateutil.tz.tzlocal)。しかし、名前を共有しているにもかかわらず、JFセバスチャンが指摘したように、コードベースは完全に異なり、誤った結果をもたらす可能性があります。


サーバーでは通常pythonが使用されます。サーバーのローカルタイムゾーンは通常無意味であり、常にUTCに設定する必要があります。このように日時tzinfoを設定すると、失敗する場合があります。UTCを使用して、出力のみで目的のタイムゾーンにローカライズします。たとえば、timedelta計算は夏時間を考慮しないため、これらはUTCで実行してからローカライズする必要があります。
MrE、

@MrE間違った、オフトピック、例?
アントニーハッチキンズ2017

夏時間を監視するタイムゾーンにローカライズされたdatetimeオブジェクトを使用してみてください。日数を追加して夏時間の状態を変更すると、ローカライズされたタイムゾーンでのdatetimeオブジェクトの操作が失敗し、夏時間を尊重しないことがわかります。したがって、常にUTC時間で日付時刻操作を行う必要があるという私のコメント。
MrE、

重要なのは、これを行わず、UTCで操作を実行してから、datetime.astimezone(timezone)を使用して、出力時にローカルタイムゾーンに変換することです。
MrE、

2

以下は、読み取り可能なタイムゾーンを使用するソリューションであり、today()で機能します。

from pytz import timezone

datetime.now(timezone('Europe/Berlin'))
datetime.now(timezone('Europe/Berlin')).today()

すべてのタイムゾーンを次のようにリストできます。

import pytz

pytz.all_timezones
pytz.common_timezones # or

1

特に非UTCタイムゾーンの場合:

独自のメソッドを持つ唯一のタイムゾーンはですがtimezone.utc、必要に応じてtimedelta&を使用し、を使用してタイムゾーンをtimezone強制することにより、任意のUTCオフセットでタイムゾーンを変更できます.replace

In [1]: from datetime import datetime, timezone, timedelta

In [2]: def force_timezone(dt, utc_offset=0):
   ...:     return dt.replace(tzinfo=timezone(timedelta(hours=utc_offset)))
   ...:

In [3]: dt = datetime(2011,8,15,8,15,12,0)

In [4]: str(dt)
Out[4]: '2011-08-15 08:15:12'

In [5]: str(force_timezone(dt, -8))
Out[5]: '2011-08-15 08:15:12-08:00'

timezone(timedelta(hours=n))タイムゾーンとして使用することは、ここでの真の特効薬であり、他にも多くの便利なアプリケーションがあります。


0

Pythonで現在の日付と時刻を取得する場合は、現在の日付と時刻を取得した後、Pythonで日付と時刻、pytzパッケージをインポートします。

from datetime import datetime
import pytz
import time
str(datetime.strftime(datetime.now(pytz.utc),"%Y-%m-%d %H:%M:%S%t"))

0

私の考えでは、もう1つの代替案は、のPendulum代わりにを使用することですpytz。次の単純なコードを考えてみます。

>>> import pendulum

>>> dt = pendulum.now().to_iso8601_string()
>>> print (dt)
2018-03-27T13:59:49+03:00
>>>

Pendulumをインストールしてドキュメントを確認するには、こちらにアクセスしてください。豊富なオプション(シンプルなISO8601、RFC3339、その他の多くのフォーマットサポートなど)、優れたパフォーマンスを備え、シンプルなコードを生成する傾向があります。


なぜここで投票するのかわからない、このコードは私のために7/24を実行する複数のプログラムで動作しています:) 私は他の意見を気にすることはありませんが、それがあなたにとってうまくいかない理由を教えてください、私がそれをチェックできるようにします。よろしく
お願いします

0

タイムゾーン対応の日付時刻には、以下に示すタイムゾーンを使用します。デフォルトはUTCです。

from django.utils import timezone
today = timezone.now()

0

「howchoo」のタイラーは、Datetimeオブジェクトのより良いアイデアを得るのに役立つ本当に素晴らしい記事を作りました、以下のリンク

日時の操作

基本的に、私は両方の日時オブジェクトの最後に以下を追加しました

.replace(tzinfo=pytz.utc)

例:

import pytz
import datetime from datetime

date = datetime.now().replace(tzinfo=pytz.utc)

0

pnp_datetimeを試してください。使用および返されるすべての時間はタイムゾーンであり、オフセットナイーブおよびオフセットアウェアの問題は発生しません。

>>> from pnp_datetime.pnp_datetime import Pnp_Datetime
>>>
>>> Pnp_Datetime.utcnow()
datetime.datetime(2020, 6, 5, 12, 26, 18, 958779, tzinfo=<UTC>)

0

Python 3.6以降、標準のlibだけで、ローカルタイム(OSの設定)を表すタイムゾーン対応のdatetimeオブジェクトを取得できることを強調しておく必要があります。astimezone()の使用

import datetime

datetime.datetime(2010, 12, 25, 10, 59).astimezone()
# e.g.
# datetime.datetime(2010, 12, 25, 10, 59, tzinfo=datetime.timezone(datetime.timedelta(seconds=3600), 'Mitteleuropäische Zeit'))

datetime.datetime(2010, 12, 25, 12, 59).astimezone().isoformat()
# e.g.
# '2010-12-25T12:59:00+01:00'

# I'm on CET/CEST

(@ johnchen902のコメントを参照)。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.