2014-10-02 3 views
9

Я хотел бы преобразовать формат даты строки в отметку времени с микросекунд я стараюсь следующее, но не дает ожидаемого результата:Python: Преобразование строки в отметку времени с микросекунд

"""input string date -> 2014-08-01 04:41:52,117 
expected result -> 1410748201.117""" 

import time 
import datetime 

myDate = "2014-08-01 04:41:52,117" 
timestamp = time.mktime(datetime.datetime.strptime(myDate, "%Y-%m-%d %H:%M:%S,%f").timetuple()) 

print timestamp 
> 1410748201.0 

Где миллисекунды идти?

+0

дата ввода (2014-08-01) не соответствует отметке времени (2014-09-15 02: 30: 01.117Z) – jfs

ответ

12

Там нет слота для компонента микросекунд в кортеж времени:

>>> import time 
>>> import datetime 
>>> myDate = "2014-08-01 04:41:52,117" 
>>> datetime.datetime.strptime(myDate, "%Y-%m-%d %H:%M:%S,%f").timetuple() 
time.struct_time(tm_year=2014, tm_mon=8, tm_mday=1, tm_hour=4, tm_min=41, tm_sec=52, tm_wday=4, tm_yday=213, tm_isdst=-1) 

Вы должны добавить их вручную:

>>> dt = datetime.datetime.strptime(myDate, "%Y-%m-%d %H:%M:%S,%f") 
>>> time.mktime(dt.timetuple()) + (dt.microsecond/1000000.0) 
1406864512.117 

Другой метод, который вы могли бы следовать, чтобы произвести timedelta() object по отношению к эпохе, а затем получить временную метку с timedelta.total_seconds() method:

epoch = datetime.datetime.fromtimestamp(0) 
(dt - epoch).total_seconds() 

Использование времени местного времени является довольно преднамеренным, поскольку у вас есть наивное (а не время) значение даты и времени. Этот метод может быть неточным, основываясь на истории вашего местного часового пояса, однако, см. J.F. Sebastian's comment. Вам нужно будет преобразовать наивное значение datetime в значение даты и времени, зависящее от часового пояса, сначала используя свой часовой пояс, прежде чем вычесть эпоху, ориентированную на часовой пояс.

Таким образом, легче придерживаться подхода timetuple() + микросекунд.

Демо:

>>> dt = datetime.datetime.strptime(myDate, "%Y-%m-%d %H:%M:%S,%f") 
>>> epoch = datetime.datetime.fromtimestamp(0) 
>>> (dt - epoch).total_seconds() 
1406864512.117 
+0

** 1 ** '(dt - epoch)' неверно, если ' dt' - наивное местное время. Местное время может быть отменено (переход DST осенью в северном полушарии). В этом случае отметка времени должна быть ** не **. ** 2 ** Также «местная временная эпоха» может вводить в заблуждение. Эпоха - это * одноразовый экземпляр (1970 для Python) - это то же самое во всем мире. Если библиотека C поддерживает базу данных хронологического времени или UTC для локального часового пояса имеет то же значение в то время, то 'datetime.fromtimestamp (0)' возвращает местное время, соответствующее эпохе. – jfs

+0

@ J.F.Sebastian: значение 'epoch' использует' fromtimestamp() ', а не' utcfromtimestamp() ', для обработки разности DST именно потому, что значение' dt' наивно. –

+0

@ J.F.Sebastian: Если бы я использовал 'utcfromtimestamp()' вместо этого, я должен был бы сначала сообщить 'dt' часовую зону и, таким образом, позволить Python компенсировать проблемы DST. –

2

Где миллисекунды идти?

Это легкая деталь. .timetuple() вызов опускает их. Вы можете добавить их обратно, используя атрибут .microsecond. datetime.timestamp() method from the standard library работает таким образом для наивных объектов даты и времени:

def timestamp(self): 
    "Return POSIX timestamp as float" 
    if self._tzinfo is None: 
     return _time.mktime((self.year, self.month, self.day, 
          self.hour, self.minute, self.second, 
          -1, -1, -1)) + self.microsecond/1e6 
    else: 
     return (self - _EPOCH).total_seconds() 

Достаточно, если возможно, ~ 1 час ошибки могут быть проигнорированы в вашем случае. Я предполагаю, что вам нужны микросекунды, и поэтому вы не можете игнорировать ошибки в 1 час времени молча.

Чтобы преобразовать локальное время, заданное в качестве строки в метку времени POSIX, является сложной задачей в целом. Вы можете конвертировать местное время в UTC, а затем get the timestamp from UTC time.

Есть два основных вопроса:

  • местного времени может быть несуществующим или неоднозначным, например,во время летнего времени переходов может происходить в то же время дважды
  • UTC смещения для местного часового пояса может быть различным в прошлом, и поэтому наивный: local time minus epoch in local time formula may fail

Оба могут быть решены с использованием базы данных TZ (pytz модуля в Python) :

from datetime import datetime 
import pytz # $ pip install pytz 
from tzlocal import get_localzone # $ pip install tzlocal 

tz = get_localzone() # get pytz timezone corresponding to the local timezone 

naive_d = datetime.strptime(myDate, "%Y-%m-%d %H:%M:%S,%f") 
# a) raise exception for non-existent or ambiguous times 
d = tz.localize(naive_d, is_dst=None) 
## b) assume standard time, adjust non-existent times 
#d = tz.normalize(tz.localize(naive_d, is_dst=False)) 
## c) assume DST is in effect, adjust non-existent times 
#d = tz.normalize(tz.localize(naive_d, is_dst=True)) 
timestamp = d - datetime(1970, 1, 1, tzinfo=pytz.utc) 

результат timestamp - это timedelta объект, вы можете преобразовать его в секунды, миллисекунды и т.д.

также различного SYS Темпы могут вести себя по-разному вокруг/в течение секунд прыжка. Большинство приложений могут игнорировать то, что они существуют.

В общем, может быть проще хранить временные метки POSIX , а не, а не пытаться угадать его по местному времени.

+0

Примечание: 'datetime.timestamp' доступен только в Python 3; OP использует Python 2 (судя по операторам 'print'). –

+0

@MartijnPieters: Я * * не предложил использовать метод '.timestamp()'. Я просто использую его в качестве примера (ошибочной) реализации. – jfs

+0

Я не хотел вас предлагать. Я только указываю, что метод не существует в Python 2. –

1

В Python 3.4, а затем вы можете использовать

timestamp = datetime.datetime.strptime(myDate, "%Y-%m-%d %H:%M:%S,%f").timestamp() 

Это не требует импорта time модуля. Он также использует меньше шагов, поэтому он должен быть быстрее. Для более старых версий python другие предоставленные ответы, вероятно, являются вашим лучшим вариантом.