我有一堆datetime对象,我想为每个对象计算从过去的固定时间(例如从1970年1月1日以来)开始的秒数。

import datetime
t = datetime.datetime(2009, 10, 21, 0, 0)

这似乎只是区分有不同日期的日期:

t.toordinal()

如何将datetime对象转换为秒?


当前回答

比较4种最常见的方法,以确保准确性:

方法一:手动计算

from datetime import datetime
total1 = int(datetimeobj.strftime('%S'))
total1 += int(datetimeobj.strftime('%M')) * 60
total1 += int(datetimeobj.strftime('%H')) * 60 * 60
total1 += (int(datetimeobj.strftime('%j')) - 1) * 60 * 60 * 24
total1 += (int(datetimeobj.strftime('%Y')) - 1970) * 60 * 60 * 24 * 365
print ("Method #1: Manual")
print ("Before: %s" % datetimeobj)
print ("Seconds: %s " % total1)
print ("After: %s" % datetime.fromtimestamp(total1))

输出:

Method #1: Manual
Before: 1970-10-01 12:00:00 
Seconds: 23630400 
After: 1970-10-01 16:00:00

精度测试:FAIL(时区偏移)

方法二:时间模块

import time
from datetime import datetime
total2 = int(time.mktime(datetimeobj.timetuple()))
print ("Method #2: Time Module")
print ("Before: %s" % datetimeobj)
print ("Seconds: %s " % total2)
print ("After: %s" % datetime.fromtimestamp(total2))

输出:

Method #2: Time Module
Before: 1970-10-01 12:00:00 
Seconds: 23616000 
After: 1970-10-01 12:00:00

准确度测试:通过

方法三:日历模块

import calendar
from datetime import datetime
total3 = calendar.timegm(datetimeobj.timetuple())
print ("Method #3: Calendar Module")
print ("Before: %s" % datetimeobj)
print ("Seconds: %s " % total3)
print ("After: %s" % datetime.fromtimestamp(total3))

输出:

Method #3: Calendar Module
Before: 1970-10-01 12:00:00
Seconds: 23616000
After: 1970-10-01 16:00:00

精度测试:FAIL(时区偏移)

方法四:Datetime时间戳

from datetime import datetime
total4 = datetimeobj.timestamp()
print ("Method #4: datetime timestamp")
print ("Before: %s" % datetimeobj)
print ("Seconds: %s " % total4)
print ("After: %s" % datetime.fromtimestamp(total4))

输出:

Method #2: Time Module
Before: 1970-10-01 12:00:00 
Seconds: 23616000 
After: 1970-10-01 12:00:00

准确度测试:通过

结论

所有4个方法都将datetime转换为epoch(总秒数) Manual方法和Calendar模块方法都是时区感知的。 datetime.timestamp()和time.mktime()方法都不涉及时区。 最简单的方法:datetime.timestamp()

其他回答

对于1970年1月1日这个特殊的日子,有多种选择。

对于任何其他开始日期,您需要以秒为单位获得两个日期之间的差异。减去两个日期会得到一个timedelta对象,从Python 2.7开始,它有一个total_seconds()函数。

>>> (t-datetime.datetime(1970,1,1)).total_seconds()
1256083200.0

开始日期通常以UTC为单位指定,因此为了得到正确的结果,您输入到这个公式中的日期时间也应该以UTC为单位。如果datetime还不是UTC,那么在使用它之前需要转换它,或者附加一个具有适当偏移量的tzinfo类。

正如评论中提到的,如果你在datetime上附加了一个tzinfo,那么你也需要在起始日期上添加一个tzinfo,否则减法将失败;对于上面的例子,我将添加tzinfo=pytz。如果使用python2,则使用tzinfo=timezone。如果使用Python 3。

将表示UTC时间的datetime对象转换为POSIX时间戳:

from datetime import timezone

seconds_since_epoch = utc_time.replace(tzinfo=timezone.utc).timestamp()

将表示本地时区时间的datetime对象转换为POSIX时间戳:

