在Python中生成RFC3339时间戳

在Python中生成RFC3339时间戳,python,datetime,iso8601,rfc3339,Python,Datetime,Iso8601,Rfc3339,我正在尝试用Python生成UTC时间戳。到目前为止,我已经能够做到以下几点: >>> d = datetime.datetime.now() >>> print d.isoformat('T') 2011-12-18T20:46:00.392227 我的问题是设置UTC偏移量 根据,classmethoddatetime.now([tz])采用可选的tz参数,其中tz必须是类tzinfo子类的实例,而datetime.tzinfo是时区信息对象的抽象基类。

我正在尝试用Python生成UTC时间戳。到目前为止,我已经能够做到以下几点:

>>> d = datetime.datetime.now()
>>> print d.isoformat('T')
2011-12-18T20:46:00.392227
我的问题是设置UTC偏移量

根据,classmethod
datetime.now([tz])
采用可选的
tz
参数,其中
tz必须是类tzinfo子类的实例,而
datetime.tzinfo
是时区信息对象的抽象基类。

这就是我迷路的地方——为什么tzinfo是一个抽象类,我应该如何实现它



注意:在PHP中,它就像
timestamp=date(date_rfc339);
一样简单,这就是为什么我无法理解Python的方法如此复杂的原因…

时区是一种痛苦,这可能就是为什么他们选择不将它们包含在datetime库中

试试pytz,它有你想要的tzinfo:

您需要首先创建
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()#我刚刚开始使用的另一个有用的实用工具:用于时区处理和日期解析的库。建议这样做,包括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时间的aware datetime对象,那么您可以:

您还可以使用获取代表本地时区的
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'))
它可以在Python2和Python3上工作。

该软件包可用于Python2.X和3.X。它实现了
tzinfo
的具体子类以及其他服务,因此您不必这样做

要添加UTC偏移,请执行以下操作: 导入日期时间 进口皮茨

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

我在RFC3339 datetime格式方面做了很多努力,但我找到了一个合适的解决方案,可以在两个方向上转换date\u字符串datetime\u对象

您需要两个不同的外部模块,因为其中一个模块只能在一个方向上进行转换(很遗憾):

首次安装:

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
input_string='1989-01-01T00:18:07-05:00'
测试日期=获取日期对象(输入字符串)
#>>>datetime.datetime(1989,1,1,0,18,7,tzinfo=)
测试字符串=获取日期字符串(测试日期)
#“1989-01-01T00:18:07-05:00”
测试字符串为输入字符串#>>>True

海瑞卡!现在,您可以轻松地(哈哈)使用日期字符串和可用格式的日期字符串。

您确实可以使用内置的 模块。作为 ,在 显示如何操作的页面。如果你看一下 你会 请参阅显示许多不同用例的长示例。这是这个的代码 您正在寻找,即生成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
在现代(3.x)python上,要获得RFC 3339 UTC时间,只需使用datetime和这一行(无需第三方模块):

结果是这样的:“2019-06-13T15:29:28.972488+00:00”


这个ISO 8601字符串也与RFC3339兼容。

@monkut-谢谢-pytz类看起来像是另一个可以工作的实现,但根据ruakh的回答,我最终使用了文档中包含的示例。它不会为我返回微秒:-/如果您只想使用UTC时区,则不需要
pytz
模块。感谢很简单。我会把你的答案留到我需要stdlib解决方案的时候。UTC是最短的演示时间。OP并没有特别要求
pytz
知道所有时区及其DST,我觉得这很有用。注意:返回与本地时区对应的puts时区。是。它应该是“
pytz
timezone”,而不是“
put
timezone”,这是python3.3+@villapx的最佳答案:rfc3339是iso8601的配置文件。碰巧,
datetime.isoformat()
是RFC 3339,用于时区感知的日期时间(这就是我使用它的原因)。@villapx:不,它是错误的。你在误导“潜在用户”。如果
.utcoffset()
未反映
.dst()
值,则您的
日期时间
类将被破坏。@J.F.Sebastian噢,哇,您是对的。我完全被
datetime.tzinfo.dst()
误导了:
请注意,dst偏移量(如果适用)已经添加到utcoffset()返回的UTC偏移量中,因此没有必要咨询dst(),除非您有兴趣单独获取dst信息。
对于
utcoffset()
,我没有直接看到上面的内容,其中指出,
“请注意,这是UTC的总偏移量。”
@jrc:now()本身可能不明确(例如,在DST转换期间)。“Heureka”。丢失“H”。实际上Python datetime与ISO 8601不兼容,因为它不允许在链接到的同一文档中以“Z”结尾的字符串,它解释了如何实现它,并给出了一些示例,包括
UTC
类(表示UTC)的完整代码,一个
FixedOffset
类(表示与UTC有固定偏移量的时区,而不是带有DST和诸如此类的时区)和其他一些。@ruakh-谢谢,我错过了这些示例-
LocalTimezone()
类完成了这个任务。刚刚发现了类似的问题:
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
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
import datetime
datetime.datetime.now(datetime.timezone.utc).isoformat()