UTC 날짜 / 시간 문자열을 현지 날짜 / 시간으로 변환


206

UTC와의 시간을 변환 할 필요가 없었습니다. 최근에 내 앱을 표준 시간대로 인식하라는 요청을 받았으며 서클에서 나 자신을 실행하고 있습니다. 현지 시간을 UTC로 변환하는 데 대한 많은 정보가 있습니다. 이것은 상당히 초등 한 것으로 나타났습니다 (아마도 잘못하고 있습니다) .UTC 시간을 최종 사용자 시간대로 쉽게 변환하는 방법에 대한 정보를 찾을 수 없습니다.

간단히 말해서 안드로이드 앱은 나에게 (appengine 앱) 데이터를 보내며 그 데이터 내에서 타임 스탬프입니다. 해당 타임 스탬프를 utc 시간으로 저장하려면 다음을 사용하십시오.

datetime.utcfromtimestamp(timestamp)

작동하는 것 같습니다. 내 앱이 데이터를 저장하면 5 시간 앞서 저장됩니다 (EST -5입니다)

데이터는 appengine의 BigTable에 저장되고 검색되면 다음과 같은 문자열로 나타납니다.

"2011-01-21 02:37:21"

사용자가 올바른 시간대에서이 문자열을 DateTime으로 어떻게 변환합니까?

또한 사용자 시간대 정보에 권장되는 스토리지는 무엇입니까? (일반적으로 tz 정보 (예 : "-5 : 00"또는 "EST"등)를 저장하는 방법은 무엇입니까?) 첫 번째 질문에 대한 답변에 두 번째 질문에 대한 매개 변수가 포함되어있을 것입니다.



이 답변 은 간단한 방법으로이 문제를 해결하는 방법을 보여줍니다.
— juan

답변:


402

자신의 tzinfo객체 를 제공하지 않으려면 python-dateutil 라이브러리를 확인하십시오 . 다소 정식 이름으로 시간대 규칙을 참조 할 수 tzinfo있도록 zoneinfo (Olson) 데이터베이스 위에 구현을 제공합니다 .

from datetime import datetime
from dateutil import tz

# METHOD 1: Hardcode zones:
from_zone = tz.gettz('UTC')
to_zone = tz.gettz('America/New_York')

# METHOD 2: Auto-detect zones:
from_zone = tz.tzutc()
to_zone = tz.tzlocal()

# utc = datetime.utcnow()
utc = datetime.strptime('2011-01-21 02:37:21', '%Y-%m-%d %H:%M:%S')

# Tell the datetime object that it's in UTC time zone since 
# datetime objects are 'naive' by default
utc = utc.replace(tzinfo=from_zone)

# Convert time zone
central = utc.astimezone(to_zone)

strptime사용법 을 보여주기 위해 확장 된 예제 편집

더 나은 진입 점 방법을 표시하기 위해 2 개의 고정 API 사용량 편집

시간대에 대한 3 가지 자동 감지 방법 편집 (야린)


1
내 이전의 코멘트에, 나는 가져올 수 있었다 dateutil.tz사용 tz.tzutc()및 tz.tzlocal()시간대가 내가 찾던 개체로. 시스템의 표준 시간대 데이터베이스가 양호한 것 같습니다 (체크인 됨 /usr/share/zoneinfo). 무슨 일이 있었는지 잘 모르겠습니다.
— 벤 크리거

1
@ Benjamin 당신은 올바른 길을 가고 있습니다. tz모듈이 라이브러리에 사용되는 정확한 진입 점입니다. 이것을 반영하여 답변을 업데이트했습니다. dateutil.zoneinfo내가 이전에 표시 된 모듈은 내부적으로 사용 tz이 DB은 zoneinfo 시스템의를 찾을 수없는 경우 가을에 다시 같은 모듈. 라이브러리를 살펴보면 패키지에 시스템의 DB를 찾을 수없는 경우 사용하는 zoneinfo DB tarball이 있음을 알 수 있습니다. 예전 예제는 그 DB를 직접 치기 위해 노력했지만 개인 DB를로드하는 데 문제가 있다고 생각합니다 (파이썬 경로에 있지 않습니까?)
— Joe Holloway


1
@JFSebastian 이것은 # 225
— Rohmer

2
@briankip 응용 프로그램이 얼마나 정교해야하는지에 달려 있지만 일반적인 응용 프로그램에서는 문제가 있습니다. 우선 어떤 시간대가 DST를 따르고 다른 시간대를 따르지 않기 때문에 추가 / 빼기 시간은 변경 될 수 있습니다. 둘째, 시간대 규칙은 시간이 지남에 따라 임의로 변경되므로 과거 날짜 / 시간으로 작업하는 경우 현재 시간이 아닌 해당 시점에 유효한 규칙을 적용해야합니다. 그렇기 때문에 뒤에서 Olson TZ 데이터베이스를 활용하는 API를 사용하는 것이 가장 좋습니다.
— Joe Holloway

