Python 当我有 UTC 偏移量时如何创建 tzinfo?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/17976063/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to create tzinfo when I have UTC offset?
提问by AppleGrew
I have one timezone's offset from UTC in seconds (19800
) and also have it in string format - +0530
.
我有一个时区与 UTC 的偏移量(以秒 ( 19800
)为单位),并且还有字符串格式 - +0530
。
How do I use them to create a tzinfo
instance? I looked into pytz
, but there I could only find APIs that take timezone name as input.
如何使用它们来创建tzinfo
实例?我查看了pytz
,但在那里我只能找到以时区名称作为输入的 API。
回答by Dmitry Nedbaylo
You have to implement subclass of datetime.tzinfo
class. General guide is described here, where you also can find excellent examples of custom tzinfo implementations.
你必须实现类的子datetime.tzinfo
类。此处描述了一般指南,您还可以在此处找到自定义 tzinfo 实现的优秀示例。
Here is example (given that there is no daylight saving time) :
这是示例(假设没有夏令时):
from datetime import tzinfo, timedelta, datetime
from pytz import UTC
class MyUTCOffsetTimezone (tzinfo):
def __init__(self, offset=19800, name=None):
self.offset = timedelta(seconds=offset)
self.name = name or self.__class__.__name__
def utcoffset(self, dt):
return self.offset
def tzname(self, dt):
return self.name
def dst(self, dt):
return timedelta(0)
now = datetime.now(tz=UTC)
print now
# -> 2015-01-28 10:46:42.256841+00:00
print now.astimezone(MyUTCOffsetTimezone())
# -> 2015-01-28 16:16:42.256841+05:30
print datetime.now(MyUTCOffsetTimezone())
# -> 2015-01-28 16:16:42.256915+05:30
回答by Serge Ballesta
Python Standard Library (8.1.6) says that :
Python 标准库 (8.1.6) 说:
- tzinfo is an abstract base class
- the datetime module does not supply any concrete subclasses of tzinfo
- you need to derive a concrete subclass, and (at least) supply implementations of the standard tzinfo methods needed by the datetime methods you use
- a concrete subclass of tzinfo may need to implement the following methods ... If in doubt, simply implement all of them
- tzinfo.utcoffset(self, dt) : return offset of local time from UTC, in minutes east of UTC
- tzinfo.dst(self, dt) : return the daylight saving time (DST) adjustment, in minutes east of UTC, or None if DST information isn't known
- tzinfo.tzname(self, dt) : return the time zone name corresponding to the datetime object dt, as a string
- tzinfo 是一个抽象基类
- datetime 模块不提供 tzinfo 的任何具体子类
- 您需要派生一个具体的子类,并且(至少)提供您使用的日期时间方法所需的标准 tzinfo 方法的实现
- tzinfo 的具体子类可能需要实现以下方法......如果有疑问,只需实现所有这些方法
- tzinfo.utcoffset(self, dt) :返回本地时间与 UTC 的偏移量,以 UTC 以东的分钟数
- tzinfo.dst(self, dt) :返回夏令时 (DST) 调整,以 UTC 以东的分钟数为单位,如果 DST 信息未知,则返回 None
- tzinfo.tzname(self, dt) : 以字符串形式返回日期时间对象 dt 对应的时区名称
All that means that you will have to provide your own implementation for the tzinfo. For example :
所有这一切意味着您必须为 tzinfo 提供您自己的实现。例如 :
class UTC0530(datetime.tzinfo):
"""tzinfo derived concrete class named "+0530" with offset of 19800"""
# can be configured here
_offset = datetime.timedelta(seconds = 19800)
_dst = datetime.timedelta(0)
_name = "+0530"
def utcoffset(self, dt):
return self.__class__._offset
def dst(self, dt):
return self.__class__._dst
def tzname(self, dt):
return self.__class__._name
Usage :
用法 :
tz = UTC0530()
d = datetime.datetime.now(tz)
d.isoformat()
output :
输出 :
2015-01-27T20:19:41.257000+05:30
回答by Joe
If you can, take a look at the excellent dateutilpackage instead of implementing this yourself.
如果可以,请查看优秀的dateutil包,而不是自己实现。
Specifically, tzoffset. It's a fixed offset tzinfo
instance initialized with offset
, given in seconds, which is what you're looking for.
具体来说,tzoffset。它是一个tzinfo
用 初始化的固定偏移实例offset
,以秒为单位给出,这就是您要寻找的。
Update
更新
Here's an example. Be sure to run pip install python-dateutil
first.
这是一个例子。一定pip install python-dateutil
要先跑。
from datetime import datetime
from dateutil import tz
# First create the tzinfo object
tzlocal = tz.tzoffset('IST', 19800)
# Now add it to a naive datetime
local = naive.replace(tzinfo=tzlocal)
# Or convert another timezone to it
utcnow = datetime.utcnow().replace(tzinfo=tz.tzutc())
now = utcnow.astimezone(tzlocal)
I looked up the name IST
from here. The name can really be anything. Just be careful if you deviate, since if you use code that relies on the name, it could lead to bugs later on.
我IST
从这里查了名字。这个名字真的可以是任何东西。如果你偏离了,请小心,因为如果你使用依赖于名称的代码,它可能会在以后导致错误。
By the way, if you have the timezone name upfront, and your operating system supports it, you can use gettzinstead:
顺便说一句,如果您预先有时区名称,并且您的操作系统支持它,您可以使用gettz代替:
# Replace the above with this
tzlocal = tz.gettz('IST')
回答by kubilayeksioglu
If you have pytz:
如果你有pytz:
tz = pytz.FixedOffset(180)
now = timezone.now()
local_now = tz.normalize(now.astimezone(tz))
回答by Turtles Are Cute
With Python 3.2 or higher, you can do this using the builtin datetime library:
使用 Python 3.2 或更高版本,您可以使用内置日期时间库执行此操作:
import datetime
datetime.timezone(-datetime.timedelta(hours=5, minutes=30)
To solve your specific problem, you could use regex:
要解决您的特定问题,您可以使用正则表达式:
sign, hours, minutes = re.match('([+\-]?)(\d{2})(\d{2})', '+0530').groups()
sign = -1 if sign == '-' else 1
hours, minutes = int(hours), int(minute)
tzinfo = datetime.timezone(sign * datetime.timedelta(hours=hours, minutes=minutes))
datetime.datetime(2013, 2, 3, 9, 45, tzinfo=tzinfo)
回答by Jim At Your Service
Based on the excellent answer from @Joe here, I wrote a function which monkey-patches pytz to support named timezones such as 'UTC-06:00' or 'UTC+11:30'. I can construct one of these names based on an offset sent to me from a browser, which only has an integer given by Javascript new Date().getTimezoneOffset() as described hereand referenced here, and then I can post the name as a normal timezone name usable by the rest of my application which uses pytz.
基于@Joe here的出色回答,我编写了一个函数,该函数对 pytz 进行猴子补丁以支持命名时区,例如“UTC-06:00”或“UTC+11:30”。我可以根据从浏览器发送给我的偏移量构造这些名称之一,它只有一个由 Javascript new Date().getTimezoneOffset() 给出的整数,如here所述和here引用,然后我可以将名称发布为正常时区名称可用于我使用 pytz 的应用程序的其余部分。
This mechanism would also work for the op in this question who has an offset in seconds.
这种机制也适用于这个问题中以秒为单位有偏移的操作。
Example construct tzname using the offset the op has in this question:
示例构造 tzname 使用 op 在这个问题中的偏移量:
minutes = offset // 60
tzname = 'UTC%s%02d:%02d' % (
'-' if minutes < 0 else '+',
abs(minutes) // 60, abs(minutes) % 60))
Example construct tzname using a browser timezone offset returned by JavaScript new Date().getTimezoneOffset(), which of note has a reversed sign:
使用 JavaScript new Date().getTimezoneOffset() 返回的浏览器时区偏移量构造 tzname 的示例,注意其中有一个相反的符号:
tzname = (
'UTC%s%02d:%02d' % (
'-' if browser_tz_offset > 0 else '+', # reverse sign
abs(browser_tz_offset) // 60, abs(browser_tz_offset) % 60))
Use the named zone to construct a tzinfo object:
使用命名区域构造一个 tzinfo 对象:
from datetime import datetime
import pytz
tz = pytz.timezone(tzname) # tzname = e.g. 'UTC-06:00' or 'Europe/Madrid'
localized_now = datetime.now(tz)
I call this function during application startup.
我在应用程序启动期间调用此函数。
import re
import pytz
from dateutil import tz as dateutil_tz
def post_load_pytz_offset_timezones_server_wide():
pristine_pytz_timezone = pytz.timezone
def extended_pytz_timezone(zone):
matches = re.match('^UTC([+-])([0-9][0-9]):([0-9][0-9])$', zone) if zone else None
if matches:
sign = -1 if matches.group(1) == '-' else 1
minutes = int(matches.group(2)) * 60 + int(matches.group(3))
tzinfo = dateutil_tz.tzoffset(zone, sign*minutes*60)
else:
tzinfo = pristine_pytz_timezone(zone)
return tzinfo
pytz.timezone = extended_pytz_timezone