PEP 431 – 시간대 지원 개선
- Author:
- Lennart Regebro <regebro at gmail.com>
- BDFL-Delegate:
- Barry Warsaw <barry at python.org>
- Status:
- Superseded
- Type:
- Standards Track
- Created:
- 11-Dec-2012
- Post-History:
- 11-Dec-2012, 28-Dec-2012, 28-Jan-2013
- Superseded-By:
- 615
번역·라이선스 안내
이 비공식 한국어 번역은 원문 Copyright 절의 Public Domain 조건에 따라 제공합니다. 원저자와 공식 원문은 그대로 표시합니다. 수정되지 않은 기준 원문 · 공식 최신판
초록
이 PEP는 Python 표준 라이브러리에 구체적인 시간대 지원을 구현하고, DST 변경 중 모호한 시간 명세를 처리할 수 있도록 시간대 API도 개선할 것을 제안합니다.
철회
오랜 논의 끝에 제가 datetime의 구현에서 문제라고 생각했던 사항들이 의도된 것임이 밝혀졌습니다. 여기에는 날짜시간 산술을 수행할 때 DST 전환을 완전히 무시하는 것이 포함됩니다. 따라서 is_dst 플래그는 아무런 유용한 기능도 하지 못하므로 이 PEP의 일부로서 무의미합니다. datetime은 설계상 모호한 날짜시간을 구분하지 않으며 앞으로도 그렇게 하지 않을 것입니다.
따라서 이 PEP를 철회합니다.
UPDATE: PEP 615 “표준 라이브러리에서 IANA 시간대 데이터베이스 지원”은 Python 3.9에 zoneinfo 모듈을 추가했으며 이 PEP를 대체했습니다.
제안
구체적인 시간대 지원
Python의 시간대 지원에는 고정 오프셋을 지원하는 tzinfo 기반 클래스 외에 표준 라이브러리 내의 구체적인 구현이 없습니다. 시간대를 적절히 지원하려면 현재 시간대와 과거의 시간대를 모두 포함하고 일광 절약 시간 변경까지 포함하는 모든 시간대의 데이터베이스가 필요합니다. 그러나 이러한 정보는 자주 변경되므로 Python 릴리스에 최신 정보를 포함하더라도 불과 몇 달 후에는 해당 정보가 오래된 것이 됩니다.
따라서 시간대 지원은 두 서드파티 모듈인 pytz와 dateutil을 통해서만 제공되어 왔으며, 두 모듈 모두 “zoneinfo” 데이터베이스를 포함하고 래핑합니다. “tz” 또는 “The Olsen database”라고도 불리는 이 데이터베이스는 시간대에 대한 사실상의 표준 시간대 데이터베이스이며, OS X를 포함한 대부분의 Unix 및 Unix 계열 운영 체제에 포함되어 있습니다.
이를 통해 표준 라이브러리에 zoneinfo 데이터를 지원하는 코드를 포함하되, 기본적으로 운영 체제의 데이터 사본을 사용하고, 일반적으로 운영 체제 또는 배포판의 업데이트 메커니즘을 통해 해당 사본이 최신 상태로 유지되도록 할 수 있습니다.
Windows와 같이 zoneinfo 데이터베이스를 포함하지 않는 운영 체제를 사용하는 경우 Python 소스 배포판에 zoneinfo 데이터베이스의 사본이 포함되며, 최신 zoneinfo 데이터베이스를 포함한 배포 패키지도 Python 패키지 색인에서 제공되므로 easy_install이나 pip같은 Python 패키징 도구로 쉽게 설치할 수 있습니다. 더 이상 업데이트를 받지 않아 데이터베이스가 오래된 Unix 계열 시스템에서도 이를 수행할 수 있습니다.
이러한 메커니즘을 사용하면 Python은 모든 플랫폼에서 표준 라이브러리를 통해 완전한 시간대 지원을 제공하며, 간단한 패키지 설치만으로 Windows처럼 zoneinfo 데이터베이스가 포함되지 않은 플랫폼이나 운영 체제 업데이트가 더 이상 제공되지 않는 플랫폼에서 업데이트된 시간대 데이터베이스를 사용할 수 있게 됩니다.
시간대 지원은 datetime모듈을 패키지로 만들고 Stuart Bishop의 pytz모듈을 기반으로 datetime에 시간대 지원을 추가하여 구현합니다.
현지 시간대 가져오기
Unix에는 사용 중인 시간대의 이름을 알아내는 표준 방법이 없습니다. 사용할 수 있는 모든 정보는 EST와 PDT같은 시간대 약어뿐이지만, 이러한 약어 중 상당수는 모호하므로 이를 바탕으로 자신이 어느 시간대에 있는지 알아낼 수 있다고 의존해서는 안 됩니다.
그러나 컴파일된 시간대 정보가 /etc/localtime에 있으므로 이를 찾는 표준 방법은 있습니다. 따라서 시간대의 이름을 알지 못하더라도 올바른 시간대 정보를 가진 현지 시간대 객체를 만들 수 있습니다. 현지 시간대를 반환하는 함수를 datetime에 제공해야 합니다.
이를 위한 지원은 Lennart Regebro의 tzlocal모듈을 새로운 datetime모듈에 통합하여 구현합니다.
Windows에서는 현지 Windows 시간대 이름을 조회하고, 유니코드 컨소시엄이 제공하는 Windows 시간대 이름과 zoneinfo 시간대 이름 간의 매핑을 사용하여 이를 zoneinfo 시간대로 변환합니다.
매핑은 각 주요 릴리스 또는 버그 수정 릴리스 전에 업데이트해야 하며, 이를 수행하는 스크립트는 Tools/디렉터리에 제공됩니다.
모호한 시간
일광 절약 시간제(DST)에서 전환할 때 시계를 한 시간 되돌립니다. 이는 해당 한 시간 동안의 시간이 DST 적용 시 한 번, DST 미적용 시 다시 한 번, 총 두 번 발생한다는 의미입니다. 마찬가지로 일광 절약 시간제로 전환할 때는 한 시간이 사라집니다.
현재 시간대 API는 DST에서 전환하는 동안 발생하는 두 개의 모호한 시간을 구분할 수 없습니다. 예를 들어 스톡홀름에서는 2012-11-28 02:00:00이라는 시간이 UTC 2012-11-28 00:00:00과 2012-11-28 01:00:00에 모두 두 번 발생합니다.
현재 시간대 API는 이를 명확히 구분할 수 없으므로 어느 시간을 반환해야 하는지 명확하지 않습니다.:
# This could be either 00:00 or 01:00 UTC:
>>> dt = datetime(2012, 10, 28, 2, 0, tzinfo=zoneinfo('Europe/Stockholm'))
# But we can not specify which:
>>> dt.astimezone(zoneinfo('UTC'))
datetime.datetime(2012, 10, 28, 1, 0, tzinfo=<UTC>)
pytz는 이러한 문제가 필요할 때 시간을 구분할 수 있도록 tzinfo 객체의 여러 메서드에 is_dst 매개변수를 추가하여 이 문제를 해결했습니다.
이 PEP는 datetime API의 관련 메서드에 이러한 is_dst 매개변수를 추가하고, 따라서 이 기능을 datetime에 직접 추가할 것을 제안합니다. 이는 기존 외부 라이브러리를 단순히 재구성하는 것이 아니라 새 코드를 작성해야 하므로, 이 기능을 포함하도록 datetime 라이브러리의 C 버전을 업데이트해야 한다는 점에서 이 PEP에서 가장 어려운 부분일 가능성이 높습니다.
구현 API
zoneinfo 데이터베이스
최신 버전의 zoneinfo 데이터베이스는 Python 소스 제어 시스템의 Lib/tzdata 디렉터리에 있어야 합니다. 이 데이터베이스 사본은 모든 Python 기능 릴리스와 버그 수정 릴리스 전에 업데이트해야 하지만, 보안 수정 전용 모드인 Python 버전의 릴리스에서는 업데이트하지 않아야 합니다.
데이터베이스를 업데이트하는 스크립트가 Tools/에 제공되며, 릴리스 지침에도 이 업데이트가 포함되도록 수정됩니다.
소스에서 설치할 때 이 데이터베이스의 설치를 활성화하거나 비활성화할 수 있도록 새 configure 옵션 --enable-internal-timezone-database 및 --disable-internal-timezone-database를 구현합니다. 소스 설치에서는 기본적으로 해당 데이터베이스를 설치합니다.
시스템에서 제공하는 zoneinfo 데이터베이스가 있는 시스템의 바이너리 설치 프로그램은 포함된 데이터베이스가 해당 플랫폼에서 절대 사용되지 않으므로 설치를 건너뛸 수 있습니다. 그 밖의 플랫폼, 예를 들어 Windows에서는 바이너리 설치 프로그램이 포함된 데이터베이스를 설치해야 합니다.
datetime 모듈의 변경 사항
새로운 시간대 지원의 공개 API에는 새 클래스 하나, 새 함수 하나, 새 예외 하나, 새 컬렉션 네 개가 포함됩니다. 이와 더불어 datetime 객체의 여러 메서드에 새 is_dst 매개변수가 추가됩니다.
새 클래스 dsttimezone
이 클래스는 DST 지원을 구현하는 tzinfo 베이스 클래스의 구체적인 구현을 제공합니다.
새 함수 zoneinfo(name=None, db_path=None)
이 함수는 유효한 zoneinfo 시간대를 지정하는 문자열이어야 하는 이름 문자열을 받습니다. 예를 들어 “US/Eastern”, “Europe/Warsaw” 또는 “Etc/GMT”입니다. 지정하지 않으면 로컬 시간대를 조회합니다. 유효하지 않은 영역 이름이 지정되거나 로컬 시간대를 검색할 수 없으면 함수는 UnknownTimeZoneError를 발생시킵니다.
이 함수는 사용할 zoneinfo 데이터베이스의 위치를 지정하는 선택적 경로도 받습니다. 지정하지 않으면 함수는 다음 순서로 데이터베이스를 검색합니다.
tzdata-update모듈이 설치되어 있는지 확인한 다음 해당 데이터베이스를 사용합니다.- 존재하는 경우
/usr/share/zoneinfo의 데이터베이스를 사용합니다. - Python에서 제공하는
Lib/tzdata의 데이터베이스를 사용합니다.
데이터베이스를 찾을 수 없는 경우, zoneinfo 데이터베이스를 찾을 수 없지만 tzdata-update 패키지로 설치할 수 있다는 메시지와 함께 UnknownTimeZoneError나 그 서브클래스가 발생합니다.
새로운 매개변수 is_dst
DST 전환 시 발생하는 시간 모호성을 처리하기 위해 여러 메서드에 새로운 is_dst 매개변수가 추가되었습니다.
tzinfo.utcoffset(dt, is_dst=False)tzinfo.dst(dt, is_dst=False)tzinfo.tzname(dt, is_dst=False)datetime.astimezone(tz, is_dst=False)
is_dst 매개변수는 False(기본값), True, 또는 None일 수 있습니다.
False는 주어진 datetime이 일광 절약 시간 중이 아닌, 즉 지정된 시간이 DST 전환 이후로 해석되어야 함을 지정합니다. 이는 기존 동작을 유지하기 위한 기본값입니다.
True는 주어진 datetime이 일광 절약 시간 중, 즉 지정된 시간이 DST 전환 이전으로 해석되어야 함을 지정합니다.
None은 지정된 시간이 DST 전환 중이었던 경우 AmbiguousTimeError 예외를 발생시킵니다. 또한 DST로의 전환 중 “존재하지 않는 시간”에 해당하는 시간이 지정된 경우 NonExistentTimeError를 발생시킵니다.
새로운 예외들
UnknownTimeZoneError이 예외는 KeyError의 서브클래스이며, 찾을 수 없는 시간대 지정이 주어졌을 때 발생합니다.:
>>> datetime.zoneinfo('Europe/New_York') Traceback (most recent call last): ... UnknownTimeZoneError: There is no time zone called 'Europe/New_York'
InvalidTimeError이 예외는
AmbiguousTimeError와NonExistentTimeError의 베이스 역할을 하여, 이 두 가지를 별도로 잡을 수 있게 해줍니다. 이는 ValueError의 서브클래스가 되어, 2011년 2월 29일과 같은 입력값과 함께 이 오류들을 잡을 수 있게 해줍니다.AmbiguousTimeError이 예외는
is_dst를 None으로 설정한 상태에서 모호한 datetime 지정이 주어졌을 때 발생합니다.:>>> datetime(2012, 11, 28, 2, 0, tzinfo=zoneinfo('Europe/Stockholm'), is_dst=None) >>> Traceback (most recent call last): ... AmbiguousTimeError: 2012-10-28 02:00:00 is ambiguous in time zone Europe/Stockholm
NonExistentTimeError이 예외는
is_dst를 None으로 설정한 상태에서 일광 절약 시간으로 인해 존재하지 않는 시간에 대한 datetime 지정이 주어졌을 때 발생합니다.:>>> datetime(2012, 3, 25, 2, 0, tzinfo=zoneinfo('Europe/Stockholm'), is_dst=None) >>> Traceback (most recent call last): ... NonExistentTimeError: 2012-03-25 02:00:00 does not exist in time zone Europe/Stockholm
새로운 컬렉션들
all_timezones은 사용할 수 있는 시간대 이름의 전체 목록으로, 알파벳순으로 나열되어 있습니다.common_timezones는 유용하고 현재 사용 중인 시간대의 목록으로, 알파벳순으로 나열되어 있습니다.
tzdata-update 패키지
zoneinfo 데이터베이스는 easy_install/pip/buildout으로 쉽게 설치할 수 있도록 패키징될 예정입니다. 이 패키지는 어떠한 Python 코드도 설치하지 않으며, 설치에 필요한 것을 제외하고는 어떠한 Python 코드도 포함하지 않습니다.
이는 내부 데이터베이스와 동일한 도구로 계속 업데이트되지만, zoneinfo 데이터베이스가 업데이트될 때마다 릴리스되며 동일한 버전 스키마를 사용합니다.
pytz API와의 차이점
pytz는tzinfo에 is_dst가 없다는 문제를 해결하기 위해localize()와normalize()함수를 가지고 있습니다.is_dst가datetime.tzinfo에 직접 구현되면 더 이상 필요하지 않습니다.timezone()함수는 Python 3.2에 도입된timezone클래스와의 충돌을 피하기 위해zoneinfo()로 불립니다.zoneinfo()는 인자 없이 호출되면 로컬 시간대를 반환합니다.pytz.StaticTzInfo클래스는 정적 시간대에 대한is_dst지원을 제공하기 위해 존재합니다.is_dst지원이datetime.tzinfo에 포함되면 더 이상 필요하지 않습니다.InvalidTimeError는ValueError의 서브클래스입니다.
참고 자료
Copyright
This document has been placed in the public domain.