๐ŸŒ About Timezone

hyukimยท2022๋…„ 1์›” 13์ผ
0

โš ๏ธ 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๋ฅผ ์ƒ์†ํ•œ ํด๋ž˜์Šค๋“ค

pytz.tzinfo.BaseTzInfo

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

๋ฌผ๋ก  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 ์”์‹œ๋‹ค.

References

profile
๐Ÿ’ช ๐Ÿฅฉ ๐Ÿบ โœˆ ๐Ÿ’ป

0๊ฐœ์˜ ๋Œ“๊ธ€