โ ๏ธ python2๋ฅผ ๊ธฐ์ค์ผ๋ก ํฉ๋๋ค!
๊ธ๋ก๋ฒ ์๋น์ค๋ฅผ ๋ง๋ค๊ฑฐ๋ ํด์ธ์ ์๋ฒ๋ฅผ ์ฌ์ฉํ๊ฒ ๋๋ฉด(๊ทธ๋ ์ง ์๋๋ผ๋) timezone์ ์ค์ ํด์ผ ํ๋ ๊ฒฝ์ฐ๊ฐ ์๋ค.
๊ฐ์ฅ ๋ง์ด ์ฐ๋ ๋ ์ง, ์๊ฐ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ธ datetime
์์๋ timezone์ ์ค์ ํ์ง ์์ผ๋ฉด ๊ธฐ๋ณธ ๊ฐ์ด ์์ด์ None
์ผ๋ก ์ฒ๋ฆฌ๋๋ค.
def __init__(self, year, month, day, hour=None, minute=None, second=None, microsecond=None, tzinfo=None):
datetime.tzinfo
์ฒ์ ๊ฐ์ฒด๋ฅผ ์์ฑํ ๋, tzinfo
๋ฅผ kwarg๋ก ์ฃผ๋ฉด ์ค์ ํ ์ ์๋ค.
datetime.datetime(2022, 1, 13, 11, 0, 0, tzinfo=tzinfo_value)
๋๋ datetime.now()
์ ๋ฃ์ด์ ์ค์ ํ ์๋ ์๋ค.
datetime.datetime.now(tzinfo_value)
datetime
๊ฐ์ฒด์ tzinfo
๊ฐ์ ๋ฐ๊พธ๋ ค๊ณ ํ๋๋ฐ, ์์ ํ ์ ์๋ค๊ณ ํ๋ค
>>> a = datetime.now()
>>> a.tzinfo = 9
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: attribute 'tzinfo' of 'datetime.datetime' objects is not writable
๊ทธ๋ ๋ค. tzinfo
๋ property
๋ผ์ ํ ๋น๋ฌธ์ผ๋ก ๊ทธ๋ฅ ์์ ํ ์ ์๋ ๊ฐ์ด ์๋์๋ค.
tzinfo = property(lambda self: object(), lambda self, v: None, lambda self: None) # default
๊ทธ๋ ๋ค๋ฉด ์ด๋ป๊ฒ ๋ฐ๊ฟ๊น?
datetime.replace()
class datetime(date):
...
def replace(self, year=None, month=None, day=None,
hour=None, minute=None, second=None,
microsecond=None, tzinfo=None): # known case of datetime.datetime.replace
์ ์ ์๋ฅผ ๋ณด๋ฉด ์ ์ ์๋ฏ์ด replace
๋ผ๋ ๋ฉ์๋๋ฅผ ํตํด ์์ ํ ์ ์๋ค. tzinfo
๋ฟ๋ง ์๋๋ผ ๋ค๋ฅธ ์ดํธ๋ฆฌ๋ทฐํธ๋ค๋ key-value ๋ก ๋ฐ๊ฟ ์ ์๋ค.
datetime.replace
๋ str.replace
์ ๊ฐ์ด ์๋ณธ ๊ฐ์ ์์ ํ์ง ์๊ณ ๋ณ๊ฒฝ๋ ๊ฐ์ ๋ฆฌํด๋ง ํ๋ค. ๊ทธ๋ฌ๋ ๋ณ๊ฒฝ ์ดํ์๋ ์ฐ๋ ค๋ฉด ํ ๋น๋ฌธ์ ์ฌ์ฉํ์
>>> today = datetime.now()
>>> today.replace(year=2023)
datetime.datetime(2023, 1, 13, 13, 54, 28, 956953)
๋๋์ด ์ข๋ค. ์ด์ tzinfo
๋ฅผ replace
๋ก ์์ ๋ง ํ๋ฉด ๋๋ค.
>>> today = datetime.now()
>>> today.replace(tzinfo=9)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: tzinfo argument must be None or of a tzinfo subclass, not type 'int'
์ด?
class tzinfo
class tzinfo(object):
""" Abstract base class for time zone info objects. """
...
์๋ฌ๋ฅผ ๋ณด๋ฉด์ ์ ์๋ฏ์ด tzinfo
์ดํธ๋ฆฌ๋ทฐํธ๋ ์ ์๊ฐ ์๋๋ผ tzinfo
๋ ์๋ธ ํด๋์ค์ ๊ฐ์ฒด์ฌ์ผ ํ๋ค.
ํ์์กด์ ์์ ํ๊ธฐ ์ํด tzinfo
๋ฅผ ์์ ๋ฐ์์ ํด๋์ค๋ฅผ ๋ง๋๋ ๊ฑด ๋นํจ์จ์ ์ผ๋ก ๋ณด์ธ๋คโฆ
ํ์ง๋ง ํ์ด์ฌ์ ์ฅ์ ์
์ ์ด๊ฑฐ ํ์ํ๋ฐโฆ
์ถ์ ๊ฒ๋ค์ ๋๊ตฐ๊ฐ๊ฐ ์ด๋ฏธ ๋ง๋ค์ด ๋๋ค๋ ๊ฒ์ด๋ค.
tzinfo
๋ฅผ ์์ํ ํด๋์ค๋คclass BaseTzInfo(tzinfo):
...
pytz
๋ ๋ฏธ๋ฆฌ ์ ์ ํด๋ ํ
์คํธ๋ฅผ ํตํด ํ์์กด์ ์ค์ ํ ์ ์๋ค.
์ ํํ ์คํธ๋ง์ ์ ์ด์ผ ํ๋ pytz.__init__.py:all_timezones
๋ฅผ ์ฐพ์์ ํ์ธํ์.
>>> from datetime import datetime
>>> from pytz import timezone
>>> now = datetime.now()
>>> now.replace(tzinfo=timezone('Asia/Seoul'))
datetime(2022, 1, 13, 14, 53, 16, 166880, tzinfo=<DstTzInfo 'Asia/Seoul' KST+9:00:00 STD>)
๋ฌผ๋ก ์ด๊ธฐํ ํ ๋๋ ๊ฐ๋ฅํ๋ค.
>>> datetime.now(timezone('Asia/Seoul'))
๊ทธ๋ฐ๋ฐ pytz
๋ฅผ ์ฌ์ฉํ ๋ ์กฐ์ฌํด์ผ ํ ๋ถ๋ถ์ด ์๋ค. 'Asia/Seoul'
, 'Asia/Pyongyang'
์ง์ญ์ ์ฌ์ฉํ ๋, 30๋ถ ์ ๋ ์ฐจ์ด๊ฐ ๋๋ ์ด์๊ฐ ์๋ค.
๋ฌผ๋ก ์ง๊ธ์ fix ๋๊ธด ํ์ง๋ง ์ด์ ๋ฒ์ ์ ์ฌ์ฉํ ๋๋ ๋ค์ ์ฒ๋ผ ๋์ฌ ์ ์๋ค.
>>> import pytz
>>> from datetime import datetime
>>> fmt = '%Y-%m-%d %H:%M:%S %Z%z'
>>> seoul = pytz.timezone('Asia/Seoul')
>>> seoul
<DstTzInfo 'Asia/Seoul' KST+8:30:00 STD>
๋ฎ์ ๋ฒ์ ์ django์์๋ ํ ์ ๋ ๋ ์ '+8:28'
๋ก ๋์จ๋ค.
>>> from datetime import datetime
>>> from django.utils import timezone
>>> timezone.get_default_timezone()
<DstTzInfo 'Asia/Seoul' LMT+8:28:00 STD>
dateutil.tz.tzoffset
class tzoffset(datetime.tzinfo):
...
tzoffset
์ UTC ๊ธฐ์ค์ผ๋ก ์ผ๋ง๋ ๋๋ฆฌ๊ณ ๋น ๋ฅธ์ง ์ด ๋จ์๋ก ์ค์ ํ ์ ์๋ค.
>>> from datetime import datetime
>>> from dateutil.tz import tzoffset
>>> now = datetime.now()
>>> now.replace(tzinfo=tzoffset('KST', 9 * 60 * 60))
datetime(2022, 1, 13, 15, 9, 10, 239466, tzinfo=tzoffset('KST', 32400))
>>> datetime.now(tzoffset('KST', 9 * 60 * 60))
datetime(2022, 1, 13, 15, 10, 16, 671827, tzinfo=tzoffset('KST', 32400))
๋ฌผ๋ก python3๋ ๋ด๋ถ์ ๋ค ๊ตฌํํด ๋ฌ์ ๊ทธ๋ฅ datetime
์ผ๋ก ์ ๋ถ ํด๊ฒฐ ๊ฐ๋ฅํ๋ค^^
from datetime import datetime, timedelta, timezone
now = datetime.now(timezone(timedelta(hours=9)))
import datetime
import dateutil.tz
datetime.datetime(2022, 1, 13, 11, 0, 0,
tzinfo=dateutil.tz.tzoffset('KST', 9 * 60 * 60))
datetime.tz.tzoffset ์์๋ค.