datetime으로 파이썬에서 UTC 타임 스탬프 가져 오기


82

날짜를 지정하여 UTC 타임 스탬프를 얻는 방법이 있습니까? 내가 기대하는 것 :

datetime(2008, 1, 1, 0, 0, 0, 0)

결과해야

 1199145600

순진한 datetime 객체를 만드는 것은 시간대 정보가 없음을 의미합니다. datetime.utcfromtimestamp에 대한 설명서를 보면 UTC 타임 스탬프를 만드는 것은 표준 시간대 정보를 제외하는 것을 의미합니다. 그래서 순진한 datetime 객체를 만들면 (내가했던 것처럼) UTC 타임 스탬프가 생성 될 것이라고 생각합니다. 하나:

then = datetime(2008, 1, 1, 0, 0, 0, 0)
datetime.utcfromtimestamp(float(then.strftime('%s')))

결과

2007-12-31 23:00:00

datetime 객체에 여전히 숨겨진 시간대 정보가 있습니까? 내가 도대체 ​​뭘 잘못하고있는 겁니까?


문제는 then.strftime('%s')현지 시간을 예상 하지만 타임 스탬프는 datetime(2008, 1, 1)UTC로 표시됩니다.
jfs 2014 년

답변:


90

순진한 datetime대 인식datetime

기본 datetime개체는 "순진한"이라고합니다. 시간대 정보없이 시간 정보를 유지합니다. 순진한 출처가 명확한 출처가없는 datetime상대 숫자 (예 :) 로 생각하십시오 +4(실제로 출처는 시스템 경계 전체에서 공통적입니다).

반대로, 인식 은 전 세계의 공통된 기원을 가진 datetime절대 숫자 (예 :) 로 생각 8하십시오.

