Python 虽然我有预感,但这不是标准做法。但几乎没有任何解释来解释重复的+2小时添加。关于云仪表板,我认为这只是一个表示问题。我们有(ndb)模型,它们使用ndb.DateTimeProperty(auto_add=True)记录时间戳;在云仪表板中,时间戳显示为本

Python 虽然我有预感,但这不是标准做法。但几乎没有任何解释来解释重复的+2小时添加。关于云仪表板,我认为这只是一个表示问题。我们有(ndb)模型,它们使用ndb.DateTimeProperty(auto_add=True)记录时间戳;在云仪表板中,时间戳显示为本,python,google-app-engine,datetime,google-cloud-datastore,timezone-offset,Python,Google App Engine,Datetime,Google Cloud Datastore,Timezone Offset,虽然我有预感,但这不是标准做法。但几乎没有任何解释来解释重复的+2小时添加。关于云仪表板,我认为这只是一个表示问题。我们有(ndb)模型,它们使用ndb.DateTimeProperty(auto_add=True)记录时间戳;在云仪表板中,时间戳显示为本地时间:2017-06-10(21:36:07.917)BST,但如果我在远程shell中打印时间戳,则时间相当于UTC:2017-06-10 20:36:07.917540。相关:好的,仪表板表示是可以理解的。但是,我的getter似乎仍然在


虽然我有预感,但这不是标准做法。但几乎没有任何解释来解释重复的+2小时添加。关于云仪表板,我认为这只是一个表示问题。我们有(ndb)模型,它们使用
ndb.DateTimeProperty(auto_add=True)
记录时间戳;在云仪表板中,时间戳显示为本地时间:2017-06-10(21:36:07.917)BST,但如果我在远程shell中打印时间戳,则时间相当于UTC:2017-06-10 20:36:07.917540。相关:好的,仪表板表示是可以理解的。但是,我的getter似乎仍然在
put()
put\u async()
上被调用——尽管我有预感这不是标准的做法。但对于重复的+2小时加法几乎没有任何解释。
class TimeZonedDateTimeProperty(db.DateTimeProperty):
    def __init__(self, *args, **kwargs):
        super(TimeZonedDateTimeProperty, self).__init__(*args, **kwargs)

    def __get__(self, model_instance, model_class):
        """Returns the value for this property on the given model instance."""

        if model_instance is None:
            return self

        attr_to_return = None

        try:
            # access the db.DateTimeProperty's getter

            attr_to_return = getattr(model_instance, super(TimeZonedDateTimeProperty, self)._attr_name())
        except AttributeError:
            attr_to_return = None

        if attr_to_return:
            # super methods of db.DateTimeProperty will be calling this 
            # getter too and we don't wanna mess up
            # the UTC convention when working with datetimes

            includes_correct_caller = None

            try:
                # after noticing that this getter is also being called
                # outside of user requests, inspect the caller and decide
                # whether to offset the UTC datetime or not 

                includes_correct_caller = "main_class_name" in str(inspect.stack()[1][0].f_locals["self"].__class__)
            except Exception:
                includes_correct_caller = False

            if includes_correct_caller:
                return attr_to_return + relativedelta(hours=+2)
            else:
                return attr_to_return
        else:
            return None
class Message(db.Model):
    ...
    sent = TimeZonedDateTimeProperty()
    ...


m = Message(...
            sent=datetime.utcnow(),
            ...)
m.put()
...

includes_correct_caller = None

try:
    _, _, _, stack_trace, _, _ = zip(*list(inspect.stack()))
    includes_correct_caller = "put" not in stack_trace    
except Exception:
    includes_correct_caller = False

if includes_correct_caller:
    return attr_to_return + relativedelta(hours=+2)
else:
    return attr_to_return
from dateutil import tz
from google.appengine.ext import db

class Message(db.Model):

    sent = db.DateTimeProperty()

    def local_sent(self, default_tz='Europe/Paris'):
        """
        Returns a timezone-aware datetime for the local
        timezone.  
        The default timezone can be overridden to support
        other locales. 
        """
        utc = tz.gettz('UTC')
        local = tz.gettz(tz)    # or some other CET timezone
        return self.sent.replace(tzinfo=utc).astimezone(local)
m = Message(sent=datetime.datetime.utcnow())
m.sent
datetime.datetime(2017, 6, 16, 18, 0, 12, 364017)
m.local_sent()
datetime.datetime(2017, 6, 16, 20, 0, 12, 364017, tzinfo=tzfile('/usr/share/zoneinfo/Europe/Paris'))
m.local_sent.strftime('%Y-%m-%d %H:%M:%S.%f %z %Z')
'2017-06-16 20:00:12.364017 +0200 CEST'

m = Message(sent=datetime.datetime.utcnow())
2017-06-16 18:15:33.555208
2017-06-16 18:15:33.555208  
m.local_sent('Asia/Beijing')
datetime.datetime(2017, 6, 17, 2, 15, 33, 555208, tzinfo=tzfile('/usr/share/zoneinfo/Asia/Beijing'))
m.local_sent('Asia/Beijing').strftime('%Y-%m-%d %H:%M:%S.%f %z %Z')
'2017-06-17 02:15:33.555208 +0800 CST'