Подтвердить что ты не робот

Как создать tzinfo, когда у меня есть UTC-смещение?

У меня есть одно временное смещение от UTC в секундах (19800), а также оно в строчном формате - +0530.

Как использовать их для создания экземпляра tzinfo? Я просмотрел pytz, но там я мог найти API, которые принимают имя часового пояса в качестве входных данных.

4b9b3361

Ответ 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)