시간대 정보가 없으면 "순진한"날짜 시간을 순진하지 않은 시간 표현으로 변환 할 수 없습니다 ( +4어디에서 시작해야할지 모를 경우 대상은 어디에 있습니까?). 이것이 당신이 datetime.datetime.toutctimestamp()방법을 가질 수없는 이유 입니다. (cf : http://bugs.python.org/issue1457227 )

당신이 있는지 확인하려면 datetime dt순진, 체크 인 dt.tzinfo경우, None그때는 순진입니다 :

datetime.now()        ## DANGER: returns naïve datetime pointing on local time
datetime(1970, 1, 1)  ## returns naïve datetime pointing on user given time

순진한 날짜 시간이 있습니다. 어떻게해야합니까?

특정 상황에 따라 가정을해야합니다. 스스로에게 물어봐야 할 질문은 다음과 같습니다 datetime. 아니면 현지 시간 이었습니까?

  • UTC를 사용하는 경우 (문제가 없음) :

    import calendar
    
    def dt2ts(dt):
        """Converts a datetime object to UTC timestamp
    
        naive datetime will be considered UTC.
    
        """
    
        return calendar.timegm(dt.utctimetuple())
    
  • UTC를 사용하지 않았다면 지옥에 오신 것을 환영합니다.

    datetime이전 기능을 사용하기 전에 의도 한 시간대를 되돌려 서 순진하지 않게 만들어야합니다 .

    당신이 필요합니다 시간대의 이름DST가 유효했던 경우에 대한 정보 대상 순진의 날짜를 (DST에 대한 마지막 정보가 cornercases 필요) 생산시를 :

    import pytz     ## pip install pytz
    
    mytz = pytz.timezone('Europe/Amsterdam')             ## Set your timezone
    
    dt = mytz.normalize(mytz.localize(dt, is_dst=True))  ## Set is_dst accordingly
    

    제공하지 않은 결과is_dst :

    사용하지 is_dst않으면 역방향 DST가 적용되는 동안 대상 날짜 시간이 생성 된 경우 (예 : 1 시간을 제거하여 DST 시간 변경) 잘못된 시간 (및 UTC 타임 스탬프)이 생성됩니다.

    is_dst물론 잘못된 것을 제공 하면 DST 겹침이나 구멍에서만 잘못된 시간 (및 UTC 타임 스탬프)이 생성됩니다. 그리고 "구멍"(전진 DST로 인해 존재하지 않았던 시간)에서 발생하는 잘못된 시간도 is_dst제공하면이 가짜 시간을 고려하는 방법에 대한 해석을 제공 할 수 있으며, 이것이 .normalize(..)실제로 여기서 뭔가를 수행 할 유일한 경우입니다. 그런 다음 실제 유효한 시간으로 변환합니다 (필요한 경우 datetime 및 DST 개체 변경). 주 .normalize()당신이 특히 다른 곳에서이 변수를 다시 사용, 마지막에 정확한 UTC 타임 스탬프를 가지고 필요하지 않습니다,하지만 당신은 당신의 변수에 가짜 시간을 갖는 아이디어를 싫어하는 경우 아마 좋습니다.

    다음의 사용을 피 (CF : pytz 날짜 시간을 사용 시간대 변환 )

    dt = dt.replace(tzinfo=timezone('Europe/Amsterdam'))  ## BAD !!
    

    왜? 때문에 .replace()맹목적으로 대체합니다 tzinfo계정에 목표 시간을내어과 나쁜 DST 객체를 선택합니다없이. 반면 .localize()목표 시간과 is_dst힌트를 사용하여 올바른 DST 개체를 선택합니다.

오래된 오답 (이 문제를 제기 한 @JFSebastien에게 감사드립니다) :

바라건대, datetime순진한 datetime 객체 생성과 원하는 순간 사이에 변경하지 않을 시스템 구성과 관련이 있기 때문에 순진한 객체 를 만들 때 시간대 (로컬 원본)를 추측하기가 매우 쉽습니다 . UTC 타임 스탬프. 이 트릭은 불완전한 질문을 하는 데 사용할 수 있습니다 .

사용하여 time.mktime다음을 만들 수 있습니다 utc_mktime.

def utc_mktime(utc_tuple):
    """Returns number of seconds elapsed since epoch

    Note that no timezone are taken into consideration.

    utc tuple must be: (year, month, day, hour, minute, second)

    """

    if len(utc_tuple) == 6:
        utc_tuple += (0, 0, 0)
    return time.mktime(utc_tuple) - time.mktime((1970, 1, 1, 0, 0, 0, 0, 0, 0))

def datetime_to_timestamp(dt):
    """Converts a datetime object to UTC timestamp"""

    return int(utc_mktime(dt.timetuple()))

datetime.NET Framework를 생성 한 시간대와 동일한 시간대에 개체가 생성 되었는지 확인해야 합니다 datetime.

이 마지막 솔루션은 지금부터 UTC 오프셋이 EPOCH의 UTC 오프셋과 동일하다고 가정하기 때문에 올바르지 않습니다. 많은 시간대 (일광 절약 시간 (DST) 오프셋에 대한 연중 특정 순간)에는 해당되지 않습니다.


4
Naive datetime 객체는 항상 UTC로 시간을 나타내야합니다. 다른 시간대는 I / O (디스플레이)에만 사용해야합니다. datetime.timestamp()Python 3.3 에는 메서드 가 있습니다 .
jfs

2
time.mktime()현지 시간으로 만 사용해야합니다. calendar.timegm()utc 타임 튜플을 posix 타임 스탬프로 변환하는 데 사용할 수 있습니다. 또는 datetime 메서드 만 사용하는 것이 좋습니다. 내 대답
jfs

4
-1. 코드는 utc_offset (now) 및 utc_offset (epoch)가 현지 시간대에서 동일하다고 가정합니다. 116 개 시간대 (일반 시간대 430 개)에서는 그렇지 않습니다.
jfs

1
여전히 -1 : .replace().NET과 같이 고정되지 않은 utc 오프셋이있는 시간대와 함께 사용하지 마십시오 'Europe/Amsterdam'. pytz를 사용한 Datetime 시간대 변환을 참조하십시오 .
jfs 2012

1
1- 왜 사용하지 말아야하는지 이해 .replace(tzinfo=get_localzone())합니까? 2- 이미 timegm()반환합니다 int. 로 포장 할 필요가 없습니다 int. 또한 .timetuple()몇 분의 1 초도 떨어집니다.
jfs

29

또 다른 가능성은 다음과 같습니다.

d = datetime.datetime.utcnow()
epoch = datetime.datetime(1970,1,1)
t = (d - epoch).total_seconds()

이것은 "d"와 "epoch"가 모두 순진한 날짜 시간이므로 "-"연산자를 유효하게 만들고 간격을 반환합니다. total_seconds()간격을 초로 바꿉니다. total_seconds()플로트 를 반환합니다.d.microsecond == 0


12
그럼 정말 :) 아이디어는 동일하지만이 사람은 이해하기 쉽다
NATIM

3
당신은 시간 라이브러리에 하나의 방법이 있다고 생각할 것입니다 ...
sheesh

21

또한 블로그 항목에서 설명한대로 calendar.timegm () 함수에 유의하십시오 .

import calendar
calendar.timegm(utc_timetuple)

출력은 vaab의 솔루션과 일치해야합니다.


13

입력 된 datetime 객체가 UTC 인 경우 :

>>> dt = datetime(2008, 1, 1, 0, 0, 0, 0)
>>> timestamp = (dt - datetime(1970, 1, 1)).total_seconds()
1199145600.0

