使用Python计算时间差

8
我想知道是否有一种方法或内置库可以找到两个字符串输入的时间差异。
我的意思是,如果我有两个输入字符串:
1. '2013-10-05T01:21:07Z' 2. '2013-10-05T01:21:16Z'
如何计算时间差并将其打印输出。
我知道这听起来有点愚蠢,但对此任何帮助都将不胜感激。

dateutil。你试过谷歌吗? - J0HN
我做的第一件事!我查看了datetime模块和time模块,但是没有找到有用的东西。相对来说我还是python的新手。 - Prince Sharma
如何在Python中解析ISO格式的日期? - jfs
3个回答

9
使用strptime()解析字符串:
a = time.strptime('2013-10-05T01:21:07Z', '%Y-%m-%dT%H:%M:%SZ')
b = time.strptime('2013-10-05T01:21:16Z', '%Y-%m-%dT%H:%M:%SZ')

这将把给定的时间字符串解析为本地时间(将夏令时设置为自动),结果是时间结构体。这些仍然反映了夏令时是否明确关闭(0)、开启(1)或隐含自动(-1)。将其转换为浮点数(从1970年01月01日开始算起的秒数):

a = time.mktime(a)
b = time.mktime(b)

然后计算差值(以秒为单位):
d = b - a

将它们转换为天/小时/分钟/秒:

days = int(d) / 86400
hours = int(d) / 3600 % 24
minutes = int(d) / 60 % 60
seconds = int(d) % 60

最后一个块只适用于正差值,所以小心不要交换 ab ;-)
但是 @J.F.Sebastian 正确指出这可能不是您想要的。从符号表示来看,似乎您的字符串描述的是 UTC 时间,而不是本地时间。对于仅涉及时间差异的情况,如果您的时间跨越了夏令时切换,则这一点非常重要。在这种情况下,它当然会导致时间差异过大或过小一小时(因为 UTC 总是不考虑夏令时)。
为避免此问题,您可以将 DST 标志从自动(-1)设置为固定值(例如关闭的 0),并使用这些值:
a = time.mktime(a[:-1] + (0,))  # switch DST to off
b = time.mktime(b[:-1] + (0,))

另外,正如@J.F.Sebastian指出的那样,您可以忽略time模块,而是使用不考虑DST方面的datetime.datetime

a = datetime.datetime.strptime('2013-10-05T01:21:07Z', '%Y-%m-%dT%H:%M:%SZ')
b = datetime.datetime.strptime('2013-10-05T01:21:16Z', '%Y-%m-%dT%H:%M:%SZ')

然后返回的结果是datetime对象,可以直接相减得到一个timedelta对象,表示所需的时间差。打印它将会得到类似于0:00:05的结果,这很可能正是你要寻找的。


输入为UTC时间。请使用calendar.timegm()而不是time.mktime()(否则在DST转换期间有50%的错误几率)。或者更好的方法是使用datetime.strptime()而不是time.strptime() - jfs
重点是:由于使用了time.mktime(),您的答案可能会对某些输入返回错误结果,而您可以完全避免这种情况,只需使用calendar.timegm()即可。 - jfs
选择任意两个时间点,当它们被解释为本地时间时具有不同的UTC偏移量,例如,如果您的本地时区是美国/纽约,则基于time.mktime()的代码将返回错误结果,对于输入2015-11-01T00:00:00Z2015-11-01T06:00:00Z - jfs
谢谢您指出这一点。我重写了我的回答的部分。 - Alfe
这是一个很好的答案,因为我在项目中只能使用Python 2.5。 - Davidson Lima
显示剩余3条评论

8
你似乎正在使用 ISO 8601 格式的 日期时间。该格式在许多地方使用,包括 GPS 交换格式。
[-]CCYY-MM-DDThh:mm:ss[Z|(+|-)hh:mm]

使用 datetime:

import datetime
a = datetime.datetime.strptime("2013-10-05T01:21:07Z", "%Y-%m-%dT%H:%M:%SZ")
b = datetime.datetime.strptime("2013-10-05T01:21:16Z", "%Y-%m-%dT%H:%M:%SZ")
c = b - a
print(c)

优点:

  • 内置于Python标准库中
  • 面向对象的接口

缺点:

  • 需要手动处理其他有效的ISO 8601表示形式,例如“2013-10-05T01:21:16+00:00”
  • 对于闰秒(如“2012-06-30T23:59:60Z”),会抛出异常

使用python-dateutil:

import dateutil.parser
a = dateutil.parser.parse("2013-10-05T01:21:07Z")
b = dateutil.parser.parse("2013-10-05T01:21:16Z")
c = b - a
print(c)

优点:

  • 自动处理几乎所有时间格式

缺点:

  • 需要 python-dateutil 库 (pip install python-dateutil)
  • 对于像 '2012-06-30T23:59:60Z' 这样的闰秒会抛出异常

使用 Alfe 建议的 time.strptime 和 time.mktime

优点:

  • Python 标准库内置
  • 可以解析像 '2012-06-30T23:59:60Z' 这样的闰秒

缺点:

  • 需要手动处理其他有效的 ISO 8601 表示形式,例如 '2013-10-05T01:21:16+00:00'
  • '2012-06-30T23:59:60Z' 和 '2012-07-01T00:00:00Z' 之间丢失一个闰秒(无法避免,除非知道下次闰秒何时发生)


-2
import datetime
a = datetime.datetime.now()
b = datetime.datetime.now()
c = b - a
datetime.timedelta(0, 8, 562000)
divmod(c.days * 86400 + c.seconds, 60)

原始答案 这里


1
从字符串中解析日期? - J0HN
这不是楼主所要求的! - ρss
请查看以下链接:https://dev59.com/BWkx5IYBdhLWcg3wAvqn - Senthilnathan
然后,您必须使用相对时间差(timedelta),这将更容易地找到日期时间差异。 - Senthilnathan
@Prince,正在解决Codestorm比赛的第四个问题 :) - Kumar Pallav
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接