通过Django的connection.cursor()在自定义函数中调用Postgresql date_trunc

时间:2014-09-19 10:15:01

标签: django postgresql django-database django-postgresql django-timezone

我创建了一个自定义Postgresql函数,它执行一些计算并使用date_trunc函数确定一个月的开头。在开发自定义函数时,我在与psql建立的数据库连接中检查了它,它工作得很好。虽然这样的连接我得到以下输出:

select date_trunc('month', TIMESTAMP WITH TIME ZONE '2014-09-14 04:10:00+02');
       date_trunc       
------------------------
 2014-09-01 00:00:00+02
(1 row)

这正是我想要的:它在我的时区给了我月初。 如果我尝试在django shell中执行相同的操作(我使用的是psycopg2连接器),我会得到不同的结果:

>>> from django.db import connection
>>> cursor = connection.cursor()
>>> cursor.execute("select date_trunc('month', TIMESTAMP WITH TIME ZONE '2014-09-14 04:10:00+02');")
>>> unicode(cursor.fetchone()[0])
u'2014-09-01 00:00:00+00:00'

如您所见,数据库以UTC格式返回月初,导致与我想要的实际时间戳相差两小时。

这是django将数据库连接的时间戳设置为UTC的结果,这导致date_trunc截断UTC时的月份。 我尝试使用SET TIMEZONE TO 'Europe/Berlin'手动设置连接的时区,但这会产生AssertionError("database connection isn't set to UTC")

以下解决方法在我的案例中有效,但它并不是一个非常漂亮的解决方案。它只能起作用,因为我不需要函数的任何返回值。

cursor.execute("SET TIMEZONE to 'Europe/Berlin'; my_function(parameters); SET TIMEZONE to 'UTC';")

我希望有人可以帮助我找到一种更优雅的方法来解决问题。

1 个答案:

答案 0 :(得分:1)

  1. 在查询中使用AT TIME ZONE'FOO'或TIMEZONE('FOO',时间戳)(根据需要使用实际时区名称的参数);见http://www.postgresql.org/docs/9.2/static/functions-datetime.html#FUNCTIONS-DATETIME-ZONECONVERT
  2. 为查询创建上下文管理器,以保存/设置/恢复特定查询的时区