【问题标题】:attribute 'tzinfo' of 'datetime.datetime' objects is not writable'datetime.datetime' 对象的属性 'tzinfo' 不可写
【发布时间】:2011-01-06 13:27:25
【问题描述】:

如何设置刚从数据存储区出来的日期时间实例的时区?

当它第一次出现时,它是 UTC。我想把它改成 EST。

我正在尝试,例如:

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

当一本书被检索到时,我想立即设置它的 tzinfo:

book.creationTime.tzinfo = EST

I use this example 我的 EST 对象在哪里

但是我得到:

'datetime.datetime' 对象的属性 'tzinfo' 不可写

我看过很多推荐 pytz 和 python-dateutil 的答案,但我真的很想知道这个问题的答案。

【问题讨论】:

    标签: python google-app-engine datetime tzinfo


    【解决方案1】:

    datetime 的对象是不可变的,所以你永远不会改变它们的任何属性——你创建一个 new 对象,它的一些属性相同,一些不同,然后将它分配给你的任何对象需要分配给它。

    即,在你的情况下,而不是

    book.creationTime.tzinfo = EST
    

    你必须编码

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

    【讨论】:

    • 注意:它不会从 UTC 转换为 EST 时区(“它首先出现在 UTC。我想将其更改为 EST。”)。时间保持不变。要转换,可以使用book.creationTime.astimezone(EST)
    【解决方案2】:

    如果您收到的日期时间在 EST,但没有设置其 tzinfo 字段,请使用 dt.replace(tzinfo=tz) 分配 tzinfo 而无需修改时间。 (您的数据库应该为您执行此操作。)

    如果您收到的日期时间采用 UDT 格式,并且您希望它采用 EST 格式,那么您需要 astimezone。 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
      

      【讨论】:

      • 这信息量不大。你可以通过说使用 datetime.replace(tzinfo=...) 来解释 - 但你还没有解释他应该如何获取他想要的 tzinfo,你只是硬编码了一个 EST/EDT 时区。
      猜你喜欢
      • 2016-09-29
      • 2013-08-23
      • 2015-05-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-01-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多