ãµãŒããŒãµã€ããšã³ãžãã¢ã®äžæã§ãã åŒç€Ÿã§ã¯2024幎ã®åãããåœå€ãžãµãŒãã¹å±éãããæºåãšããŠãäžå¹Žã»ã©åããã·ã¹ãã ã®åœéå察å¿ãè¡ã£ãŠããŸããã ãã®æºåã«ã¯ããµãŒãã¹ã®å€èšèªå¯Ÿå¿ãæ¥æ¬æšæºæä»¥å€ã®ã¿ã€ã ãŸãŒã³ã§ãµãŒãã¹ãå©çšã§ããããã«ããæ¹ä¿®ãªã©ãå«ãŸããŸããããµãŒããŒããŒã ã§ã¯ç¹ã«åŸè
ã«èŠåŽããŸããã ããã§ãã®æ¹ä¿®ã§åŸãPythonã§ã¿ã€ã ãŸãŒã³ãæ±ãéã®ç¥èŠã®äžéšãããã®ããã°èšäºã«ãŸãšããŸãã ã¿ã€ã ãŸãŒã³ã«ã€ã㊠ã¿ã€ã ãŸãŒã³ã®åºæº UTCãªãã»ããã ãã§ã¿ã€ã ãŸãŒã³ãæ±ãåé¡ç¹ ãµããŒã¿ã€ã ç¹å®ã¿ã€ã ãŸãŒã³ã§ã®UTCãªãã»ããå€æŽ IANAã®Time Zone Database (äœè«) Time Zone Databaseããèªã¿åãäžçã®æŽå² Pythonã§ã®å®è£
ã®æ³šæç¹ pytzãdatetimeãªããžã§ã¯ãã®ã³ã³ã¹ãã©ã¯ã¿ã«æž¡ã pytzãªããžã§ã¯ããdatetimeã®ã³ã³ã¹ãã©ã¯ã¿ã«æž¡ããŠãããŸãåããªãçç± zoneinfoãã¡ã€ã«ã®ã1901幎åé¡ã strftime(%s)ã§ã®ãšããã¯ç§å€æ ãŸãšã ã¿ã€ã ãŸãŒã³ã«ã€ã㊠Pythonã§ã®å®è£
ã®è©±ã«å
¥ãåã«ããŸãã¯ã¿ã€ã ãŸãŒã³ã®æŠå¿µèªäœã«ã€ããŠèª¬æããŸãã ã¿ã€ã ãŸãŒã³ã®åºæº äžçäžã®åå°åã¯ç°ãªãæšæºæéãçšããŠããŠãå°åéã«æå·®ãããããšã¯èšããŸã§ããªããšæããŸãã ãããŠãããã®ç°ãªãæé垯ã®åºæºãšãªãæå»ãååšããããšãæåããšæããŸãã ãã¡ãã®åºæºæå»ã¯ãã€ã®ãªã¹ã®ã°ãªãããžå€©æå°ã«ãããæéãåºã«å®ããããŠãããšãæåŠæ ¡ã§ç¿ã£ãæ¹ãå€ããšæããŸãã çµåºŠ0床ã®å°ç¹ã«ããå倩æå°ãåºæºæéãšããèãã¯ãGMT (Greenwich Mean Time)ãšåŒã°ãããã®ã§ãããçŸåšãã¡ãã¯UTC (Coordinated Universal Time)ãšããæŠå¿µã«åã£ãŠä»£ããããŠããŸãã æ
£ç¿çã«åäžã®ãã®ãšæ±ãããããšãããäž¡è
ã§ãããå³å¯ã«ã¯æŠå¿µçãç®åºæ¹æ³çãªéãããããŸãã GMTã¯ã°ãªãããžå€©æå°ã§ã®å°æ¹å¹³åæã衚ããŸããã€ãŸãGMTã¯ç¹å®å°åã§ã®å€©äœèŠ³æž¬ãåºã«ç®åºãããããã³ãã³ããããæãäžã€ã®ã¿ã€ã ãŸãŒã³ã§ãã æ¯ã¹ãŠUTCã¯ã倩äœèŠ³æž¬ã ãã§ã¯ãªãååæèšã«åºã¥ãèšç®ãªã©ããç®åºãããåºæºæã§ãããèªäœã¯ã©ããã®å°åã®ã¿ã€ã ãŸãŒã³ã§ã¯ãªãã§ããå°çäžã®å°åã®æšæºæãããã®åºæºæãšã®å·®åã§è¡šçŸããããã«ååšããŠããŸãã UTCãªãã»ããã ãã§ã¿ã€ã ãŸãŒã³ãæ±ãåé¡ç¹ UTCã®ãããªåºæºãšãªãæéã®æŠå¿µãååšããã°ããããšã®ãªãã»ããïŒåºæºãšã®å·®ç°ïŒã®ã¿ãçšããŠã·ã¹ãã ã§äžçäžã®æéãåãæ±ãããã ãšäžèŠæããŸããããããå®éã¯ãããªçãã¯ãªãã§ãã以äžã«ãç¹å®å°åã®äººéã®çšããæéã®æŠå¿µãåäžã®UTCãªãã»ããã§ã¯è¡šããªãããšã®äŸãæããŸãã ãµããŒã¿ã€ã äžéšã®ã¿ã€ã ãŸãŒã³ã§ã¯ãäžå¹ŽãéããŠåãUTCãªãã»ããã®æéãçšããŠããããã§ã¯ãªããæ¥ç
§æéãé·ãææã«ã¯ãµããŒã¿ã€ã ãšããŠæéãæ©ããããšãè¡ãããŠããŸãã å ããŠããµããŒã¿ã€ã ã®éå§ã»çµäºææãæ¯å¹Žäžå®ãšã¯éãããé »ç¹ã«å€æŽãããå°åããããŸãã ïŒäŸïŒ1998幎ã®ãã©ãžã«ã§ã¯ã ãµããŒã¿ã€ã ã®éå§æ¥ãããŒãæçã®æ¥èšªææãšãããããäžæ¥é
ãããŸããã ïŒ ç¹å®ã¿ã€ã ãŸãŒã³ã§ã®UTCãªãã»ããå€æŽ æŽå²ãé¡ãã°ãå°çäžã®å€ãã®å°ç¹ã§æ¡çšããŠããæšæºæéã®å€æŽãè¡ãããŠããŸããã ïŒäŸïŒãµã¢ã¢ã§ã¯ã 2011幎ã«ã¿ã€ã ãŸãŒã³ãUTC-11ããUTC+13ã«å€æŽããŸããã ïŒ åŸè¿°ããéãããã®ãããªæšæºæéã®å€æŽãçµéšããå°åã«ã¯ãæ¥æ¬ãå«ãŸããŸãã IANAã®Time Zone Database äžè¿°ã®éãã人ã
ãçæŽ»ã§çšããŠããæéã®æŠå¿µã¯ãå£ç¯çãæŽå²çãªçç±ããåçŽãªUTCãªãã»ããäžã€ã§ã¯è¡šçŸããããªãå ŽåããããŸãã ããã§ããã®ãããªäžè¬çã«äœ¿ãããã¿ã€ã ãŸãŒã³ããå£ç¯çãªå€åãæŽå²çãªçµç·¯ãå
æ¬ããŠãŸãšããŠããã®ããTime Zone Databaseã§ãã www.iana.org Asia/Tokyo ãªã©ã®ããèŠãããã¿ã€ã ãŸãŒã³ã®è¡šèšã¯ãIANAã«ãã£ãŠç·šçºãããŠãããã¡ãã®ããŒã¿ããŒã¹ã«ãã£ãŠèŠå®ãããŠããŸãã ãã¡ãã®ããŒã¿ããŒã¹ã®æ
å ±ã¯ãããã°ã©ã ããã¯ãããããªç°å¢ã§å©çšã§ããŸããUnix likeãªã·ã¹ãã ã§ããã° /usr/share/zoneinfo/ ã«ãã€ããªåœ¢åŒã§å
¥ã£ãŠããã»ããPythonã®å®è¡ç°å¢ããåç
§ãããå Žå㯠tzdataãšããã¢ãžã¥ãŒã« ãçšããããšã§OSã«ãããå©çšã§ããŸãã ãã¡ãã®äžèº«ã確èªããäžçªç°¡åãªæ¹æ³ã¯ãäžèšã®IANAã®ãªã³ã¯ãéããããŒã¿ããŒã¹ã®ãã¡ã€ã«ãããŠã³ããŒããè§£åãéãããšã§ãã詊ãã«ãã¥ãŒãšãŒã¯ã®ã¿ã€ã ãŸãŒã³æ
å ±ãéããŠã¿ããšã以äžã®ããã«ãªã£ãŠããŸãã # Monthly Notices of the Royal Astronomical Society 44, 4 (1884-02-08), 208 # says that New York City Hall time was 3 minutes 58.4 seconds fast of # Eastern time (i.e., -4:56:01.6) just before the 1883 switch. # Rule NAME FROM TO - IN ON AT SAVE LETTER Rule NYC 1920 only - Mar lastSun 2 : 00 1 : 00 D Rule NYC 1920 only - Oct lastSun 2 : 00 0 S Rule NYC 1921 1966 - Apr lastSun 2 : 00 1 : 00 D Rule NYC 1921 1954 - Sep lastSun 2 : 00 0 S Rule NYC 1955 1966 - Oct lastSun 2 : 00 0 S # Zone NAME STDOFF RULES FORMAT [UNTIL] #STDOFF -4:56:01.6 Zone America/New_York - 4 : 56 : 02 - LMT 1883 Nov 18 17 :00u - 5 : 00 US E%sT 1920 - 5 : 00 NYC E%sT 1942 - 5 : 00 US E%sT 1946 - 5 : 00 NYC E%sT 1967 - 5 : 00 US E%sT æåã«ã³ã¡ã³ãã§ã1883å¹Žã®æšæºæéã®å€æŽãŸã§ã¯æ±æµ·å²žæéãã3å58.4ç§æ©ãã£ããšããè³æã®ç޹ä»ããããŠããŸãã ãã®åŸéå»ã®ãµããŒã¿ã€ã ã®å®æœã®æŽå²ããã³ã¡ã³ãã§æžãããŠãã1883幎以åã®æéã®çŸåšãšã®æå·®ã«ã€ããŠãèšè¿°ãããŠããŸãã (äœè«) Time Zone Databaseããèªã¿åãäžçã®æŽå² äžèšã®ãã¥ãŒãšãŒã¯ã®äŸã®éããTime Zone Databaseã¯åãªãæšæºæã®å€åçãèæ
®ããæå»å€æã®ã«ãŒã«ãèšèŒãããŠããã®ã¿ã§ãªããè±å¯ãªã³ã¡ã³ããããèªã¿ç©ãšããŠãé¢çœãã§ããæ¥æ¬ã®äŸãèŠãŠã¿ãŸãã # From Paul Eggert (1995-03-06): # Today's _Asahi Evening News_ (page 4) reports that Japan had # daylight saving between 1948 and 1951, but "the system was discontinued # because the public believed it would lead to longer working hours." # From Mayumi Negishi in the 2005-08-10 Japan Times: # http://www.japantimes.co.jp/cgi-bin/getarticle.pl5?nn20050810f2.htm # Occupation authorities imposed daylight-saving time on Japan on # [1948-05-01].... But lack of prior debate and the execution of # daylight-saving time just three days after the bill was passed generated # deep hatred of the concept.... The Diet unceremoniously passed a bill to # dump the unpopular system in October 1951, less than a month after the San # Francisco Peace Treaty was signed. (A government poll in 1951 showed 53% # of the Japanese wanted to scrap daylight-saving time, as opposed to 30% who # wanted to keep it.) # -- äžç¥ -- # Rule NAME FROM TO - IN ON AT SAVE LETTER/S Rule Japan 1948 only - May Sat>= 1 24 : 00 1 : 00 D Rule Japan 1948 1951 - Sep Sat>= 8 25 : 00 0 S Rule Japan 1949 only - Apr Sat>= 1 24 : 00 1 : 00 D Rule Japan 1950 1951 - May Sat>= 1 24 : 00 1 : 00 D # Zone NAME STDOFF RULES FORMAT [UNTIL] Zone Asia/Tokyo 9 : 18 : 59 - LMT 1887 Dec 31 15 :00u 9 : 00 Japan J%sT ã³ã¡ã³ãåã³ Rule ã®é
ã«ã¯ãæ¥æ¬ãéå»ã«å®æœããŠãããµããŒã¿ã€ã ã®æ
å ±ãèŒã£ãŠããŸããçµæŠçŽåŸæ¥æ¬ã§ã¯GHQã®æå°ã«ããã¿ã€ã ãŸãŒã³ãå°å
¥ããŠããããã§ããã人ã
ã¯ãµããŒã¿ã€ã ã«ãã£ãŠåŽåæéã䌞ã°ãããã®ã§ã¯ãªãããšäžå®ã«ãªã倧å€äžäººæ°ã§ãã£ãããããµã³ãã©ã³ã·ã¹ã³å¹³åæ¡çŽç· çµåŸæ¥æ¬ã䞻暩ãå埩ãããšãããã«ãµããŒã¿ã€ã ã¯å»æ¢ãããããã§ãã ã¡ãªã¿ã« Zone ã®é
ç®ã«ããéããæ¥æ¬ã¯1888å¹Žã®æ£æããåã«ã¯ä»ãã 18å59ç§ æ©ãæšæºæéãçšããŠããŸããïŒæ±äº¬ã®å°æ¹å¹³åæïŒã ä»ãŸã§ããã°ã©ã ã§æ¥æ¬æéãæ±ãã³ãŒããæžããéã«ãã¿ã€ã ãŸãŒã³åãæ±ãã®äžåã§æå³ããæå»ããã 18å59ç§ ãããæå»ãšãªããã°ãèµ·ãããªã©ããŠãã®æéãèŠãããšãããããšæããŸããããã®æéã¯ããããããŠããŸãïŒè©³ããäŸã¯åŸè¿°ããŸãïŒã Pythonã§ã®å®è£
ã®æ³šæç¹ ãã£ãšPythonã®è©±ã«å
¥ããŸãã Pythonã§timezone awareãªåœ¢ã§datetimeãªããžã§ã¯ããåãæ±ãéã«é¥ããããªèª€ãããããã€ãæããŠã¿ãŸãã pytzãdatetimeãªããžã§ã¯ãã®ã³ã³ã¹ãã©ã¯ã¿ã«æž¡ã Pythonã«ãããã¿ã€ã ãŸãŒã³é¢é£ã®ããããééãã§ã¯äžçªæåãªè©±ãããããŸãããã pytz åã®ã¿ã€ã ãŸãŒã³ãdatetimeãªããžã§ã¯ãã®ã³ã³ã¹ãã©ã¯ã¿ã«æž¡ããšã倧æµã®å Žåæå³ããªãdatetimeãªããžã§ã¯ããäœæãããŸãã >>> import datetime >>> import pytz >>> datetime.datetime( 2023 , 8 , 25 , 12 , 0 , 0 , tzinfo=pytz.timezone( 'Asia/Tokyo' )).utcoffset() datetime.timedelta(seconds= 33540 ) # â9æé19å äžèšã®ãããªã³ãŒããæžããå Žåãå®è£
è
ã¯å€§æµã®å ŽåUTCãªãã»ããã9æéã¡ããã©ã®ã¿ã€ã ãŸãŒã³ã®ãªããžã§ã¯ãã®çæãæåŸ
ããŠãããšæããŸãããå®éã«ã¯9æé19åãšãªã£ãŠããŸãã pytzã¯datetimeãªããžã§ã¯ãã®ã³ã³ã¹ãã©ã¯ã¿ã«æž¡ããããããªå©ç𿹿³ã¯æ³å®ãããŠãããïŒè©³ããã¯åŸè¿°ïŒããã®ãããªå©ç𿹿³ãã§ããªãããšã ããã¥ã¡ã³ãã«èšèŒãããŠããŸãã This library differs from the documented Python API for tzinfo implementations; if you want to create local wallclock times you need to use the localize() method documented in this document. äžèšåŒçšã«ããéããpytzã§datetimeãªããžã§ã¯ãã«ã¿ã€ã ãŸãŒã³æ
å ±ãä»äžãããå Žåã¯ã localize() ãçšããã®ãæ£è§£ã§ãã >>> pytz.timezone( 'Asia/Tokyo' ).localize(datetime.datetime( 2023 , 8 , 25 , 12 , 0 , 0 )).utcoffset() datetime.timedelta(seconds= 32400 ) # â9æéã¡ããã© ã¡ãªã¿ã«ãpytzãdatetimeãªããžã§ã¯ãã®ã³ã³ã¹ãã©ã¯ã¿ã«æž¡ãéã®ãã°ã¯äžã«äŸç€ºããŸããããããã¯ã³ã³ã¹ãã©ã¯ã¿ã ãã§ãªã replace() ã®åŒæ°ãšããŠæž¡ããŠãåæ§ã®äºè±¡ã¯èµ·ãããŸãã >>> import datetime >>> import pytz # ãŸãã¯timezone unawareãªdatetimeãªããžã§ã¯ããäœæ >>> d = datetime.datetime( 2023 , 8 , 25 , 12 , 0 , 0 ) >>> d datetime.datetime( 2023 , 8 , 25 , 12 , 0 ) # ããã«replace()ã§timezoneæ
å ±ãã€ãããšããã¯ã19åããã >>> d.replace(tzinfo=pytz.timezone( 'Asia/Tokyo' )).utcoffset() datetime.timedelta(seconds= 33540 ) # â9æé19å ãã¡ãã®çç±ã¯åçŽã§ãdatetimeã¯ã©ã¹ã® replace() ã¯å
éšã§æ°èŠã«ãªããžã§ã¯ãã®çæãè¡ã£ãŠããŠããã®éã«ã³ã³ã¹ãã©ã¯ã¿ã®åŒæ°ã« replace() ã®åŒæ°ããã®ãŸãŸæž¡ããŠããããã§ãã github.com def replace (self, year= None , month= None , day= None , hour= None , minute= None , second= None , microsecond= None , tzinfo= True , *, fold= None ): """Return a new datetime with new values for the specified fields.""" if year is None : year = self.year if month is None : month = self.month if day is None : day = self.day if hour is None : hour = self.hour if minute is None : minute = self.minute if second is None : second = self.second if microsecond is None : microsecond = self.microsecond if tzinfo is True : tzinfo = self.tzinfo if fold is None : fold = self.fold return type (self)(year, month, day, hour, minute, second, microsecond, tzinfo, fold=fold) æçµè¡ã§ãæ°ãã«ãªããžã§ã¯ããäœæããã®ã³ã³ã¹ãã©ã¯ã¿ã®äžã§tzinfoãæž¡ããŠããŸãã pytzãªããžã§ã¯ããdatetimeã®ã³ã³ã¹ãã©ã¯ã¿ã«æž¡ããŠãããŸãåããªãçç± pytzã®ãã®æåã¯Pythonçéã§ã¯çµæ§æåã§ããããªããã®ãããªæåã«ãªã£ãŠããã®ã説æããŠããããã°èšäºçã¯ãïŒèªåã®ãªããªãã®ãªãµãŒãèœåã ãšïŒèŠåœãããŸããã§ãããããã§ãå°ãèªåã§å®è£
ã調ã¹ãŠã¿ãŸããã ãŸããPythonã®datetimeã®ããã¥ã¡ã³ãã«ã¯ä»¥äžã®ãããªèšè¿°ããããŸããã docs.python.org For applications requiring aware objects, datetime and time objects have an optional time zone information attribute, tzinfo, that can be set to an instance of a subclass of the abstract tzinfo class. These tzinfo objects capture information about the offset from UTC time, the time zone name, and whether daylight saving time is in effect. Only one concrete tzinfo class, the timezone class, is supplied by the datetime module. The timezone class can represent simple timezones with fixed offsets from UTC, such as UTC itself or North American EST and EDT timezones. Supporting timezones at deeper levels of detail is up to the application. The rules for time adjustment across the world are more political than rational, change frequently, and there is no standard suitable for every application aside from UTC. Pythonã®æšæºã©ã€ãã©ãªã§ããdatetimeã§ã¯ãã¿ã€ã ãŸãŒã³æ
å ±ãšããŠã¯ tzinfo ãšããæœè±¡ã¯ã©ã¹ *1 ãšããã®å®è£
ãšã㊠timezone ãšããã¯ã©ã¹ãçšæããŠããŸããããã¡ãã®å®è£
ã¯UTCãªãã»ãããåºå®ã§ããåæãšãªã£ãŠããŸããUTCãªãã»ãããæŽå²ççµç·¯ãªã©ã§å€ãã£ãŠãããããªãå®éã®æéã®æŠå¿µã«è¿ããã®ã䜿ããããã°ãåã©ã€ãã©ãªãå©çšããã¢ããªã±ãŒã·ã§ã³åŽã§ tzinfo ããããªã«å®è£
ããŠã©ãã«ãããŠãããšããæå³ã®ããã§ãã ãã¡ãã®tzinfoã®ã¯ã©ã¹ã§ãããå®è£
ã®éã«UTCãªãã»ãããããæãã«å¯Ÿå¿ããã«ã¯ utcoffset() ãšããã¡ãœãããäžæžãããŠã»ããããã§ãã class tzinfo : """Abstract base class for time zone info classes. Subclasses must override the tzname(), utcoffset() and dst() methods. """ __slots__ = () def tzname (self, dt): "datetime -> string name of time zone." raise NotImplementedError ( "tzinfo subclass must override tzname()" ) def utcoffset (self, dt): "datetime -> timedelta, positive for east of UTC, negative for west of UTC" raise NotImplementedError ( "tzinfo subclass must override utcoffset()" ) def dst (self, dt): """datetime -> DST offset as timedelta, positive for east of UTC. Return 0 if DST not in effect. utcoffset() must include the DST offset. """ raise NotImplementedError ( "tzinfo subclass must override dst()" ) # 以äžç¥ 次ã«ãdatetimeãªããžã§ã¯ãã®ã³ã³ã¹ãã©ã¯ã¿ã«æž¡ããŠãæ£ããåãã dateutil.tz ã®å®è£
ã§ã¯ãã® utcoffset() ãã©ãå®è£
ããŠããã®ãã¿ãŠã¿ãŸãã github.com def utcoffset (self, dt): if dt is None : return None if not self._ttinfo_std: return ZERO return self._find_ttinfo(dt).delta # äžç¥ âãã¡ãã¯äžã®é¢æ°ããåŒã°ããŠãã def _find_ttinfo (self, dt): idx = self._resolve_ambiguous_time(dt) return self._get_ttinfo(idx) # äžç¥ âãã¡ãã¯äžã®é¢æ°ããåŒã°ããŠãã def _resolve_ambiguous_time (self, dt): idx = self._find_last_transition(dt) # If we have no transitions, return the index _fold = self._fold(dt) if idx is None or idx == 0 : return idx # If it's ambiguous and we're in a fold, shift to a different index. idx_offset = int ( not _fold and self.is_ambiguous(dt, idx)) return idx - idx_offset äžã®ã³ãŒãã§ã¯ã utcoffset() ãåŒã°ããéã«ã¯æ¯åãå
éšã§æšæºæéã®å€é·ã®æŽå²ãåç
§ãã颿°ãåŒã³åºãããã®çµæãåèã«æ¡çšãã¹ãUTCãšã®ãªãã»ãããå°ãåºããŠããŸãããã®ããšãããdateutil.tzã§ã¯ utcoffset() ãåŒã³åºããããšããã®éœåºŠæšæºæéã®éæŽãèæ
®ããŠUTCãªãã»ããã®å€å®ãããŠããããšãããããŸãã æ¯ã¹ãŠãã³ã³ã¹ãã©ã¯ã¿ã«æž¡ããšããŸãåããªãpytzã®æ¹ã®å®è£
ãèŠãŠã¿ãŸãã github.com def utcoffset (self, dt, is_dst= None ): # 颿°ã®ã³ã¡ã³ãã¯é·ãã®ã§ç¥ if dt is None : return None elif dt.tzinfo is not self: dt = self.localize(dt, is_dst) return dt.tzinfo._utcoffset else : return self._utcoffset ãã¡ãã¯æ¡ä»¶åå²ã«ãã£ãŠã¯ãdateutil.tzã§ã®å Žåã®ãããªUTCãªãã»ããã®æ±ºå®ã®ããã®è€éãªèšç®ã¯ããã«ãäºåã«ã¯ã©ã¹ã«ã»ããããã _utcoffset ã®å€ãåçŽã«è¿ãã®ã¿ã«ãªããŸããåºæ¬çã«datetimeãªããžã§ã¯ããçæãããŠãã㯠utcoffset() ãåŒã°ããéã«ã¯ãäžèšã³ãŒãã®æ¡ä»¶åå²äžçªæåŸã® else ç¯ã«å
¥ãããã§ãã£ãã®ã§ãpytzã¯ã€ã³ã¹ã¿ã³ã¹äœææã«èšå®ãããUTCãªãã»ãããè¿ãç¶ããæåã«ãªã£ãŠãããã§ãã äžèšã®å®è£
2äŸããã¯ãdateutil.tzã®æ¹ã¯UTCãªãã»ãããåç
§ãããå Žåã¯æ¯ååŒæ°ã®datetimeãªããžã§ã¯ãã®æ¥ä»ã確èªããŠUTCãªãã»ãããæ±ºå®ããŠããŠãpytzã®æ¹ã¯äžåºŠUTCãªãã»ããã®å€ãèšå®ãããããããè¿ãç¶ããããšããéããèŠãŠåããŸãã datetimeãªããžã§ã¯ãã®ã³ã³ã¹ãã©ã¯ã¿ã«ã¿ã€ã ãŸãŒã³ãæž¡ããŠãŒã¹ã±ãŒã¹ã®å Žåãå
ã«åŒæ°ãšããŠæž¡ãããã«äœæãããã¿ã€ã ãŸãŒã³ãªããžã§ã¯ãã¯äœæäºå®ã®datetimeãªããžã§ã¯ããèªã¿åããªãã®ã§ãã©ã®ãã㪠tzinfo ã®å®è£
ã§ããäžæŠã¯æ£ç¢ºã«ã¯UTCãªãã»ãããæ±ºããããªãç¶æ
ã«ãªããŸããdateutil.tzã®æ¹ã¯ãã®åŸæ¹ããŠdatetimeãªããžã§ã¯ãã®æ¥ä»ã確èªããŠUTCãªãã»ãããåèšç®ããã¿ã€ãã³ã°ãããã®ã«å¯Ÿããpytzã®å Žåã¯ããããªãããã§ãã ãã®ããšãããpytzãªããžã§ã¯ããdatetimeãªããžã§ã¯ãã®ã³ã³ã¹ãã©ã¯ã¿ã«æž¡ããšãUTCãªãã»ãããäžæãªç¶æ
ã§èšé²ããã該åœã¿ã€ã ãŸãŒã³ã§ã®æãå€ãUTCãªãã»ããã®æ
å ±ãä¿æãç¶ã *2 ãäžè¿°ã®ãããªæåãèµ·ãããšæãããŸãã zoneinfoãã¡ã€ã«ã®ã1901幎åé¡ã äžã§ãTime Zone Databseã®æ
å ±ã¯Unix likeãªç°å¢ã§ã¯ /usr/share/zoneinfo 以äžã«åæ
å ±ãå
¥ã£ãŠãããšæžããŸããã ãã®ãã¡ã€ã«ãçšããŠã¿ã€ã ãŸãŒã³ãæ±ãéã®æå³ããªãæåã玹ä»ããŸãã äžéšã®ç°å¢ *3 ã§ä»¥äžã®ãããªã³ãŒããå®è¡ãããšãæå³ããæéããã18å59ç§ãããããšã«ãªããŸãã >>> import datetime >>> import dateutil.tz # å¹Žææ¥ã¯ãªãã«æéã®ã¿ãæå®ããŠdatetimeãªããžã§ã¯ããäœæããããã«dateutil.tzã§Asia/Tokyoã®ã¿ã€ã ãŸãŒã³æ
å ±ãä»äžããUTCãªãã»ãããååŸ >> datetime.datetime.strptime( '12:00' , '%H:%M' ).replace(tzinfo=dateutil.tz.gettz( 'Asia/Tokyo' )).utcoffset() datetime.timedelta(seconds= 33539 ) # UTCãªãã»ããã¯9æé(32400ç§)ãæåŸ
ããŠããã®ã«ã9æé18å59ç§(33539ç§)ãšãªã£ã (äžã®ã³ãŒãã¯ãããããæ¥ä»ã®ãªãæéã®ããŒã¿ãæ±ãã®ã«datetime.timeã§ã¯ãªãäœèšã«æ
å ±éã®å€ãdatetime.datetimeãçšããŠãããšãããæ¬è³ªçãªééãã§ãããããã«ã¯ç®ãçã£ãŠãã ããã) ãã¡ãã¯ãdatetimeãªããžã§ã¯ãã§æéã®ã¿ãæå®ãããšå¹Žææ¥ã¯1900幎1æ1æ¥ãšãªãããšãäžéšã®ç°å¢ã§Time Zone Databaseã®æ
å ±ãèŒã£ãŠãããã€ããªã®ãã¡ã€ã«ã§æ¥ä»ããŒã¿ã32ããããŸã§ããæ±ããŠããªãããšãã®äºã€ã®èŠå ãéãªã£ãŠãã®ãããªæåã«ãªã£ãŠããŸãã åè
ã«ã€ããŠã¯ã1900幎1æ1æ¥æç¹ã§ã¯æ¢ã«æ¥æ¬ã§ã¯ä»ãšåãæšæºæéãæ¡çšãããŠããç¶æ
ã§ãã£ãããããã¡ãåäœã§ã¯UTCãªãã»ããã¯9æé18å59ç§ãšã¯ãªããªãã¯ãã§ãã åŸè
ã«ã€ããŠã¯ã32ãããã§æ±ããæéã®ç¯å²ãè¶
ãããšã³ã³ãã¥ãŒã¿ã誀åäœãããšèšãããã2038幎åé¡ããšåæºã§ãã32bitã®ç§æ°ã§ãšããã¯æéããè² ã®æ¹åã«åãã£ãŠè¡šçŸã§ããéçã¯1901幎ã®12æ13æ¥ã§ãããdatetimeãªããžã§ã¯ãã«èªåã§ã€ãããã1900幎1æ1æ¥ã¯ãããããå€ããããäžéšç°å¢ã§UTCãªãã»ããã®èšç®ãããŸããããªã£ãŠããããã§ãã äžèšã®äºè±¡ãåçŸããç°å¢ã§åç
§ãããŠããã¿ã€ã ãŸãŒã³ã®æ
å ±ã®ãã¡ã€ã«ãã RFC8536ã§ã®ä»æ§ ãããšã«ãã€ããªãèªãã§ã¿ãŸãã $ hexdump -C /usr/share/zoneinfo/Asia/Tokyo 00000000 54 5a 69 66 32 00 00 00 00 00 00 00 00 00 00 00 |TZif2...........| 00000010 00 00 00 00 00 00 00 04 00 00 00 04 00 00 00 00 |................| 00000020 00 00 00 09 00 00 00 04 00 00 00 0c 80 00 00 00 |................| 00000030 d7 3e 02 70 d7 ed 59 f0 d8 f8 fa 70 d9 cd 3b f0 |.>.p..Y....p..;.| 00000040 db 07 00 f0 db ad 1d f0 dc e6 e2 f0 dd 8c ff f0 |................| 00000050 03 01 02 01 02 01 02 01 02 00 00 83 03 00 00 00 |................| 00000060 00 8c a0 01 04 00 00 7e 90 00 08 00 00 7e 90 00 |.......~.....~..| 00000070 08 4c 4d 54 00 4a 44 54 00 4a 53 54 00 00 00 00 |.LMT.JDT.JST....| 00000080 01 00 00 00 01 54 5a 69 66 32 00 00 00 00 00 00 |.....TZif2......| 00000090 00 00 00 00 00 00 00 00 00 00 00 00 04 00 00 00 |................| 000000a0 04 00 00 00 00 00 00 00 0a 00 00 00 04 00 00 00 |................| 000000b0 0c f8 00 00 00 00 00 00 00 ff ff ff ff 65 c2 a4 |.............e..| 000000c0 70 ff ff ff ff d7 3e 02 70 ff ff ff ff d7 ed 59 |p.....>.p......Y| 000000d0 f0 ff ff ff ff d8 f8 fa 70 ff ff ff ff d9 cd 3b |........p......;| 000000e0 f0 ff ff ff ff db 07 00 f0 ff ff ff ff db ad 1d |................| 000000f0 f0 ff ff ff ff dc e6 e2 f0 ff ff ff ff dd 8c ff |................| 00000100 f0 00 03 01 02 01 02 01 02 01 02 00 00 83 03 00 |................| 00000110 00 00 00 8c a0 01 04 00 00 7e 90 00 08 00 00 7e |.........~.....~| 00000120 90 00 08 4c 4d 54 00 4a 44 54 00 4a 53 54 00 00 |...LMT.JDT.JST..| 00000130 00 00 01 00 00 00 01 0a 4a 53 54 2d 39 0a |........JST-9.| 0000013e äžèšç»åã«èª¬æãæžããéããæ¬ãã¡ã€ã«ã«ã¯UTCãªãã»ãããä»ããã18å59ç§ãããŠããææã®ã«ãŒã«ãèšèŒãããŠããŸããããã¡ããæ¡çšãããŠããæåŸã®æéã«ãããéšåã«ã笊å·ä»ã32bitã®intergerã®æå°å€ã§ãã 80 00 00 00 (-2147483648)ãå
¥ã£ãŠããŸãããã¡ããUNIX timeãšããŠèªã¿åããš1901幎12æ13æ¥äžã®æéã«ãªãããããã以åã®æéã¯ãã®ãã¡ã€ã«ãåç
§ããéãUTCãªãã»ããã9æé18å59ç§ãšæ±ãããŠããŸããŸããïŒå®éã«ãã®UTCãªãã»ããã®æšæºæéãå©çšãããŠããã®ã¯1887幎æ«ãŸã§ãªã®ã§ãããã14幎åã®æ¥æ¬æéã¯æ£ãã倿ã§ããªãããšã«ãªããŸããïŒ éã«ããã®çŸè±¡ãèµ·ããªãçè
ã®Macäžã®åããã¡ã€ã«ãèŠãŠã¿ããšããã®ç¬Šå·ä»ã32bitæŽæ°ã§ã¯UNIX timeãšããŠæ±ããªãææã®ããŒã¿ã¯ãçç¥ãããŠããããšãããããŸããã % hexdump -C /usr/share/zoneinfo/Asia/Tokyo 00000000 54 5a 69 66 32 00 00 00 00 00 00 00 00 00 00 00 |TZif2...........| 00000010 00 00 00 00 00 00 00 03 00 00 00 03 00 00 00 00 |................| 00000020 00 00 00 08 00 00 00 03 00 00 00 08 d7 3e 02 70 |.............>.p| 00000030 d7 ed 59 f0 d8 f8 fa 70 d9 cd 3b f0 db 07 00 f0 |..Y....p..;.....| 00000040 db ad 1d f0 dc e6 e2 f0 dd 8c ff f0 00 01 00 01 |................| 00000050 00 01 00 01 00 00 8c a0 01 00 00 00 7e 90 00 04 |............~...| 00000060 00 00 7e 90 00 04 4a 44 54 00 4a 53 54 00 00 00 |..~...JDT.JST...| 00000070 01 00 00 01 54 5a 69 66 32 00 00 00 00 00 00 00 |....TZif2.......| 00000080 00 00 00 00 00 00 00 00 00 00 00 04 00 00 00 04 |................| 00000090 00 00 00 00 00 00 00 09 00 00 00 04 00 00 00 0c |................| 000000a0 ff ff ff ff 65 c2 a4 70 ff ff ff ff d7 3e 02 70 |....e..p.....>.p| 000000b0 ff ff ff ff d7 ed 59 f0 ff ff ff ff d8 f8 fa 70 |......Y........p| 000000c0 ff ff ff ff d9 cd 3b f0 ff ff ff ff db 07 00 f0 |......;.........| 000000d0 ff ff ff ff db ad 1d f0 ff ff ff ff dc e6 e2 f0 |................| 000000e0 ff ff ff ff dd 8c ff f0 03 01 02 01 02 01 02 01 |................| 000000f0 02 00 00 83 03 00 00 00 00 8c a0 01 04 00 00 7e |...............~| 00000100 90 00 08 00 00 7e 90 00 08 4c 4d 54 00 4a 44 54 |.....~...LMT.JDT| 00000110 00 4a 53 54 00 00 00 00 01 00 00 00 01 0a 4a 53 |.JST..........JS| 00000120 54 2d 39 0a |T-9.| 00000124 ããŒã¿ã®åæ°ãåé¡ã®èµ·ããç°å¢ãšæ¯ã¹äžã€æžã£ãŠããããšãšã9æé18å59ç§ã®UTCãªãã»ããã衚ã 83 03 ïŒ09:18:59ãç§æ°ã«ãã33540ã®16鲿°è¡šèšïŒãšããå€ãïŒæéã®å€æã«ãŒã«ã®é
ç®ããã¯ïŒèŠåœãããªãããšãããããŸãã ããã«ãã£ãŠ1888幎1æ1æ¥ãã1901幎12æ13æ¥ãŸã§ã®æ¥æ¬ã®æ¥ä»ãæ£ããæ±ããããã«ãªããŸãããéã«1887幎æ«ä»¥åã®ããŒã¿ã¯å®éã®åœæã®æšæºæãšã¯ãããæéã§åãæ±ãããŸãã # 1887幎æ«ä»¥åã®æšæºæãzoneinfoãã¡ã€ã«ã«èšé²ãããŠããªããçè
ã®Macã§å®è¡ >>> datetime.datetime( 1887 , 1 , 1 , 0 , 0 , 0 , tzinfo=dateutil.tz.gettz( "Asia/Tokyo" )).utcoffset() datetime.timedelta(seconds= 32400 ) # âå®éã¯33540(9æé18å59ç§)ã§ããã¹ããã32400(9æé)ãšãªã£ãŠããŸã£ãŠãã äœããã®çç±ã§1887幎以åã®æ¥æ¬ã®æ¥ä»ããŒã¿ãæ±ãããå Žåã¯ããã¡ãã®æåã«æ°ãã€ããå¿
èŠãããããã§ãã strftime(%s)ã§ã®ãšããã¯ç§å€æ datetimeãªããžã§ã¯ãããšããã¯ç§ã«å€æãããå Žåã«ã strftime(%s) ãçšããããšã§ãããå®çŸã§ãããšæžããŠããèšäºãã¡ãã»ãååšããŸãã ããããã¡ã㯠Pythonã®datetimeã®ããã¥ã¡ã³ã ã§ã¯ãµããŒããããŠãããšã¯äžåæžããŠããããéæšå¥šã§ãã # æ¥æ¬æéã§åãç°å¢ã§ã >>> import time >>> time.tzname ( 'JST' , 'JST' ) >>> import datetime >>> import dateutil.tz # çŸåšæå»ãååŸããåŸãããã«ãã¥ãŒãšãŒã¯ã®ã¿ã€ã ãŸãŒã³ãä»äžããŸã >>> d = datetime.datetime.now().astimezone(dateutil.tz.gettz( 'America/New_York' )) >>> d datetime.datetime( 2024 , 2 , 8 , 1 , 41 , 57 , 844204 , tzinfo=tzfile( '/usr/share/zoneinfo/America/New_York' )) # strftime(%s)ãçšããŠãšããã¯ç§ã«å€æ >>> epoch_s = d.strftime( "%s" ) >>> epoch_s '1707324117' # ãããdatetimeã«å€æãåã³ãã¥ãŒãšãŒã¯ã®ã¿ã€ã ãŸãŒã³ãã€ãããšãããšãã14æéãããŠããããšãããããŸã >>> datetime.datetime.fromtimestamp( int (epoch_s)).astimezone(dateutil.tz.gettz( 'America/New_York' )) datetime.datetime( 2024 , 2 , 7 , 11 , 41 , 57 , tzinfo=tzfile( '/usr/share/zoneinfo/America/New_York' )) # ãã¡ãã¯ãšããã¯ç§å€æã®éã«ããã¥ãŒãšãŒã¯ã§ã®æéãšããŠã§ã¯ãªãæ¥æ¬æéãšããŠå€æãããããã§ã äžèšã®ã³ãŒãäŸã®éãã strftime(%s) ã ãšå€æå
ã®datetimeãªããžã§ã¯ããtimezone awareã§ãã£ããšããŠãã倿æã«ã¯ãã®ã¿ã€ã ãŸãŒã³æ
å ±ã§ã¯ãªããå®è¡ç°å¢ã®ã¿ã€ã ãŸãŒã³æ
å ±ãåç
§ããŠããŸããŸãã ïŒæ¥æ¬æéã§åãç°å¢ã§ãæ¥æ¬æéã®æå»ããŒã¿ã®ã¿ãæ±ã£ãŠãããšæ°ã¥ããã«ãã®ãããªå®è£
ãçŽããŠããŸããããããŸããããã©ã¡ããäžæ¹ãæ¥æ¬æé以å€ãšãªããšãã¡ãã¯äžå
·åãèµ·ãããŸããïŒ ãã¡ãdatetimeãªããžã§ã¯ãããšããã¯ç§ã«å€æãããå Žåã¯ã timestamp() ã䜿ãã®ãæ£è§£ã§ãã ãŸãšã ã³ã³ãã¥ãŒã¿ã§æ±ãå Žåã®ã¿ã€ã ãŸãŒã³ã®æŠå¿µã¯ãåãªãå°åéã®æå·®ã®å¯ãéãã§ã¯ãªããæŽå²çå€é·ãªã©æéè»žã®æ
å ±ãå«ãã è€éãªãã®ã§ã (Pythonãã¿ã€ã ãŸãŒã³ãšãã«éã£ã話ã§ã¯ãªãã§ãã)ã¡ãããšããã¥ã¡ã³ãèªã¿ãŸããã *1 : å³å¯ã«ãããšããã¯æœè±¡ã¯ã©ã¹ãšã¯åŒã°ãªããããããªãã§ãããå®éã®å®è£
ã¯ãªãå©çšåŽã§ã®é¢æ°ã®overrideãæåŸ
ããŠããã¯ã©ã¹ãšããæå³ã§ãéã«ãã®èªã䜿ã£ãŠãŸã *2 : pytzã®ãªããžã§ã¯ããã³ã³ã¹ãã©ã¯ã¿å
ã§ãšããããæãå€ãææã®UTCãªãã»ãããåç
§ããéšåã®å®è£
ã¯ãã¡ã: https://github.com/stub42/pytz/blob/fb43f957c5149e750c3be3cfc72b22ad94db4886/src/pytz/tzinfo.py#L189 *3 : ubuntu:focal-20230412ã®Dockerã€ã¡ãŒãžãããšã«ããã³ã³ããã§apt-get install tzdataãããéã«çºçããã®ã確èªããŸãã