44

외부 라이브러리에 의존하지 않는 탄력적 인 방법은 다음과 같습니다.

from datetime import datetime
import time

def datetime_from_utc_to_local(utc_datetime):
    now_timestamp = time.time()
    offset = datetime.fromtimestamp(now_timestamp) - datetime.utcfromtimestamp(now_timestamp)
    return utc_datetime + offset

이것은 DelboyJay의 예제에서 타이밍 문제를 피합니다. 그리고 Erik van Oosten의 개정에서 더 적은 타이밍 문제.

흥미로운 각주로서 위에서 계산 된 표준 시간대 오프셋은 일광 절약 규칙 변경으로 인해 다음과 같은 겉보기에 해당되는 표현과 다를 수 있습니다.

offset = datetime.fromtimestamp(0) - datetime.utcfromtimestamp(0) # NO!

업데이트 : 이 스 니펫은 현재 시간의 UTC 오프셋을 사용하는 취약점이 있으며 입력 날짜 시간의 UTC 오프셋과 다를 수 있습니다. 다른 솔루션에 대해서는이 답변에 대한 의견을 참조하십시오.

다른 시간을 돌아 다니려면 지나간 시간부터 신기원 시간을 잡으십시오. 다음은 내가하는 일입니다.

def utc2local (utc):
    epoch = time.mktime(utc.timetuple())
    offset = datetime.fromtimestamp (epoch) - datetime.utcfromtimestamp (epoch)
    return utc + offset

이것은 잘 작동하며 시간과 날짜 시간 외에는 아무것도 필요하지 않습니다.
— Mike_K

6
@ Mike_K : 맞지 않습니다. 다른 이유로 과거에 다른 UTC 오프셋을 가진 DST 또는 시간대를 지원하지 않습니다. pytz-like db가없는 완전한 지원 은 불가능합니다 (PEP-431 참조). Linux, OS X와 ​​같이 이미 역사적인 시간대 DB를 가진 시스템에서 이러한 경우 작동하는 stdlib 전용 솔루션을 작성할 수 있지만 내 대답을 참조하십시오 .
— jfs

@ JFSebastian :이 코드는 일반적으로 작동하지 않지만 OS X 및 Linux에서 작동한다고 말합니다. 이 코드가 Windows에서 작동하지 않습니까?
— David Foster

2
@DavidFoster : Linux 및 OS X에서도 코드가 실패 할 수 있습니다. 귀하와 내 stdlib 전용 솔루션 의 차이점은 귀하의 시간에 utc 오프셋과 다를 수있는 현재 오프셋을 사용한다는 것 utc_datetime입니다.
— jfs

1
잘 했어 그것은 매우 미묘한 차이입니다. UTC 오프셋도 시간이 지남에 따라 변경 될 수 있습니다. 한숨
— David Foster

23

tzinfo 객체 에 대한 날짜 및 시간 설명서를 참조하십시오 . 자신을 지원하려는 시간대를 구현해야합니다. 문서 하단에있는 예입니다.

다음은 간단한 예입니다.

from datetime import datetime,tzinfo,timedelta

class Zone(tzinfo):
    def __init__(self,offset,isdst,name):
        self.offset = offset
        self.isdst = isdst
        self.name = name
    def utcoffset(self, dt):
        return timedelta(hours=self.offset) + self.dst(dt)
    def dst(self, dt):
            return timedelta(hours=1) if self.isdst else timedelta(0)
    def tzname(self,dt):
         return self.name

GMT = Zone(0,False,'GMT')
EST = Zone(-5,False,'EST')

print datetime.utcnow().strftime('%m/%d/%Y %H:%M:%S %Z')
print datetime.now(GMT).strftime('%m/%d/%Y %H:%M:%S %Z')
print datetime.now(EST).strftime('%m/%d/%Y %H:%M:%S %Z')

t = datetime.strptime('2011-01-21 02:37:21','%Y-%m-%d %H:%M:%S')
t = t.replace(tzinfo=GMT)
print t
print t.astimezone(EST)

산출

01/22/2011 21:52:09 
01/22/2011 21:52:09 GMT
01/22/2011 16:52:09 EST
2011-01-21 02:37:21+00:00
2011-01-20 21:37:21-05:00a

받아 줘서 고마워! 특정 예제 시간을 번역하기 위해 약간 업데이트했습니다. 시간을 파싱하면 문서에서 "순진한"시간을 생성합니다. 사용은 replaceGMT로 시간대를 설정하고이 시간대 "인식"다음 사용하도록하는 astimezone다른 시간대로 변환 할 수 있습니다.
— Mark Tolonen

