Python에서 datetime 객체를 인식(순진하지 않음)시키는 방법
해야 할 일
타임존 비대응 datetime 객체가 있는데 다른 타임존 인식 datetime 객체와 비교하려면 타임존을 추가해야 합니다.이 레거시 케이스에 대해 애플리케이션 전체를 모르는 타임존으로 변환하고 싶지 않습니다.
내가 시도한 것
첫 번째, 문제를 설명하기 위해:
Python 2.6.1 (r261:67515, Jun 24 2010, 21:47:49)
[GCC 4.2.1 (Apple Inc. build 5646)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import datetime
>>> import pytz
>>> unaware = datetime.datetime(2011,8,15,8,15,12,0)
>>> unaware
datetime.datetime(2011, 8, 15, 8, 15, 12)
>>> aware = datetime.datetime(2011,8,15,8,15,12,0,pytz.UTC)
>>> aware
datetime.datetime(2011, 8, 15, 8, 15, 12, tzinfo=<UTC>)
>>> aware == unaware
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: can't compare offset-naive and offset-aware datetimes
먼저 아스타임존을 시도했습니다.
>>> unaware.astimezone(pytz.UTC)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: astimezone() cannot be applied to a naive datetime
>>>
실제로 변환을 시도하고 있기 때문에 실패한 것은 그리 놀라운 일이 아닙니다.치환(How do I get a value of datetime)이 더 나은 선택인 것 같습니다.python에서는 timezone을 인식하고 있습니까?:
>>> unaware.replace(tzinfo=pytz.UTC)
datetime.datetime(2011, 8, 15, 8, 15, 12, tzinfo=<UTC>)
>>> unaware == aware
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: can't compare offset-naive and offset-aware datetimes
>>>
단, 보시다시피 replace는 tzinfo를 설정하지만 오브젝트를 인식하지 않는 것으로 보입니다.입력 문자열을 해석하기 전에 타임존을 설정하기 위해 다시 조작할 준비를 하고 있습니다(중요하다면 해석에 dateutil을 사용하고 있습니다). 하지만 그것은 매우 애매한 것 같습니다.
또한 Python 2.6과 Python 2.7 모두에서 동일한 결과를 얻었습니다.
맥락
데이터 파일의 파서를 쓰고 있습니다.날짜 문자열에 시간대 표시기가 없는 오래된 형식이 있습니다.데이터 소스를 이미 수정했지만 레거시 데이터 형식을 지원해야 합니다.다양한 비즈니스 BS 이유로 레거시 데이터의 일회성 변환은 선택사항이 아닙니다.일반적으로 디폴트 타임존을 하드 코딩하는 것은 마음에 들지 않지만, 이 경우 가장 좋은 옵션인 것 같습니다.문제의 모든 레거시 데이터가 UTC에 있다는 것을 충분히 확신하고 있기 때문에 이 경우 디폴트로 인한 위험을 감수할 준비가 되어 있습니다.
일반적으로 naigive datetime 타임존을 인식하려면 localize 방식을 사용합니다.
import datetime
import pytz
unaware = datetime.datetime(2011, 8, 15, 8, 15, 12, 0)
aware = datetime.datetime(2011, 8, 15, 8, 15, 12, 0, pytz.UTC)
now_aware = pytz.utc.localize(unaware)
assert aware == now_aware
UTC 타임존의 경우, 실제로는localize처리할 서머타임 계산이 없기 때문에:
now_aware = unaware.replace(tzinfo=pytz.UTC)
동작합니다.(.replace새 날짜/시간을 반환하며 수정하지 않습니다.unaware.)
다음 예에서는 모두 외부 모듈을 사용하지만 다음 SO 답변에서도 나타나듯이 datetime 모듈만 사용해도 동일한 결과를 얻을 수 있습니다.
from datetime import datetime, timezone
dt = datetime.now()
dt = dt.replace(tzinfo=timezone.utc)
print(dt.isoformat())
# '2017-01-12T22:11:31+00:00'
의존성이 적고 pyz 문제가 없습니다.
메모: 이것을 python3 및 python2 와 함께 사용하는 경우는, 타임 존 Import에도 사용할 수 있습니다(UTC 의 경우는 하드 코드 됩니다).
try:
from datetime import timezone
utc = timezone.utc
except ImportError:
#Hi there python2 user
class UTC(tzinfo):
def utcoffset(self, dt):
return timedelta(0)
def tzname(self, dt):
return "UTC"
def dst(self, dt):
return timedelta(0)
utc = UTC()
이 Python 2 스크립트는 2011년에 작성했지만 Python 3에서 동작하는지 확인하지 못했습니다.
dt_aware에서 dt_unaware로 이행했습니다.
dt_unaware = dt_aware.replace(tzinfo=None)
dt_unware를 dt_aware로 설정합니다.
from pytz import timezone
localtz = timezone('Europe/Lisbon')
dt_aware = localtz.localize(dt_unware)
나는 이 문장을 Django에서 사용하여 알지 못하는 시간을 인지하는 시간으로 변환합니다.
from django.utils import timezone
dt_aware = timezone.make_aware(dt_unaware, timezone.get_current_timezone())
Python 3.9는 모듈을 추가하므로 이제 표준 라이브러리만 필요합니다!
from zoneinfo import ZoneInfo
from datetime import datetime
unaware = datetime(2020, 10, 31, 12)
표준 시간대를 첨부합니다.
>>> unaware.replace(tzinfo=ZoneInfo('Asia/Tokyo'))
datetime.datetime(2020, 10, 31, 12, 0, tzinfo=zoneinfo.ZoneInfo(key='Asia/Tokyo'))
>>> str(_)
'2020-10-31 12:00:00+09:00'
시스템의 로컬 타임존을 접속합니다.
>>> unaware.replace(tzinfo=ZoneInfo('localtime'))
datetime.datetime(2020, 10, 31, 12, 0, tzinfo=zoneinfo.ZoneInfo(key='localtime'))
>>> str(_)
'2020-10-31 12:00:00+01:00'
그 후, 다른 타임 존으로 적절히 변환됩니다.
>>> unaware.replace(tzinfo=ZoneInfo('localtime')).astimezone(ZoneInfo('Asia/Tokyo'))
datetime.datetime(2020, 10, 31, 20, 0, tzinfo=backports.zoneinfo.ZoneInfo(key='Asia/Tokyo'))
>>> str(_)
'2020-10-31 20:00:00+09:00'
Windows 에는 시스템 타임 존 데이터베이스가 없기 때문에, 여기에서는 추가 패키지가 필요합니다.
pip install tzdata
할 수 .zoneinfoPython 3.6에서 3.8:
pip install backports.zoneinfo
그 후, 다음과 같이 입력합니다.
from backports.zoneinfo import ZoneInfo
앞의 답변에 동의하며, UTC에서 시작해도 괜찮습니다.그러나 UTC가 아닌 로컬 시간대가 있는 날짜의 tz 인식 값으로 작업하는 것도 일반적인 시나리오라고 생각합니다.
이름만 입력하면 replace()가 적용되어 적절한 datetime 인식 객체를 생성할 수 있습니다.이것은 사실이 아니다.
replace( tzinfo=...) )의 동작은 랜덤인 것 같습니다.그러므로 그것은 쓸모가 없다.이것을 사용하지 마세요!
localize는 사용하는 올바른 기능입니다.예:
localdatetime_aware = tz.localize(datetime_nonaware)
또는 보다 완전한 예를 제시하겠습니다.
import pytz
from datetime import datetime
pytz.timezone('Australia/Melbourne').localize(datetime.now())
그럼 현재 현지 시각의 타임존 대응 datetime 값이 표시됩니다.
datetime.datetime(2017, 11, 3, 7, 44, 51, 908574, tzinfo=<DstTzInfo 'Australia/Melbourne' AEDT+11:00:00 DST>)
를 사용하여 및 을 사용하는 타임존을 가져옵니다.
from datetime import datetime
from dateutil import tz
unlocalisedDatetime = datetime.now()
localisedDatetime1 = datetime.now(tz = tz.tzlocal())
localisedDatetime2 = datetime(2017, 6, 24, 12, 24, 36, tz.tzlocal())
localisedDatetime3 = unlocalisedDatetime.astimezone(tz = tz.tzlocal())
localisedDatetime4 = unlocalisedDatetime.replace(tzinfo = tz.tzlocal())
:datetime.astimezone해 줍니다.datetime into 은 UTC를 호출하는 것과 .datetime.replace는 「」입니다.None.
이것은 @Sérgio와 @unutbu의 답변을 정리한 것입니다.다음 중 하나를 사용하여 '그냥' 작동합니다.pytz.timezone오브젝트 또는 IANA 타임존 문자열.
def make_tz_aware(dt, tz='UTC', is_dst=None):
"""Add timezone information to a datetime object, only if it is naive."""
tz = dt.tzinfo or tz
try:
tz = pytz.timezone(tz)
except AttributeError:
pass
return tz.localize(dt, is_dst=is_dst)
이게 뭐 같아datetime.localize() (오류).inform() ★★★★★★★★★★★★★★★★★」.awarify()모두 tz 이 아닌 로 기본
표준시 대응 datetime을 원하는 사용자용
import datetime
datetime.datetime(2019, 12, 7, tzinfo=datetime.timezone.utc)
python 3.9 stdlib로 시작하는 UTC 이외의 타임존을 가진 datetime을 원하는 사용자용
import datetime
from zoneinfo import ZoneInfo
datetime.datetime(2019, 12, 7, tzinfo=ZoneInfo("America/Los_Angeles"))
또 다른 방법으로는datetime"CHANGE: " "CHANGE: "CHANGE:
>>> from datetime import datetime, timezone
>>> datetime.now(timezone.utc)
datetime.datetime(2021, 5, 1, 22, 51, 16, 219942, tzinfo=datetime.timezone.utc)
Python은 매우 처음이고 저도 같은 문제를 겪었습니다.이 솔루션은 매우 심플하고, 나에게 있어서 정상적으로 동작합니다(Python 3.6).
unaware=parser.parse("2020-05-01 0:00:00")
aware=unaware.replace(tzinfo=tz.tzlocal()).astimezone(tz.tzlocal())
시간대 간 변경
import pytz
from datetime import datetime
other_tz = pytz.timezone('Europe/Madrid')
# From random aware datetime...
aware_datetime = datetime.utcnow().astimezone(other_tz)
>> 2020-05-21 08:28:26.984948+02:00
# 1. Change aware datetime to UTC and remove tzinfo to obtain an unaware datetime
unaware_datetime = aware_datetime.astimezone(pytz.UTC).replace(tzinfo=None)
>> 2020-05-21 06:28:26.984948
# 2. Set tzinfo to UTC directly on an unaware datetime to obtain an utc aware datetime
aware_datetime_utc = unaware_datetime.replace(tzinfo=pytz.UTC)
>> 2020-05-21 06:28:26.984948+00:00
# 3. Convert the aware utc datetime into another timezone
reconverted_aware_datetime = aware_datetime_utc.astimezone(other_tz)
>> 2020-05-21 08:28:26.984948+02:00
# Initial Aware Datetime and Reconverted Aware Datetime are equal
print(aware_datetime1 == aware_datetime2)
>> True
다음은 코드의 변경을 최소화하는 간단한 솔루션입니다.
from datetime import datetime
import pytz
start_utc = datetime.utcnow()
print ("Time (UTC): %s" % start_utc.strftime("%d-%m-%Y %H:%M:%S"))
시간(UTC): 09-01-2021 03:49:03
tz = pytz.timezone('Africa/Cairo')
start_tz = datetime.now().astimezone(tz)
print ("Time (RSA): %s" % start_tz.strftime("%d-%m-%Y %H:%M:%S"))
시간(RSA): 09-01-2021 05:49:03
unutbu의 답변 형식으로, 이런 것을 다루는 보다 직관적인 구문을 가진 유틸리티 모듈을 만들었습니다.pip과 함께 설치할 수 있습니다.
import datetime
import saturn
unaware = datetime.datetime(2011, 8, 15, 8, 15, 12, 0)
now_aware = saturn.fix_naive(unaware)
now_aware_madrid = saturn.fix_naive(unaware, 'Europe/Madrid')
특히 Unix 타임스탬프일 경우 팬더를 사용하는 매우 간단한 솔루션이 있습니다.
import pandas as pd
unix_timestamp = 1513393355
pst_tz = pd.Timestamp(unix_timestamp, unit='s', tz='US/Pacific')
utc_tz = pd.Timestamp(unix_timestamp, unit='s', tz='UTC')
언급URL : https://stackoverflow.com/questions/7065164/how-to-make-a-datetime-object-aware-not-naive-in-python
'source' 카테고리의 다른 글
| 셀이 변경될 때마다 Excel VBA가 매크로를 자동으로 실행 (0) | 2023.04.12 |
|---|---|
| WPF(C# 또는 vb.net)에서 응용 프로그램 실행 파일의 위치를 찾을 수 있습니까? (0) | 2023.04.12 |
| Python을 사용하여 다른 Excel 파일에서 복사한 열로 Excel 파일을 작성합니다. (0) | 2023.04.12 |
| Swift에서 문자열에서 첫 번째 문자를 제거하는 가장 간결한 방법은 무엇입니까? (0) | 2023.04.12 |
| Windows 의 빌트인 기능만을 사용해 스크립트를 압축 또는 압축 해제하려면 어떻게 해야 합니까? (0) | 2023.04.12 |