GAE中使用Google数据API的本地时区问题

1 投票
2 回答
986 浏览
提问于 2025-04-15 15:58

我正在开发一个小应用,使用的是Google App Engine(Python),这个应用通过Google数据API来创建一个新的日历,并在里面添加一些事件。

我使用的事件数据是从其他地方解析过来的,这些事件的日期是以欧洲/斯德哥尔摩的时区表示的(我想是夏令时CEST或标准时CET)。

所以,首先我会用Python创建一个时间结构,比如这样:

start = strptime("2009-11-16 10:15", "%Y-%m-%d %H:%M")

Python的文档说我可以用标志%Z来指定时区,实际上在我的Python解释器中是可以用的……但是在Google App Engine服务器上(无论是本地还是部署后)就完全不行了。这并不是新鲜事,我在这里也看到过类似的问题。

因为我在使用Google数据API,而它需要时间以UTC/GMT格式,所以我需要一种方法将欧洲/斯德哥尔摩的本地时间转换为UTC/GMT,而不使用strptime中的%Z标志……(而且我希望这个方法比单纯地每个日期减去一个小时要聪明一些……)

再次感谢你们的帮助 :)

2 个回答

0

在把你的对象转换成日期时间格式之后,你需要添加时区。为此,你需要创建一个从datetime.tzinfo类派生的类。

import datetime as dt
class SomeZone(dt.tzinfo):
    # a helper class to quickly create simple timezones - give gmt_offset
    def __init__(self, gmt_offset):
        dt.tzinfo.__init__(self)
        self.gmt_offset = gmt_offset        
    def utcoffset(self, dtime): return dt.timedelta(hours=self.gmt_offset)
    def dst(self, dtime): return dt.timedelta(0)
    def tzname(self, dtime): return None

start = strptime("2009-11-16 10:15", "%Y-%m-%d %H:%M")
start.replace(tzinfo=SomeZone(your_offset_here))

好了,现在它就是一个带有时区的日期时间了。从这里开始,谷歌会接手,因为日期时间字段会考虑时区,并且在存储时会以UTC格式保存。

只要记得夏令时和其他相关的事情就可以了。

如果你想深入了解,我在上面提到的类可以在这里找到。

1

我去年在我的博客上发过一篇关于这个主题的文章,里面提到了一些相关内容。简单来说,就是在存储时间的时候,所有的时间都会转换成UTC(协调世界时),然后在读取的时候再加上UTC的时区。你可以随意修改这个方法,把时间转换成你想要的任何本地时区。

这个代码示例可能有点过时了,因为我很久没用过appengine了。不过我希望它能在某种程度上对你有所帮助。

import pytz

class TzDateTimeProperty(db.DateTimeProperty):
    def get_value_for_datastore(self, model_instance):
        if model_instance.posted_at.tzinfo is None:
            model_instance.posted_at = model_instance.posted_at.replace(tzinfo=pytz.utc)
        else:
            model_instance.posted_at = model_instance.posted_at.astimezone(pytz.utc)
        return super(TzDateTimeProperty, self).get_value_for_datastore(model_instance)
    def make_value_from_datastore(self, value):
        value = super(TzDateTimeProperty, self).make_value_from_datastore(value)
        if value.tzinfo is None:
            value = value.replace(tzinfo=pytz.utc)
        else:
            value = value.astimezone(pytz.utc)
        return value

我还推荐一个很棒的库叫pytz;它提供了几乎所有有用的时区对象。(我想给它链接,但防止垃圾信息的机制阻止了我。你可以在网上搜索一下。)

撰写回答