순진하고 인식하는 datetime.now () <= challenge.datetime_end를 비교할 수 없습니다


154

비교 연산자를 사용하여 현재 날짜와 시간을 모델에 지정된 날짜와 시간과 비교하려고합니다.

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 ()에 사용하는 형식입니다. 순진하거나 알고 있습니까? 로케일 datetime을 인식하기 위해 datetime.now ()를 어떻게 얻습니까?




1
날짜와 함께 연주하는 아주 좋은 라이브러리가 있습니다 : 진자 (나는 제휴하지 않습니다)
Thomas Decaux

답변:


137

기본적으로 datetime객체는 naivePython에 있으므로 두 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

참고 : ValueErrorif tzinfo가 이미 설정되어 있습니다. 확실하지 않은 경우 다음을 사용하십시오.

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

BTW, 다음과 같이 시간대 정보를 사용하여 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)

그것은 말합니다 : ValueError : 계산하려고 할 때 순진한 날짜 시간이 아닙니다 (tzinfo가 이미 설정되어 있음) : datetimeStart = utc.localize (challenge.datetime_start)
sccrthlt

네, ValueError가 발생합니다.
Dmitrii Mikhailov

4
교체하면 tzinfo변환이 수행되지 않으므로 비교가 잘못됩니다.
OrangeDog

이것을 위해 +1. 그리고 utc = pytz.utcpylint 오류를 방지하기 위해 사용 합니다 No value for argument 'dt' in unbound method call (no-value-for-parameter). pytz link
sam

90

datetime.datetime.now 시간대를 인식하지 못합니다.

Django는이를 위해 도우미를 제공합니다. pytz

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

당신은 비교할 수 있어야 nowchallenge.datetime_start


3
경우 USE_TZ=True다음이 timezone.now()경우에도 시간대 인식 날짜 객체를 반환 pytz(다른 이유로 설치하는 것이 좋습니다 될 수 있지만)가 설치되지 않습니다.
jfs

49

한 줄의 코드 솔루션

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()날짜 / 시간에 추가해야합니다 .
그러나 참조 변수 와 동일한 시간대를 추가해야합니다 . 그렇기 때문에 먼저 tzinfo속성을 읽었습니다 .


18

시간대를 비활성화합니다. 사용하다challenge.datetime_start.replace(tzinfo=None);

replace(tzinfo=None)다른 날짜 시간 에도 사용할 수 있습니다 .

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

2

따라서이 문제를 해결하는 방법은 두 개의 날짜 시간이 올바른 시간대에 있는지 확인하는 것입니다.

나는 당신이 사용하고 있음을 볼 수 있습니다 datetime.now()tzinfo를 설정하지 않고 현재 시간으로 시스템을 반환하는 것을 하고 .

tzinfo는 어떤 시간대에 있는지 알려주기 위해 datetime에 첨부 된 정보입니다. 순진한 datetime을 사용하는 경우 시스템 전체에서 일관성을 유지해야합니다. 나는 단지 사용하는 것이 좋습니다datetime.utcnow()

tzinfo와 관련된 날짜 시간을 생성하는 어딘가에서 볼 때 올바른 시간대에 현지화되어 있는지 확인해야합니다 (tzinfo가 관련되어 있음).

Delorean을 살펴보면 이런 종류의 일을 훨씬 쉽게 처리 할 수 ​​있습니다.


8
utcnow에서도이 문제가 나타납니다.
Andy Hayden

0

그것은 나를 형성하고 있습니다. 여기서는 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

다만:

dt = datetimeObject.strftime(format) # format = your datetime format ex) '%Y %d %m'
dt = datetime.datetime.strptime(dt,format)

이렇게하십시오 :

start_time = challenge.datetime_start.strftime('%Y %d %m %H %M %S')
start_time = datetime.datetime.strptime(start_time,'%Y %d %m %H %M %S')

end_time = challenge.datetime_end.strftime('%Y %d %m %H %M %S')
end_time = datetime.datetime.strptime(end_time,'%Y %d %m %H %M %S')

다음 사용 start_timeend_time

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.