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

匿名 (未验证) 提交于 2019-12-03 02:49:01

问题:

How do I set the timezone of a datetime instance that just came out of the datastore?

When it first comes out it is in UTC. I want to change it to EST.

I'm trying, for example:

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

When a Book is retrieved, I want to set its tzinfo immediately:

book.creationTime.tzinfo = EST 

Where I use this example for my EST object

However I get:

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

I've seen a number of answers that recommend pytz and python-dateutil, but I really want an answer to this question.

回答1:

datetime's objects are immutable, so you never change any of their attributes -- you make a new object with some attributes the same, and some different, and assign it to whatever you need to assign it to.

I.e., in your case, instead of

book.creationTime.tzinfo = EST 

you have to code

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


回答2:

If you're receiving a datetime that's in EST, but doesn't have its tzinfo field set, use dt.replace(tzinfo=tz) to assign a tzinfo without modifying the time. (Your database should be doing this for you.)

If you're receiving a datetime that's in UDT, and you want it in EST, then you need astimezone. http://docs.python.org/library/datetime.html#datetime.datetime.astimezone

In the vast majority of cases, your database should be storing and returning data in UDT, and you shouldn't need to use replace (except possibly to assign a UDT tzinfo).



回答3:

What you want is right there in the 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 

output:

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


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!