import tzlocal # $ pip install tzlocal

local_timezone = tzlocal.get_localzone()
seconds_since_epoch = local_timezone.localize(local_time, is_dst=None).timestamp()

参见如何在Python中将本地时间转换为UTC ?如果tz数据库在给定平台上可用;只使用stdlib的解决方案可能有效。

如果需要<3.3 Python版本的解决方案,请参考链接。

从Python 3.3开始,使用datetime.timestamp()方法,这变得超级简单。当然,这只在您需要1970-01-01 UTC的秒数时才有用。

from datetime import datetime
dt = datetime.today()  # Get timezone naive now
seconds = dt.timestamp()

返回值将是一个浮点数,表示秒的几分之一。如果datetime是无时区的(如上例所示),则假定datetime对象表示本地时间,即从您所在位置的当前时间到UTC 1970-01-01的秒数。

import datetime
import math


def getSeconds(inputDate):
    time = datetime.date.today().strftime('%m/%d/%Y')
    date_time = datetime.datetime.strptime(time, '%m/%d/%Y')
    msg = inputDate
    props = msg.split(".")
    a_timedelta = datetime.timedelta
    if(len(props)==3):
        a_timedelta = date_time - datetime.datetime(int(props[0]),int(props[1]),int(props[2]))
    else:
        print("Invalid date format")
        return
    seconds = math.trunc(a_timedelta.total_seconds())
    print(seconds)
    return seconds

例子getSeconds(“2022.1.1”)

比较4种最常见的方法,以确保准确性:

方法一:手动计算

from datetime import datetime
total1 = int(datetimeobj.strftime('%S'))
total1 += int(datetimeobj.strftime('%M')) * 60
total1 += int(datetimeobj.strftime('%H')) * 60 * 60
total1 += (int(datetimeobj.strftime('%j')) - 1) * 60 * 60 * 24
total1 += (int(datetimeobj.strftime('%Y')) - 1970) * 60 * 60 * 24 * 365
print ("Method #1: Manual")
print ("Before: %s" % datetimeobj)
print ("Seconds: %s " % total1)
print ("After: %s" % datetime.fromtimestamp(total1))

输出:

Method #1: Manual
Before: 1970-10-01 12:00:00 
Seconds: 23630400 
After: 1970-10-01 16:00:00

精度测试:FAIL(时区偏移)

方法二:时间模块

import time
from datetime import datetime
total2 = int(time.mktime(datetimeobj.timetuple()))
print ("Method #2: Time Module")
print ("Before: %s" % datetimeobj)
print ("Seconds: %s " % total2)
print ("After: %s" % datetime.fromtimestamp(total2))

输出:

Method #2: Time Module
Before: 1970-10-01 12:00:00 
Seconds: 23616000 
After: 1970-10-01 12:00:00

准确度测试:通过

方法三:日历模块

import calendar
from datetime import datetime
total3 = calendar.timegm(datetimeobj.timetuple())
print ("Method #3: Calendar Module")
print ("Before: %s" % datetimeobj)
print ("Seconds: %s " % total3)
print ("After: %s" % datetime.fromtimestamp(total3))

输出:

Method #3: Calendar Module
Before: 1970-10-01 12:00:00
Seconds: 23616000
After: 1970-10-01 16:00:00

精度测试:FAIL(时区偏移)

方法四:Datetime时间戳

from datetime import datetime
total4 = datetimeobj.timestamp()
print ("Method #4: datetime timestamp")
print ("Before: %s" % datetimeobj)
print ("Seconds: %s " % total4)
print ("After: %s" % datetime.fromtimestamp(total4))

输出:

Method #2: Time Module
Before: 1970-10-01 12:00:00 
Seconds: 23616000 
After: 1970-10-01 12:00:00

准确度测试:通过

结论

所有4个方法都将datetime转换为epoch(总秒数) Manual方法和Calendar模块方法都是时区感知的。 datetime.timestamp()和time.mktime()方法都不涉及时区。 最简单的方法:datetime.timestamp()