Joe의 답변을 바꾸어 죄송합니다. 기술적으로 당신의 대답은 원시 파이썬 (알아두면 좋은)으로 그것을 수행하는 방법을 정확하게 설명하지만, 그가 제안한 라이브러리는 훨씬 빨리 해결책을 얻습니다.
— MattoTodd

4
일광 절약 시간제를 자동으로 처리하는 것처럼 보이지 않습니다.
— Gringo Suave

@GringoSuave : 의도하지 않았습니다. 이에 대한 규칙은 복잡하고 자주 변경됩니다.
— Mark Tolonen

19

모호한 현지 시간에 해당하는 시간 (예 : DST 전환 중) 및 / 또는 현지 utc 오프셋이 현지 시간대의 시간에 따라 다른 경우에도 정확한 결과를 얻으려면 시간대를 사용하십시오 pytz.

#!/usr/bin/env python
from datetime import datetime
import pytz    # $ pip install pytz
import tzlocal # $ pip install tzlocal

local_timezone = tzlocal.get_localzone() # get pytz tzinfo
utc_time = datetime.strptime("2011-01-21 02:37:21", "%Y-%m-%d %H:%M:%S")
local_time = utc_time.replace(tzinfo=pytz.utc).astimezone(local_timezone)

10

이 답변은 이외의 다른 모듈을 사용하지 않으려는 경우 유용합니다 datetime.

datetime.utcfromtimestamp(timestamp)순진한 datetime객체 (인식 대상 아님)를 반환합니다 . 인식하는 것은 시간대를 인식하고 순진하지 않습니다. 시간대 간 (예 : UTC와 현지 시간 간) 변환하려는 경우 알고 있어야합니다.

시작 날짜를 인스턴스화하는 사람이 아니지만 datetimeUTC 시간 으로 순진한 객체를 만들 수있는 경우이 Python 3.x 코드를 사용하여 변환하려고 할 수 있습니다.

import datetime

d=datetime.datetime.strptime("2011-01-21 02:37:21", "%Y-%m-%d %H:%M:%S") #Get your naive datetime object
d=d.replace(tzinfo=datetime.timezone.utc) #Convert it to an aware datetime object in UTC time.
d=d.astimezone() #Convert it to your local timezone (still aware)
print(d.strftime("%d %b %Y (%I:%M:%S:%f %p) %Z")) #Print it with a directive of choice

표준 시간대가 현재 MDT 인 경우 일광 절약 시간이 MST를 인쇄하므로 위의 코드에서 작동하지 않는다고 잘못 생각하지 않도록주의하십시오. 월을 8 월로 변경하면 MDT가 인쇄됩니다.

datetime파이썬 3.x에서도 인식 객체 를 얻는 또 다른 쉬운 방법 은 시작하도록 지정된 시간대로 객체를 만드는 것입니다. UTC를 사용한 예는 다음과 같습니다.

import datetime, sys

aware_utc_dt_obj=datetime.datetime.now(datetime.timezone.utc) #create an aware datetime object
dt_obj_local=aware_utc_dt_obj.astimezone() #convert it to local time

#The following section is just code for a directive I made that I liked.
if sys.platform=="win32":
    directive="%#d %b %Y (%#I:%M:%S:%f %p) %Z"
else:
    directive="%-d %b %Y (%-I:%M:%S:%f %p) %Z"

print(dt_obj_local.strftime(directive))

Python 2.x를 사용하는 경우 Python 2.x 에는 존재하지 않으므로 datetime.tzinfo인식 datetime객체 를 작성하는 데 도움 이되도록 서브 클래스 를 작성하고 사용해야합니다 datetime.timezone.


8

Django를 사용하는 경우 다음 timezone.localtime방법을 사용할 수 있습니다 .

from django.utils import timezone
date 
# datetime.datetime(2014, 8, 1, 20, 15, 0, 513000, tzinfo=<UTC>)

timezone.localtime(date)
# datetime.datetime(2014, 8, 1, 16, 15, 0, 513000, tzinfo=<DstTzInfo 'America/New_York' EDT-1 day, 20:00:00 DST>)

2

화살표 를 사용할 수 있습니다

from datetime import datetime
import arrow

now = datetime.utcnow()

print(arrow.get(now).to('local').format())
# '2018-04-04 15:59:24+02:00'

arrow.get()무엇이든 먹일 수 있습니다 . 타임 스탬프, iso 문자열 등


1

나는 전통적으로 이것을 프론트 엔드로 연기합니다. 백 엔드에서 시간을 타임 스탬프 또는 UTC로 다른 날짜 시간 형식으로 보낸 다음 클라이언트가 시간대 오프셋을 파악 하고이 데이터를 적절한 시간대로 렌더링하도록하십시오.

