我有一个时区与UTC的偏移量(秒19800
),并且还有字符串格式 - +0530
。
如何使用它们创建tzinfo
实例?我查看了pytz
,但在那里我只能找到以时区名称作为输入的API。
答案 0 :(得分:25)
如果可以的话,请查看优秀的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
from here。这个名字真的可以是任何东西。如果你偏离,请小心,因为如果你使用依赖于名称的代码,它可能会在以后导致错误。
顺便说一下,如果您预先设置了时区名称,并且操作系统支持该名称,则可以改为使用gettz:
# Replace the above with this
tzlocal = tz.gettz('IST')
答案 1 :(得分:16)
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
答案 2 :(得分:8)
您必须实现datetime.tzinfo
类的子类。一般指南是described here,您还可以在其中找到自定义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
答案 3 :(得分:7)
使用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)
答案 4 :(得分:6)
如果你有pytz:
tz = pytz.FixedOffset(180)
now = timezone.now()
local_now = tz.normalize(now.astimezone(tz))
答案 5 :(得分:0)
基于@Joe here的出色回答,我编写了一个函数,该函数对pytz进行了猴子修补,以支持诸如“ UTC-06:00”或“ UTC + 11:30”之类的命名时区。我可以根据从浏览器发送给我的偏移量来构造其中一个名称,该偏移量仅包含Javascript new Date()。getTimezoneOffset()给出的整数,如here和引用的here所述,并且然后我可以将该名称发布为正常的时区名称,供其他使用pytz的应用程序使用。
此机制也适用于此问题中以秒为单位偏移的操作。
使用op在此问题中具有的偏移量构造示例tzname:
minutes = offset // 60
tzname = 'UTC%s%02d:%02d' % (
'-' if minutes < 0 else '+',
abs(minutes) // 60, abs(minutes) % 60))
使用浏览器时区偏移量返回的示例构造tzname JavaScript新的Date()。getTimezoneOffset(),注意其中带有反斜杠的符号:
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
答案 6 :(得分:0)
很简单,只需import datetime
>>> tz = datetime.timezone(datetime.timedelta(seconds=19800))
接下来,你可以,例如
>>> datetime.datetime.now(tz).isoformat(timespec='minutes')
'2021-08-03T18:07+05:30'