我有一个时区与 UTC 的偏移量(以秒为单位)(19800
),并且还具有字符串格式 - +0530
。
如何使用它们创建tzinfo
实例?我查看了pytz
,但在那里我只能找到将时区名称作为输入的 API。
我有一个时区与 UTC 的偏移量(以秒为单位)(19800
),并且还具有字符串格式 - +0530
。
如何使用它们创建tzinfo
实例?我查看了pytz
,但在那里我只能找到将时区名称作为输入的 API。
如果可以的话,看看优秀的dateutil包,而不是自己实现它。
具体来说,tzoffset。这是一个用 初始化的固定偏移量tzinfo
实例offset
,以秒为单位,这就是您要查找的内容。
更新
这是一个例子。一定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)
IST
我从这里查了名字。这个名字真的可以是任何东西。如果您有偏差,请小心,因为如果您使用依赖名称的代码,以后可能会导致错误。
顺便说一句,如果您预先设置了时区名称,并且您的操作系统支持它,您可以使用gettz代替:
# Replace the above with this
tzlocal = tz.gettz('IST')
使用 Python 3.2 或更高版本,您可以使用内置的日期时间库执行此操作:
import datetime
datetime.timezone(-datetime.timedelta(hours=5, minutes=30)
要解决您的特定问题,您可以使用正则表达式:
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)
Python 标准库(8.1.6)说:
这意味着您必须为 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
用法 :
tz = UTC0530()
d = datetime.datetime.now(tz)
d.isoformat()
输出 :
2015-01-27T20:19:41.257000+05:30
你必须实现类的子datetime.tzinfo
类。此处描述了一般指南,您还可以在其中找到自定义 tzinfo 实现的优秀示例。
这是示例(假设没有夏令时):
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
如果你有 pytz:
tz = pytz.FixedOffset(180)
now = timezone.now()
local_now = tz.normalize(now.astimezone(tz))
很简单,只有import datetime
>>> tz = datetime.timezone(datetime.timedelta(seconds=19800))
接下来,您可以,例如
>>> datetime.datetime.now(tz).isoformat(timespec='minutes')
'2021-08-03T18:07+05:30'
基于@Joe here的出色回答,我编写了一个函数,它对 pytz 进行猴子补丁以支持命名时区,例如“UTC-06:00”或“UTC+11:30”。我可以根据从浏览器发送给我的偏移量来构造其中一个名称,该偏移量只有一个由 Javascript new Date().getTimezoneOffset() 给出的整数,如此处所述并在此处引用,然后我可以将名称发布为正常的时区名称可供我使用 pytz 的应用程序的其余部分使用。
这种机制也适用于这个问题中以秒为单位的偏移量的操作。
使用操作在此问题中的偏移量构造 tzname 示例:
minutes = offset // 60
tzname = 'UTC%s%02d:%02d' % (
'-' if minutes < 0 else '+',
abs(minutes) // 60, abs(minutes) % 60))
使用 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))
使用命名区域构造一个 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)
我在应用程序启动期间调用此函数。
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