在 Python 中生成 RFC 3339 时间戳[重复]
- 2025-04-01 09:56:00
- admin 原创
- 14
问题描述:
我正在尝试用 Python 生成RFC 3339 UTC 时间戳。到目前为止,我已经能够执行以下操作:
>>> d = datetime.datetime.now()
>>> print d.isoformat('T')
2011-12-18T20:46:00.392227
我的问题在于设置 UTC 偏移量。
根据文档,类方法datetime.now([tz])
采用可选tz
参数,其中tz must be an instance of a class tzinfo subclass
,并且datetime.tzinfo
是an abstract base class for time zone information objects.
这就是我迷失的地方——tzinfo 怎么是一个抽象类,我该如何实现它?
(注意:在 PHP 中它很简单timestamp = date(DATE_RFC3339);
,这就是为什么我无法理解为什么 Python 的方法如此复杂......)
解决方案 1:
2021 年更新
在 Python 3.2 中,timezone
datetime 模块被添加,允许您轻松地将时区分配给 UTC。
import datetime
n = datetime.datetime.now(datetime.timezone.utc)
n.isoformat() # '2021-07-13T15:28:51.818095+00:00'
先前的答案:
时区很麻烦,这可能就是为什么他们选择不将其包含在日期时间库中。
尝试 pytz,它有你正在寻找的 tzinfo:
http://pytz.sourceforge.net/
您需要首先创建datetime
对象,然后像下面这样应用时区,然后您的.isoformat()
输出将根据需要包含 UTC 偏移量:
d = datetime.datetime.utcnow()
d_with_timezone = d.replace(tzinfo=pytz.UTC)
d_with_timezone.isoformat()
'2017-04-13T14:34:23.111142+00:00'
或者,只需使用 UTC,并在末尾添加“Z”(代表祖鲁时区)以将“时区”标记为 UTC。
d = datetime.datetime.utcnow() # <-- get time in UTC
print d.isoformat("T") + "Z"
'2017-04-13T14:34:23.111142Z'
解决方案 2:
在 Python 3.3+ 中:
>>> from datetime import datetime, timezone
>>> local_time = datetime.now(timezone.utc).astimezone()
>>> local_time.isoformat()
'2015-01-16T16:52:58.547366+01:00'
在较旧的 Python 版本中,如果您所需要的只是一个表示 UTC 当前时间的 datetime 对象,那么您可以定义一个简单的 tzinfo 子类,如文档中所示,以表示 UTC 时区:
from datetime import datetime
utc_now = datetime.now(utc)
print(utc_now.isoformat('T'))
# -> 2015-05-19T20:32:12.610841+00:00
您还可以使用tzlocal
模块来获取pytz
代表您当地时区的时区:
#!/usr/bin/env python
from datetime import datetime
from tzlocal import get_localzone # $ pip install tzlocal
now = datetime.now(get_localzone())
print(now.isoformat('T'))
它适用于 Python 2 和 3。
解决方案 3:
在现代(3.x)python 上,要获取 RFC 3339 UTC 时间,您需要做的就是使用 datetime 和这一行(无需第三方模块):
import datetime
datetime.datetime.now(datetime.timezone.utc).isoformat()
结果如下:“2019-06-13T15:29:28.972488+00:00”
此 ISO 8601 字符串也兼容 RFC3339。
解决方案 4:
我对 RFC3339 日期时间格式苦苦挣扎,但我找到了一个合适的解决方案,可以在两个方向上转换 date_string <=> datetime_object。
您需要两个不同的外部模块,因为其中一个只能在一个方向进行转换(不幸的是):
首次安装:
sudo pip install rfc3339
sudo pip install iso8601
然后包括:
import datetime # for general datetime object handling
import rfc3339 # for date object -> date string
import iso8601 # for date string -> date object
为了不需要记住哪个模块用于哪个方向,我编写了两个简单的辅助函数:
def get_date_object(date_string):
return iso8601.parse_date(date_string)
def get_date_string(date_object):
return rfc3339.rfc3339(date_object)
你可以很容易地在代码中像这样使用它:
input_string = '1989-01-01T00:18:07-05:00'
test_date = get_date_object(input_string)
# >>> datetime.datetime(1989, 1, 1, 0, 18, 7, tzinfo=<FixedOffset '-05:00' datetime.timedelta(-1, 68400)>)
test_string = get_date_string(test_date)
# >>> '1989-01-01T00:18:07-05:00'
test_string is input_string # >>> True
好啦!现在您可以轻松(哈哈)以可用格式使用日期字符串和日期字符串。
解决方案 5:
我刚开始使用的另一个有用的实用程序:用于时区处理和日期解析的 dateutil库。推荐 SO,包括这个答案
解决方案 6:
pytz包适用于 Python 2.X 和 3.X。它实现了 的具体子类tzinfo
以及其他服务,因此您不必这样做。
要添加 UTC 偏移量:导入 datetime 导入 pytz
dt = datetime.datetime(2011, 12, 18, 20, 46, 00, 392227)
utc_dt = pytz.UTC.localize(dt)
现在这个:
print utc_dt.isoformat()
将打印:
2011-12-18T20:46:00.392227+00:00
解决方案 7:
您确实可以使用内置的
datetime模块。正如
@ruakh
提到的,页面中有一些示例展示了如何使用。如果您查看
tzinfo部分,您会看到一个很长的示例,其中展示了许多不同的用例。这是您要查找的代码,用于生成 RFC 3339 UTC 时间戳。
from datetime import tzinfo, timedelta, datetime
import time as _time
ZERO = timedelta(0)
STDOFFSET = timedelta(seconds=-_time.timezone)
if _time.daylight:
DSTOFFSET = timedelta(seconds=-_time.altzone)
else:
DSTOFFSET = STDOFFSET
DSTDIFF = DSTOFFSET - STDOFFSET
class LocalTimezone(tzinfo):
def utcoffset(self, dt):
if self._isdst(dt):
return DSTOFFSET
else:
return STDOFFSET
def dst(self, dt):
if self._isdst(dt):
return DSTDIFF
else:
return ZERO
def tzname(self, dt):
return _time.tzname[self._isdst(dt)]
def _isdst(self, dt):
tt = (dt.year, dt.month, dt.day,
dt.hour, dt.minute, dt.second,
dt.weekday(), 0, 0)
stamp = _time.mktime(tt)
tt = _time.localtime(stamp)
return tt.tm_isdst > 0
Local = LocalTimezone()
d = datetime.now(Local)
print d.isoformat('T')
# which returns
# 2014-04-28T15:44:45.758506-07:00