атрибут '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, но мне действительно нужен ответ на этот вопрос.


person bobobobo    schedule 18.01.2010    source источник


Ответы (3)


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

Т.е. в вашем случае вместо

book.creationTime.tzinfo = EST

ты должен кодировать

book.creationTime = book.creationTime.replace(tzinfo=EST)
person Alex Martelli    schedule 18.01.2010
comment
примечание: он не преобразует часовой пояс UTC в EST (сначала выходит, что это UTC. Я хочу изменить его на EST.). Время остается прежним. Для преобразования можно использовать book.creationTime.astimezone(EST). - person jfs; 04.09.2014

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

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

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

person Glenn Maynard    schedule 18.01.2010

Все, что вам нужно, прямо здесь, в документации.

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
person telliott99    schedule 18.01.2010
comment
Вряд ли это очень информативно. Вы могли бы объяснить то же самое, сказав использовать datetime.replace (tzinfo = ...) - но вы не объяснили, как он должен ПОЛУЧАТЬ желаемый tzinfo, вы просто жестко запрограммировали часовой пояс EST / EDT. - person Auspex; 23.04.2013