Как создать tzinfo, когда у меня есть UTC-смещение?
У меня есть одно временное смещение от UTC в секундах (19800
), а также оно в строчном формате - +0530
.
Как использовать их для создания экземпляра tzinfo
? Я просмотрел pytz
, но там я мог найти API, которые принимают имя часового пояса в качестве входных данных.
Ответы
Ответ 1
Если вы можете, посмотрите на отличный 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
здесь. Название действительно может быть чем угодно. Просто будьте осторожны, если вы отклоняетесь, поскольку, если вы используете код, который зависит от имени, это может привести к ошибкам позже.
Кстати, если у вас есть имя часового пояса upfront, и ваша операционная система поддерживает его, вы можете вместо этого использовать gettz:
# Replace the above with this
tzlocal = tz.gettz('IST')
Ответ 2
Стандартная библиотека Python (8.1.6) говорит, что:
- tzinfo - абстрактный базовый класс
- модуль datetime не предоставляет каких-либо конкретных подклассов tzinfo
- вам нужно получить конкретный подкласс и (по крайней мере) реализацию поставки стандартных методов tzinfo, необходимых для использования методов datetime, которые вы используете
- конкретному подклассу tzinfo, возможно, потребуется реализовать следующие методы... Если есть сомнения, просто реализуйте все из них
- tzinfo.utcoffset(self, dt): смещение по местному времени с UTC, в минутах к востоку от UTC
- tzinfo.dst(self, dt): вернуть настройку перехода на летнее время (DST) в минутах к востоку от UTC или None, если информация о DST не известна
- tzinfo.tzname(self, dt): вернуть имя часового пояса, соответствующее объекту datetime dt, в виде строки
Все это означает, что вам нужно будет предоставить свою собственную реализацию для 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
Ответ 3
Вы должны реализовать подкласс класса 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
Ответ 4
Если у вас есть pytz:
tz = pytz.FixedOffset(180)
now = timezone.now()
local_now = tz.normalize(now.astimezone(tz))
Ответ 5
С Python 3.2 или выше вы можете сделать это, используя встроенную библиотеку 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)