web-dev-qa-db-ja.com

ナイーブとアウェアなdatetime.now()<= challenge.datetime_endを比較できません

比較演算子を使用して、現在の日付と時刻をモデルで指定された日付と時刻と比較しようとしています。

if challenge.datetime_start <= datetime.now() <= challenge.datetime_end:

スクリプトは次のエラーを出します:

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

モデルは次のようになります。

class Fundraising_Challenge(models.Model):
    name = models.CharField(max_length=100)
    datetime_start = models.DateTimeField()
    datetime_end = models.DateTimeField()

ロケールの日付と時刻を使用するDjangoもあります。

私が見つけることができなかったのは、DateTimeField()にDjangoが使用するフォーマットです。それは素朴なのですか、それとも意識しているのですか?そして、ロケールdatetimeを認識するためにdatetime.now()を取得するにはどうすればよいですか?

107
Scott

デフォルトでは、datetimeオブジェクトはPythonのnaiveであるため、これらの両方をナイーブまたはアウェアなdatetimeオブジェクトにする必要があります。これは以下を使用して実行できます。

import datetime
import pytz

utc=pytz.UTC

challenge.datetime_start = utc.localize(challenge.datetime_start) 
challenge.datetime_end = utc.localize(challenge.datetime_end) 
# now both the datetime objects are aware, and you can compare them

注:ValueErrorが既に設定されている場合、これはtzinfoを発生させます。それがわからない場合は、

start_time = challenge.datetime_start.replace(tzinfo=utc)
end_time = challenge.datetime_end.replace(tzinfo=utc)

ところで、次のようにタイムゾーン情報を持つdatetime.datetimeオブジェクトのUNIXタイムスタンプをフォーマットすることができます

d = datetime.datetime.utcfromtimestamp(int(unix_timestamp))
d_with_tz = datetime.datetime(
    year=d.year,
    month=d.month,
    day=d.day,
    hour=d.hour,
    minute=d.minute,
    second=d.second,
    tzinfo=pytz.UTC)
88
Viren Rajput

datetime.datetime.nowはタイムゾーンを認識しません。

Djangoにはこのためのヘルパーが付属しています。これにはpytzが必要です

from Django.utils import timezone
now = timezone.now()

nowchallenge.datetime_startを比較できるはずです

69
Alfredo Aguirre

コードソリューションの1行

if timezone_aware_var <= datetime.datetime.now(timezone_aware_var.tzinfo):
    pass #some code

説明バージョン:

# Timezone info of your timezone aware variable
timezone = your_timezone_aware_variable.tzinfo

# Current datetime for the timezone of your variable
now_in_timezone = datetime.datetime.now(timezone)

# Now you can do a fair comparison, both datetime variables have the same time zone
if your_timezone_aware_variable <= now_in_timezone:
    pass #some code

概要:
タイムゾーン情報をnow() datetimeに追加する必要があります。
ただし、参照変数の同じタイムゾーンを追加する必要があります。それが最初にtzinfo属性を読んだ理由です。

34
ePi272314

タイムゾーンを無効にします。 challenge.datetime_start.replace(tzinfo=None);を使用します

他のdatetimereplace(tzinfo=None)を使用することもできます。

if challenge.datetime_start.replace(tzinfo=None) <= datetime.now().replace(tzinfo=None) <= challenge.datetime_end.replace(tzinfo=None):
8
Amin Fathi

したがって、この問題を解決する方法は、2つの日時が正しいタイムゾーンにあることを確認することです。

Tzinfoが設定されていないシステムの現在時刻を返すdatetime.now()を使用していることがわかります。

tzinfoは、日時がどのタイムゾーンにあるかを知らせるために日時に付加される情報です。単純な日時を使用している場合は、システム全体で一貫性を保つ必要があります。 datetime.utcnow()のみを使用することを強くお勧めします

tzinfoが関連付けられたdatetimeを作成している場所を確認するには、それらが正しいタイムゾーンにローカライズされている(tzinfoが関連付けられている)ことを確認する必要があります。

Delorean を見てください。これにより、この種の処理がはるかに簡単になります。

3
myusuf3

それは私から働いています。ここでは、datetimeで作成されたテーブルを取得し、datetimeに10分を追加しています。後で現在の時刻に応じて、有効期限操作が行われます。

from datetime import datetime, time, timedelta
import pytz

データベースの日時に10分追加

table_datetime = '2019-06-13 07:49:02.832969'(例)

# Added 10 minutes on database datetime
# table_datetime = '2019-06-13 07:49:02.832969' (example)

table_expire_datetime = table_datetime + timedelta(minutes=10 )

# Current datetime
current_datetime = datetime.now()


# replace the timezone in both time
expired_on = table_expire_datetime.replace(tzinfo=utc)
checked_on = current_datetime.replace(tzinfo=utc)


if expired_on < checked_on:
    print("Time Crossed)
else:
    print("Time not crossed ")

それは私のために働いた。

0
Chandan Sharma