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

Атрибут 'tzinfo' объектов 'datetime.datetime' не доступен для записи

Как установить часовой пояс экземпляра datetime, который только что вышел из хранилища данных?

Когда он впервые появляется, он находится в UTC. Я хочу изменить его на EST.

Я пытаюсь, например:

class Book( db.Model ):
    creationTime = db.DateTimeProperty()

Когда книга будет восстановлена, я хочу немедленно установить ее tzinfo:

book.creationTime.tzinfo = EST

Где Я использую этот пример для моего объекта EST

Однако я получаю:

attribute 'tzinfo' of 'datetime.datetime' objects is not writable

Я видел несколько ответов, которые рекомендуют pytz и python-dateutil, но я действительно хочу ответить на этот вопрос.

4b9b3361

Ответ 1

datetime объекты неизменяемы, поэтому вы никогда не изменяете ни один из их атрибутов - вы создаете объект new с некоторыми атрибутами одинаковыми, а некоторые разные, и назначаете его на все, что вам нужно назначьте его.

I.e., в вашем случае вместо

book.creationTime.tzinfo = EST

вам нужно закодировать

book.creationTime = book.creationTime.replace(tzinfo=EST)

Ответ 2

Если вы получаете дату и время, которое в EST, но не имеет его заданного поля tzinfo, используйте dt.replace(tzinfo=tz) для назначения tzinfo без изменения времени. (Ваша база данных должна делать это за вас.)

Если вы получаете дату и время, что в UDT, и вы хотите его в EST, вам нужна асинметза. http://docs.python.org/library/datetime.html#datetime.datetime.astimezone

В подавляющем большинстве случаев ваша база данных должна хранить и возвращать данные в UDT, и вам не нужно использовать замену (за исключением, возможно, назначения UDT tzinfo).

Ответ 3

То, что вы хотите, находится прямо в docs.

from datetime import tzinfo, timedelta, datetime

ZERO = timedelta(0)
HOUR = timedelta(hours=1)
DSTSTART = datetime(1, 4, 1, 2)
DSTEND = datetime(1, 10, 25, 1)

def first_sunday_on_or_after(dt):
    days_to_go = 6 - dt.weekday()
    if days_to_go:
        dt += timedelta(days_to_go)
    return dt

class USTimeZone(tzinfo):

    def __init__(self, hours, reprname, stdname, dstname):
        self.stdoffset = timedelta(hours=hours)
        self.reprname = reprname
        self.stdname = stdname
        self.dstname = dstname

    def __repr__(self):
        return self.reprname

    def tzname(self, dt):
        if self.dst(dt):
            return self.dstname
        else:
            return self.stdname

    def utcoffset(self, dt):
        return self.stdoffset + self.dst(dt)

    def dst(self, dt):
        if dt is None or dt.tzinfo is None:
            # An exception may be sensible here, in one or both cases.
            # It depends on how you want to treat them.  The default
            # fromutc() implementation (called by the default astimezone()
            # implementation) passes a datetime with dt.tzinfo is self.
            return ZERO
        assert dt.tzinfo is self

        # Find first Sunday in April & the last in October.
        start = first_sunday_on_or_after(DSTSTART.replace(year=dt.year))
        end = first_sunday_on_or_after(DSTEND.replace(year=dt.year))

        # Can't compare naive to aware objects, so strip the timezone from
        # dt first.
        if start <= dt.replace(tzinfo=None) < end:
            return HOUR
        else:
            return ZERO

now = datetime.now()
print now
print now.tzinfo

Eastern = USTimeZone(-5, 'Eastern', 'EST', 'EDT')
now_tz_aware = now.replace(tzinfo=Eastern)
print now_tz_aware

выход:

2010-01-18 17:08:02.741482
None
2010-01-18 17:08:02.741482-05:00