Python中的时间问题

Python中的时间问题,python,datetime,python-3.x,timestamp,python-2.x,Python,Datetime,Python 3.x,Timestamp,Python 2.x,可以随意添加您最喜欢的模块,但到目前为止,我们还有、、和要处理,因为还没有实现,这为我们提供了一种统一、具体的方法来处理时区及其相关的奇怪现象,例如在夏令时转换期间出现两次或根本没有出现的不明确的日期时间。无论如何,我的问题相当平淡,但我似乎找不到答案 后台故事:我正在开发一个小插件,最初允许用户在当前文档中插入时间戳(以他们指定的格式,返回默认格式)。最终,它会在保存时更新时间戳,但这与此处无关。下面是我的简短、自包含的示例代码: import sublime_plugin from date

可以随意添加您最喜欢的模块,但到目前为止,我们还有、、和要处理,因为还没有实现,这为我们提供了一种统一、具体的方法来处理时区及其相关的奇怪现象,例如在夏令时转换期间出现两次或根本没有出现的不明确的日期时间。无论如何,我的问题相当平淡,但我似乎找不到答案

后台故事:我正在开发一个小插件,最初允许用户在当前文档中插入时间戳(以他们指定的格式,返回默认格式)。最终,它会在保存时更新时间戳,但这与此处无关。下面是我的简短、自包含的示例代码:

import sublime_plugin
from datetime import datetime as dt


class TimeStampCommand(sublime_plugin.TextCommand):

    def run(self, edit):
        stamp = dt.utcnow().strftime("%Y-%m-%d %H:%M:%S UTC")  # 2013-10-10 22:38:40 UTC
        for r in self.view.sel():
            if r.empty():
                self.view.insert(edit, r.a, stamp)
            else:
                self.view.replace(edit, r, stamp)
从列表中,我应该能够添加一个
%Z
,并获得本地时区:

stamp = dt.now().strftime("%Y-%m-%d %H:%M:%S %Z")  # should be 2013-10-10 18:38:40 EDT
或者稍微修改它,获得更通用的UTC偏移:

stamp = dt.now().strftime("%Y-%m-%d %H:%M:%S UTC %z")  # should be 2013-10-10 18:38:40 UTC -0400
不幸的是,事实并非如此,因为
dt.now()
返回的时间是“幼稚的”——它没有任何时区信息。我可以使用,但毫无帮助的是,这只是一个抽象的基类,因为时区杂乱无章,复杂多变。因此,从根本上来说,我的问题是:如何创建一个“感知”的
time
/
datetime
/
dateutil
/
任何可以利用
strftime()
格式选项完整数组的对象?我希望用户能够根据自己的语言环境(我需要检测到这种情况),或者根据提供的语言环境,随心所欲地格式化时间戳。最好我希望它能在Windows、Mac和Linux(支持升华文本的平台)上工作。最后,如果Python2.6和3.3(分别用于ST2和ST3的内置解释器版本)之间存在差异,我想了解一下

请注意,我不是要你为我写所有的代码,我想自己学习。我只需要一些好的指点就可以朝着正确的方向前进,因为我一天大部分时间都在旋转轮子。至少,只要弄清楚如何生成
2013-10-10 18:38:40 UTC-0400
将是一个很好的开始,尽管其他东西也会很好:)

如何创建一个“aware”time/datetime/dateutil/whatever对象来利用strftime()格式选项的完整数组

如果您有时区,使用
pytz
模块很容易:

>>> mytz = pytz.timezone('America/Los_Angeles')
>>> now = datetime.datetime.now(tz=mytz)
>>> now
datetime.datetime(2013, 10, 10, 16, 34, 3, 113620, tzinfo=<DstTzInfo 'America/Los_Angeles' PDT-1 day, 17:00:00 DST>)
当然,这不能解析回一个明确的datetime对象,因为无法判断它是指太平洋还是巴基斯坦。因此,向最终用户显示可能有用,但对其他方面没有太多用处。即使你只决定美国的问题,“MST”是指美国大部分DST规则的in-7,还是亚利桑那州没有DST规则的in-7?大多数流行的三字母代码甚至比这两个更糟糕


但是,更重要的是,你首先是如何获得时区的

你不能

在某些POSIX系统上,您可以从
os.environ['TZ']
读取它。但通常不会,或者,如果它可用,除非用户特意将其显式设置为有用的时区标识符,否则它将是一个模棱两可的缩写,如“PST”

在几乎所有POSIX系统上,您都可以执行以下操作:

>>> time.tzset()
>>> time.tzname
('PST', 'PDT')
但这肯定是一个模棱两可的缩写。(而且它在Windows上仍然不起作用。)


至少,只要弄清楚如何生成2013-10-10 18:38:40 UTC-0400将是一个很好的开始

这不是小事,但至少很简单,没有任何第三方代码;这太乏味了

首先,如果您可以信任
tzset
(大多数POSIX平台):

或者,如果您不能信任tzset

>>> t = time.time()
>>> local = datetime.datetime.fromtimestamp(t)
>>> utc = datetime.datetime.utcfromtimestamp(t)
>>> offset = local - utc
>>> sec = offset.total_seconds()
然后将其格式化为字符串:

>>> hr, sec = divmod(sec, 3600)
>>> min, sec = divmod(sec, 60)
>>> offstr = '{:+03d}{:02d}'.format(hr, min)
现在,如果要格式化原始本地时间:

>>> datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") + " " + offstr
'2013-10-10 16:18:36 -0800'

那么,你应该怎么做

显然,所有内部和持久性使用仍然使用UTC时间。然后,您只需要处理本地时间的直接输入和输出。而且,由于您编写的是桌面应用程序,而不是web服务,因此只需使用各种函数即可将naive local与UTC进行转换,而无需知道“local”时区实际上是哪个时区


在您的用例中,用户的时间戳可以从原始日期时间加上您在
tzset
之后从
time
模块中获得的名称(如果可能)进行格式化,如果没有,则返回偏移量。这不会比构建一个可感知的日期时间更糟糕。

您是否阅读了说明
%Z
已被弃用的说明?除了POSIX和Windows的限制,三个字母的时区不是唯一的标识符-
AST
是加拿大的大西洋标准时间,中东的阿拉伯标准时间,巴西的Acre标准时间,分别是-4、+3和-5。我没有,谢谢你指出这一点。也许我会保留默认值作为UTC偏移量,如果他们真的想打印完整时区名称(
time.tzname[time.daylight]
)。
tzname[daylight]
不正确;如果时区有日光,则为1(实际上,仅为“非零”…但我从未见过任何其他数字),如果时区当前处于日光下,则为1。顺便说一句,解决此问题的正确方法是征服世界并取缔所有时区。人们会知道16:00是清晨。或者,如果不是的话,你就朝他们的脸开枪。如果你决定这样做,我将支持你的全球霸主运动。@abarnert:你对Unicode有什么计划?:-)非常有帮助,也是一个很好的开始。
>>> hr, sec = divmod(sec, 3600)
>>> min, sec = divmod(sec, 60)
>>> offstr = '{:+03d}{:02d}'.format(hr, min)
>>> datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") + " " + offstr
'2013-10-10 16:18:36 -0800'