Есть ли способ получить метку времени в формате 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.Ответы:
Наивный
datetime
против осведомленногоdatetime
datetime
Объекты по умолчанию называются «наивными»: они хранят информацию о времени без информации о часовом поясе. Думайте о наивностиdatetime
как об относительном числе (например:)+4
без четкого происхождения (на самом деле ваше происхождение будет общим для всей границы вашей системы).Напротив, думайте о знании
datetime
как об абсолютных числах (например:)8
с общим происхождением для всего мира.Без информации о часовом поясе вы не можете преобразовать "наивное" datetime в какое-либо ненативное представление времени (где же
+4
цели, если мы не знаем, с чего начать?). Вот почему у вас не может бытьdatetime.datetime.toutctimestamp()
метода. (см. 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? или это было местное время?Если вы использовали 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
Перед тем, как использовать предыдущую функцию, вы должны сделать свое дело не наивным, вернув им предполагаемый часовой пояс.Вам понадобится название часового пояса и информация о том, действовало ли летнее время при создании целевого наивного datetime (последняя информация о летнем времени требуется для угловых случаев):
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
будет сгенерировано неправильное время (и временная метка UTC), если целевая дата-время была создана, когда было установлено обратное летнее время (например, изменение времени летнего времени путем удаления одного часа).Предоставление неверного
is_dst
значения, конечно же, будет генерировать неправильное время (и временную метку UTC) только при перекрытии летнего времени или дырах. И, когда также указывается неправильное время, возникающее в «дырах» (время, которое никогда не существовало из-за перехода на летнее время вперед),is_dst
даст интерпретацию того, как рассматривать это фиктивное время, и это единственный случай, когда здесь.normalize(..)
действительно что-то будет делать, так как затем он переведет его как действительное время (при необходимости изменив дату и время И объект DST). Обратите внимание, что.normalize()
это не требуется для наличия правильной отметки времени в формате UTC в конце, но, вероятно, рекомендуется, если вам не нравится идея фиктивного времени в ваших переменных, особенно если вы повторно используете эту переменную в другом месте.и ИЗБЕГАЙТЕ СЛЕДУЮЩЕГО : (см. Преобразование часового пояса Datetime с использованием pytz )
dt = dt.replace(tzinfo=timezone('Europe/Amsterdam')) ## BAD !!
Почему? потому что
.replace()
заменяет вслепуюtzinfo
без учета целевого времени и выберет плохой объект DST. В то время как.localize()
использует целевое время и вашуis_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
объект создан в том же часовом поясе, что и тот, который создал вашdatetime
.Это последнее решение неверно, поскольку в нем предполагается, что смещение UTC от настоящего момента совпадает с смещением UTC от EPOCH. Что не так для многих часовых поясов (в конкретный момент года для смещений летнего времени (DST)).
источник
datetime.timestamp()
Python 3.3 есть метод.time.mktime()
следует использовать только для местного времени.calendar.timegm()
может использоваться для преобразования кортежа времени utc в метку времени posix. Или еще лучше использовать только методы datetime. Смотрите мой ответ.replace()
с часовым поясом с нефиксированным смещением utc, например'Europe/Amsterdam'
. См. Раздел «Преобразование часового пояса в дату и время с помощью pytz» ..replace(tzinfo=get_localzone())
? 2- ужеtimegm()
возвращаетсяint
. Не нужно оборачиватьint
. Также.timetuple()
падает за доли секунды.Другая возможность:
d = datetime.datetime.utcnow() epoch = datetime.datetime(1970,1,1) t = (d - epoch).total_seconds()
Это работает, поскольку и «d», и «epoch» являются наивными датами, делая оператор «-» действительным и возвращая интервал.
total_seconds()
превращает интервал в секунды. Обратите внимание, чтоtotal_seconds()
возвращает число с плавающей запятой, дажеd.microsecond == 0
источник
Также обратите внимание на функцию calendar.timegm (), описанную в этой записи блога:
import calendar calendar.timegm(utc_timetuple)
Вывод должен соответствовать решению vaab.
источник
Если входной объект datetime находится в UTC:
>>> dt = datetime(2008, 1, 1, 0, 0, 0, 0) >>> timestamp = (dt - datetime(1970, 1, 1)).total_seconds() 1199145600.0
Примечание: он возвращает число с плавающей запятой, т.е. микросекунды представлены как доли секунды.
Если объект даты ввода находится в формате UTC:
>>> from datetime import date >>> utc_date = date(2008, 1, 1) >>> timestamp = (utc_date.toordinal() - date(1970, 1, 1).toordinal()) * 24*60*60 1199145600
Дополнительные сведения см. В разделе « Преобразование datetime.date в метку времени в формате UTC в Python» .
источник
Я чувствую, что основной ответ все еще не так ясен, и стоит потратить время, чтобы понять время и часовые пояса .
Самое важное, что нужно понимать, имея дело со временем, - это то, что время относительно !
2017-08-30 13:23:00
: (наивное datetime), представляет местное время где-то в мире, но учтите, что2017-08-30 13:23:00
в Лондоне НЕ ТО ЖЕ ВРЕМЯ, как2017-08-30 13:23:00
в Сан-Франциско.Поскольку одну и ту же строку времени можно интерпретировать как разные моменты времени в зависимости от того, где вы находитесь в мире, существует необходимость в абсолютном понятии времени.
UTC метка времени представляет собой число в секундах (или миллисекундах) от эпохи (определяется как
1 January 1970 00:00:00
приGMT
временной зоны +00: 00 смещение).Эпоха привязана к часовому поясу GMT и, следовательно, является абсолютной точкой времени. UTC метка времени будучи смещение от абсолютного времени , следовательно , определяет абсолютную точку во времени .
Это дает возможность упорядочивать события по времени.
Без информации о часовом поясе время является относительным и не может быть преобразовано в абсолютное понятие времени без указания некоторого указания на то, к какому часовому поясу следует привязать наивное datetime.
Какие типы времени используются в компьютерной системе?
наивное datetime : обычно для отображения в местном времени (то есть в браузере), где ОС может предоставить программе информацию о часовом поясе.
Метки времени в формате UTC : метка времени в формате UTC - это абсолютная точка времени, как упоминалось выше, но она привязана к заданному часовому поясу, поэтому метка времени в формате UTC может быть преобразована в дату и время в любом часовом поясе, однако она не содержит информации о часовом поясе. Что это значит? Это означает, что 1504119325 соответствует
2017-08-30T18:55:24Z
или2017-08-30T17:55:24-0100
также2017-08-30T10:55:24-0800
. Он не сообщает вам, откуда записана дата и время. Обычно он используется на стороне сервера для записи событий (журналов и т. Д.) Или используется для преобразования даты и времени с учетом часового пояса в абсолютный момент времени и вычисления разницы во времени .Строка даты и времени 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
timezone - это место в мире , но оно превращается вPST
(Тихоокеанское стандартное время) смещение часового пояса зимой и вPDT
(Тихоокеанское летнее время) летом.Таким образом, помимо получения смещения часового пояса из строки даты, вы также должны получить точное имя часового пояса.
Большинство пакетов смогут самостоятельно конвертировать числовые смещения из летнего времени в стандартное, но это не обязательно тривиально с простым смещением. Например,
WAT
обозначение часового пояса в Западной Африке - UTC + 0100, как иCET
часовой пояс во Франции, но во Франции используется летнее время, а в Западной Африке - нет (потому что они близки к экватору).Короче говоря, это сложно. ОЧЕНЬ сложно, и поэтому вам не следует делать это самостоятельно, а доверять пакету, который сделает это за вас, и ПОДДЕРЖИВАЙТЕ ЭТО ВОВРЕМЕННО!
источник
Простое решение без использования внешних модулей:
from datetime import datetime, timezone dt = datetime(2008, 1, 1, 0, 0, 0, 0) int(dt.replace(tzinfo=timezone.utc).timestamp())
источник
Действительно существует проблема с использованием utcfromtimestamp и указанием часовых поясов. Хороший пример / объяснение доступен по следующему вопросу:
Как указать часовой пояс (UTC) при преобразовании во время Unix? (Python)
источник
Я думаю, что правильный способ сформулировать ваш вопрос
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)
источник
Принятый ответ, похоже, не работает для меня. Мое решение:
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
смещение текущего ( ) UTC местного часового пояса и 1970 отличается.mktime()
ожидает местное время.Самый простой способ:
>>> 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
источник
timezone.utc
объект, а затем просто использовать это с.timestamp()
:datetime(2008, 1, 1, tzinfo=timezone.utc).timestamp()
. Не нужно создавать объект эпохи и вычитать ..