Python:用微秒将字符串转换为时间戳

Python:用微秒将字符串转换为时间戳,python,datetime,timestamp,converter,Python,Datetime,Timestamp,Converter,我想将字符串日期格式转换为微秒时间戳 我尝试了以下方法,但没有给出预期结果: """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(myDa

我想将字符串日期格式转换为微秒时间戳 我尝试了以下方法,但没有给出预期结果:

"""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

毫秒到哪里去了?

时间元组中的微秒组件没有插槽:

>>> 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
您可以遵循的另一种方法是生成一个相对于历元的时间戳,然后使用以下命令获取时间戳:

使用本地时间纪元是经过深思熟虑的,因为您有一个简单的(不知道时区的)日期时间值。但是,根据本地时区的历史记录,此方法可能不准确,请参阅。您必须先使用本地时区将原始datetime值转换为时区感知的datetime值,然后再减去时区感知的历元

因此,更容易坚持使用
timetuple()
+微秒的方法

演示:

毫秒到哪里去了

这是最简单的部分
.timetuple()
调用会删除它们。您可以使用
.microsecond
属性将它们添加回。对于朴素的datetime对象,该函数就是这样工作的:

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,然后再转换

有两个主要问题:

  • 本地时间可能不存在或不明确,例如,在DST转换期间,同一时间可能出现两次
  • 本地时区的UTC偏移量在过去可能不同,因此是一个简单的:
可以使用tz数据库(
pytz
Python中的模块)解决这两个问题:

结果是
timestamp
——一个
timedelta
对象,您可以将其转换为秒、毫秒等

此外,在闰秒前后/闰秒期间,不同的系统可能表现不同。大多数应用程序可以忽略它们的存在


一般来说,除了本地时间之外,存储POSIX时间戳可能更简单,而不是试图从本地时间猜测它。

在Python 3.4及更高版本中,您可以使用

timestamp = datetime.datetime.strptime(myDate, "%Y-%m-%d %H:%M:%S,%f").timestamp()
这不需要导入
时间
模块。它还使用较少的步骤,因此应该更快。对于较早版本的python,提供的其他答案可能是您的最佳选择


但是,生成的时间戳将以本地时间而不是UTC来解释myDate,如果myDate以UTC给出,则可能会导致问题。如果输入日期(2014-08-01)与时间戳(2014-09-15 02:30:01.117Z)不对应,则输入日期(2014-09-15 02:30:01.117Z)1
(dt-epoch)
不正确,如果
dt
是原始本地时间。当地时间可能会推迟(北半球秋季的DST转换)。在这种情况下不应设置时间戳。2“当地时间纪元”也可能会产生误导。epoch是一个单一的时间实例(对于Python来说是1970年)——世界各地都是一样的。如果C库支持历史时区数据库或本地时区的UTC在该时间具有相同的值,则
datetime.fromtimstamp(0)
返回与历元对应的本地时间。@J.F.Sebastian:
epoch
值使用
fromtimstamp()
,而不是
utcfromtimestamp()
,要处理DST差异,正是因为
dt
值太天真了。@J.F.Sebastian:如果我使用
utcfromtimestamp()
,我必须首先使
dt
时区感知,从而允许Python补偿DST问题。你误解了。问题是公式使用的是当地时间。当地时间可能模棱两可(如果它是输入,并且没有其他可用信息,您将无能为力)。而且本地时区的utc偏移量在过去可能不同(您需要tz数据库来找到它)。正确的公式:
ts=utc\u time-epoch\u in\u utc=local time-utc offset(现在)-local time中的epoch+utc offset(那时)
。您的公式相当于使用UTC偏移量,即假定
UTC偏移量(现在)=UTC偏移量(当时)
@J.F.Sebastian:啊,这一点很好。如果有一个合适的时区数据库,这个公式会更简单。作为一种近似,忽略历史问题,它足够好吗?因为
time.time()
也不使用历史值。注意:
datetime.timestamp
仅在Python 3中可用;OP使用的是Python 2(从
print
语句判断)。@MartijnPieters:我没有建议使用
.timestamp()
方法。我只是用它作为一个例子(有缺陷的)实现。我不是有意建议你这么做。我只是指出Python2中不存在该方法。@MartijnPieters:我理解你所说的。我不明白你为什么这么说。在这种情况下,代码恰好包含在Python3 stdlib
+d中并不重要。微秒/1e6
在Python2和Python3上的工作方式相同。
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()
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 = datetime.datetime.strptime(myDate, "%Y-%m-%d %H:%M:%S,%f").timestamp()