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'