如何在GQL的DateTimeProperty()中插入时间戳?

1 投票
1 回答
826 浏览
提问于 2025-04-17 20:07

我的定时任务的目标是把推文和它们的时间戳保存到Google App Engine的数据库里。不过,我一直搞不清楚怎么把时间戳保存成正确的格式(现在保存的是字符串形式)。我希望能把它保存成DateTimeProperty,这样以后排序会更方便。现在我遇到了两个具体的问题:

  1. 如何正确使用time.mktime(),
  2. 如何把正确格式的值放入GQL中。

这个字段在json中的格式是这样的:

s = "Wed, 20 Mar 2013 05:39:25 +0000"

我尝试使用datetime模块来解析这个字符串:

timestr = datetime.datetime.strptime(s, "%a, %b %Y %d %H:%M:%S +0000")
when = datetime.fromtimestamp(time.mktime(timestr))

总的来说,这是我cron.py文件的一部分:

result = simplejson.load(urllib.urlopen(twitterurl))
for item in result['results']:

g = ""
try:
    g = simplejson.dumps(item['geo']['coordinates'])
except:
    pass

timestr = datetime.datetime.strptime(str(item['created_at']), "%a, %b %Y %d %H:%M:%S +0000")
when = datetime.fromtimestamp(time.mktime(timestr))

tStore = TweetsFromJSON(user_id=str(item['from_user_id']),
                        user=item['from_user'], 
                        tweet=unicodedata.normalize('NFKD', item['text']).encode('ascii', 'ignore'),
                        timestamp=when,
                        iso=item['iso_language_code'], 
                        geo=g
                        )

数据库的模型应该是:

class TweetsFromJSON(db.Model):
    user = db.TextProperty()
    user_id = db.TextProperty()
    tweet = db.TextProperty()
    timestamp = db.DateTimeProperty()
    iso = db.StringProperty()
    geo = db.StringProperty()

1 个回答

1

你应该使用以下格式来用 datetime.strptime 来解析时间字符串:

"%a, %d %b %Y %H:%M:%S %z"

在Python 3中,这样做是有效的:

Python 3.3.0 (default, Mar 22 2013, 20:14:41) 
[GCC 4.2.1 Compatible FreeBSD Clang 3.1 ((branches/release_31 156863))] on freebsd9
Type "help", "copyright", "credits" or "license" for more information.
>>> from datetime import datetime
>>> s = 'Wed, 20 Mar 2013 05:39:25 +0000'
>>> datetime.strptime(s, "%a, %d %b %Y %H:%M:%S %z")
datetime.datetime(2013, 3, 20, 5, 39, 25, tzinfo=datetime.timezone.utc)

注意,这个方法返回的是一个 datetime 对象,所以后续的处理就不需要了。

可惜的是,这在Python 2中不管用;

Python 2.7.3 (default, Jan 17 2013, 21:23:30) 
[GCC 4.2.1 Compatible FreeBSD Clang 3.0 (branches/release_30 142614)] on freebsd9
Type "help", "copyright", "credits" or "license" for more information.
>>> from datetime import datetime
>>> s = 'Wed, 20 Mar 2013 05:39:25 +0000'
>>> datetime.strptime(s, "%a, %d %b %Y %H:%M:%S %z")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python2.7/_strptime.py", line 317, in _strptime
    (bad_directive, format))
ValueError: 'z' is a bad directive in format '%a, %d %b %Y %H:%M:%S %z'

这似乎是Python 2.7中的一个bug。文档中提到了 %z,但在 /usr/local/lib/python2.7/_strptime.py 里的代码没有包含正确的正则表达式来匹配它。

作为在Python 2中的一个解决方法,你可以试试这个:

>>> datetime.strptime(s[:-6], "%a, %d %b %Y %H:%M:%S")
datetime.datetime(2013, 3, 20, 5, 39, 25)

这个方法只是把最后6个字符去掉。只有当时区偏移有符号并且有四位数字时,这种方法才会正确工作。另一种选择是使用 splitjoin

>>> datetime.strptime(' '.join(s.split()[:-1]), "%a, %d %b %Y %H:%M:%S")
datetime.datetime(2013, 3, 20, 5, 39, 25)

根据我的理解,你需要自己解析时区信息,创建一个自定义的 tzinfo 子类(可以参考文档中的 FixedOffset 类示例),然后用 datetime.replace() 把它放入 datetime 对象中。

撰写回答