참고 : 이는 float를 반환합니다. 즉, 마이크로 초는 초의 분수로 표시됩니다.

입력 날짜 개체가 UTC 인 경우 :

>>> from datetime import date
>>> utc_date = date(2008, 1, 1)
>>> timestamp = (utc_date.toordinal() - date(1970, 1, 1).toordinal()) * 24*60*60
1199145600

Python에서 datetime.date를 UTC 타임 스탬프변환 에서 자세한 내용을 참조하십시오 .


8

주요 답변이 아직 명확하지 않은 것 같고 시간시간대 를 이해하는 데 시간을 할애 할 가치가 있습니다.

시간을 다룰 때 이해해야 할 가장 중요한 것은 시간이 상대적 이라는 것입니다 !

  • 2017-08-30 13:23:00: (순진한 날짜 시간), 세계 어딘가 의 현지 시간을 나타내지 만 2017-08-30 13:23:00런던은 샌프란시스코 와 같은 시간아닙니다2017-08-30 13:23:00 .

동일한 시간 문자열은 사용자가 어디에 있는지에 따라 다른 시점으로 해석 될 수 있기 때문에 절대적인 시간 개념이 필요합니다 .

UTC 타임 스탬프는 초 (밀리 초)의 개수 로부터 (정의 에포크 1 January 1970 00:00:00에서 GMT: 00 시간대 오프셋 +00).

Epoch는 GMT 시간대에 고정되어 있으므로 절대 시점입니다. UTC 타임 스탬프 가되는 오프셋 절대 시간으로부터 따라서 정의 시간 절대 포인트 .

이를 통해 제 시간에 이벤트를 주문할 수 있습니다.

시간대 정보가 없으면 시간은 상대적이며 순진한 datetime이 고정되어야하는 시간대를 표시하지 않고 는 절대 시간 개념 으로 변환 할 수 없습니다 .