웹 응용 프로그램의 경우 이것은 자바 스크립트에서 수행하기가 매우 쉽습니다. 내장 메소드를 사용하여 브라우저의 시간대 오프셋을 쉽게 쉽게 파악한 다음 백엔드의 데이터를 올바르게 렌더링 할 수 있습니다.


3
이것은 단순히 디스플레이를 위해 현지화하는 많은 경우에 효과적입니다. 그러나 때때로 사용자 시간대를 기반으로 일부 비즈니스 로직을 수행해야하며 애플리케이션 서버 티어를 변환 할 수 있어야합니다.
— Joe Holloway

1

calendar.timegm유닉스 시대 이후의 시간을 초로 time.localtime변환하고 다시 변환 하는 데 사용할 수 있습니다 .

import calendar
import time

time_tuple = time.strptime("2011-01-21 02:37:21", "%Y-%m-%d %H:%M:%S")
t = calendar.timegm(time_tuple)

print time.ctime(t)

제공합니다 Fri Jan 21 05:37:21 2011(UTC + 03:00 시간대이므로).


1
import datetime

def utc_str_to_local_str(utc_str: str, utc_format: str, local_format: str):
    """
    :param utc_str: UTC time string
    :param utc_format: format of UTC time string
    :param local_format: format of local time string
    :return: local time string
    """
    temp1 = datetime.datetime.strptime(utc_str, utc_format)
    temp2 = temp1.replace(tzinfo=datetime.timezone.utc)
    local_time = temp2.astimezone()
    return local_time.strftime(local_format)

utc = '2018-10-17T00:00:00.111Z'
utc_fmt = '%Y-%m-%dT%H:%M:%S.%fZ'
local_fmt = '%Y-%m-%dT%H:%M:%S+08:00'
local_string = utc_str_to_local_str(utc, utc_fmt, local_fmt)
print(local_string)   # 2018-10-17T08:00:00+08:00

예를 들어, 시간대는 ' +08 : 00 '입니다. 입력 utc = 2018-10-17T00 : 00 : 00.111Z 이면 출력을 얻습니다 = 2018-10-17T08 : 00 : 00 + 08 : 00


1
당신은 당신이 달성하고자하는 것과 다른 문제를 설명하는 나머지 텍스트를 일반 텍스트로 더 잘 설명해야합니다
— m33n

1

여기에 대한 답변 에서 시간 모듈을 사용하여 utc에서 컴퓨터에 설정된 현지 시간으로 변환 할 수 있습니다.

utc_time = time.strptime("2018-12-13T10:32:00.000", "%Y-%m-%dT%H:%M:%S.%f")
utc_seconds = calendar.timegm(utc_time)
local_time = time.localtime(utc_seconds)

0

로컬 시스템 설정을 사용하여 시차를 해결하는 빠르고 더러운 버전입니다. 참고 : 현재 시스템이 실행되고 있지 않은 시간대로 변환해야하는 경우에는 작동하지 않습니다. BST 시간대에서 영국 설정으로 테스트했습니다.

from datetime import datetime
def ConvertP4DateTimeToLocal(timestampValue):
   assert isinstance(timestampValue, int)

   # get the UTC time from the timestamp integer value.
   d = datetime.utcfromtimestamp( timestampValue )

   # calculate time difference from utcnow and the local system time reported by OS
   offset = datetime.now() - datetime.utcnow()

   # Add offset to UTC time and return it
   return d + offset

그것이 있어야 datetime.fromtimestamp(ts): POSIX 타임 스탬프 (플로트 초) -> 현지 시간 날짜 객체 (OS 과거에 날짜를 윈도우에서 유닉스, 지역 시간대, 즉 과거의 UTC 오프셋을 기억하지만 경우 잘 작동)). 그렇지 않으면 pytz를 사용할 수 있습니다.
— jfs

다음을 수행 할 것을 제안 할 수 offset = datetime.utcnow().replace(minute=0, second=0, microsecond=0) - datetime.now().replace(minute=0, second=0, microsecond=0) 있습니다.없이 마이크로 초 차이가 있습니다.
— Erik van Oosten

@ErikvanOosten : datetime.fromtimestamp(ts)답변 대신 시도해 보셨습니까 ?
— jfs

0

솔직한 답변을 편리한 방법으로 통합합니다 .

import calendar
import datetime

def to_local_datetime(utc_dt):
    """
    convert from utc datetime to a locally aware datetime according to the host timezone

    :param utc_dt: utc datetime
    :return: local timezone datetime
    """
    return datetime.datetime.fromtimestamp(calendar.timegm(utc_dt.timetuple()))
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.