컴퓨터 시스템에서 사용되는 시간 유형은 무엇입니까?

  • naive datetime : 일반적으로 OS가 프로그램에 시간대 정보를 제공 할 수있는 현지 시간 (예 : 브라우저)으로 표시합니다.

  • UTC 타임 스탬프 : UTC 타임 스탬프는 위에서 언급했듯이 절대적인 시점이지만 주어진 시간대에 고정되어 있으므로 UTC 타임 스탬프는 모든 시간대 의 datetime으로 변환 될 수 있지만 시간대 정보 는 포함되어 있지 않습니다 . 그게 무슨 뜻입니까? 이는 1504119325가 2017-08-30T18:55:24Z, 또는 2017-08-30T17:55:24-0100또는에 해당함을 의미합니다 2017-08-30T10:55:24-0800. 기록 된 날짜 / 시간의 출처를 알려주지 않습니다 . 일반적으로 서버 측에서 이벤트 (로그 등)를 기록하거나 시간대 인식 datetime절대 시점 으로 변환하고 시간 차이를 계산하는 사용 됩니다 .

  • ISO-8601 날짜 / 시간 문자열 : ISO-8601은 시간대와 함께 날짜 / 시간을 기록하는 표준화 된 형식입니다. (사실 여러 형식이 있습니다. https://en.wikipedia.org/wiki/ISO_8601 ) 시스템간에 직렬화 가능한 방식으로 시간대 인식 날짜 / 시간 정보를 전달하는 데 사용됩니다.

언제 사용합니까? 아니면 시간대에 대해 언제 신경을 써야합니까?

  • 어떤 식 으로든 시간 을 관리 해야하는 경우 시간대 정보가 필요합니다. 캘린더 또는 알람은 전 세계의 모든 사용자를 위해 정확한 시간에 회의를 설정하기 위해 시간이 필요합니다. 이 데이터가 서버에 저장되면 서버는 datetime이 어떤 시간대에 해당하는지 알아야합니다.

  • 세계의 다른 장소에서 발생하는 이벤트 간의 시간 차이를 계산하려면 UTC 타임 스탬프만으로도 충분하지만 이벤트가 발생한 시간을 분석하는 기능을 잃게됩니다 (예 : 웹 분석의 경우 사용자가 언제 방문하는지 알고 싶을 수 있습니다. 현지 시간으로 사이트 : 오전 또는 저녁에 더 많은 사용자가 표시됩니까? 시간 정보 없이는 알 수 없습니다.

날짜 문자열의 시간대 오프셋 :

중요한 또 다른 점은 날짜 문자열의 시간대 오프셋이 고정되지 않는다는 것 입니다. 즉 2017-08-30T10:55:24-0800, 오프셋 -0800또는 8 시간 전이라고해서 항상 그렇다는 의미는 아닙니다!

여름에는 일광 절약 시간이 될 수 있으며 -0700

즉, 시간대 오프셋 (+0100)시간대 이름 (유럽 / 프랑스) 또는 시간대 지정 (CET) 과 동일하지 않습니다.

America/Los_Angeles시간대는 세계의장소 이지만 PST겨울에는 (태평양 표준시) 시간대 오프셋 표기법 PDT으로, 여름에는 (태평양 일광 절약시 ) 로 바뀝니다 .

따라서 날짜 문자열에서 시간대 오프셋을 얻는 것 외에도 정확한 시간대 이름을 가져와야합니다.

대부분의 패키지는 자체적으로 일광 절약 시간에서 표준 시간으로 숫자 오프셋을 변환 할 수 있지만 오프셋만으로는 반드시 사소한 것은 아닙니다. 예를 들어 WAT서 아프리카의 시간대 지정은 CET프랑스의 시간대 와 마찬가지로 UTC + 0100 이지만 프랑스는 일광 절약 시간을 준수하지만 서 아프리카는 그렇지 않습니다 (적도에 가깝기 때문에).

간단히 말해 복잡합니다. 매우 복잡하기 때문에이 작업을 직접 수행해서는 안되지만이를 수행하는 패키지를 신뢰하고 최신 상태로 유지하십시오!


다른 패키지의 함정을 이해하려면 Python의 날짜와 시간에 대한 내 블로그 게시물을 참조하십시오. medium.com/@eleroy/…
MrE

3

외부 모듈을 사용하지 않는 간단한 솔루션 :

from datetime import datetime, timezone

dt = datetime(2008, 1, 1, 0, 0, 0, 0)
int(dt.replace(tzinfo=timezone.utc).timestamp())


1

Is there a way to get the timestamp by specifying the date in UTC?타임 스탬프는 상대적이지 않고 절대적인 숫자이기 때문에 질문을 표현하는 올바른 방법은라고 생각합니다 . 상대 (또는 시간대 인식) 부분은 날짜입니다.

타임 스탬프에 판다가 매우 편리하다는 것을 알았습니다.

import pandas as pd
dt1 = datetime(2008, 1, 1, 0, 0, 0, 0)
ts1 = pd.Timestamp(dt1, tz='utc').timestamp()
# make sure you get back dt1
datetime.utcfromtimestamp(ts1)  

팬더를 사용하는 것은 IMHO 올바른 접근 방식입니다. 현재 시간에는 t = Timestamp.utcnow ()가있어 올바른 시간을 직접 가져옵니다. :)
ntg

0

받아 들인 대답이 저에게 효과가없는 것 같습니다. 내 솔루션 :

import time
utc_0 = int(time.mktime(datetime(1970, 01, 01).timetuple()))
def datetime2ts(dt):
    """Converts a datetime object to UTC timestamp"""
    return int(time.mktime(dt.utctimetuple())) - utc_0

dt로컬 시간대와 1970 년 의 현재 ( ) UTC 오프셋 이 다른 경우 실패합니다 . mktime()현지 시간을 예상합니다.
jfs

0

가장 간단한 방법 :

>>> from datetime import datetime
>>> dt = datetime(2008, 1, 1, 0, 0, 0, 0)
>>> dt.strftime("%s")
'1199163600'

편집 : @Daniel이 정확합니다. 이것은 기계의 시간대로 변환됩니다. 수정 된 답변은 다음과 같습니다.

>>> from datetime import datetime, timezone
>>> epoch = datetime(1970, 1, 1, 0, 0, 0, 0, timezone.utc)
>>> dt = datetime(2008, 1, 1, 0, 0, 0, 0, timezone.utc)
>>> int((dt-epoch).total_seconds())
'1199145600'

실제로 timezone.utc둘 다 datetime동일한 시간대 (또는 시간대가없는 한)를 갖는 한 시차가 동일하기 때문에을 지정할 필요조차 없습니다.

>>> from datetime import datetime
>>> epoch = datetime(1970, 1, 1, 0, 0, 0, 0)
>>> dt = datetime(2008, 1, 1, 0, 0, 0, 0)
>>> int((dt-epoch).total_seconds())
1199145600

이 메서드는 utc를 반환하지 않고 datetime을 현재 시간대로 조정합니다. 즉. 지금이 tz +3로 오전 12시이면 epoch에서 오전 9시를 반환합니다.
Daniel Dubovski

아 맞다. 내 시간대는 UTC 였기 때문에 작동했습니다.
Mike Furlender 2018 년

(Python 3.2 이상) timezone.utc개체를 사용하려면 다음과 함께 사용 .timestamp()하십시오 datetime(2008, 1, 1, tzinfo=timezone.utc).timestamp(). epoch 객체를 생성하고 뺄 필요가 없습니다.
Martijn Pieters
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.