我使用PostgreSQL 8.4.11和发现奇怪的错误。 当我查询:
SELECT "documents_document"."given_on"
FROM "documents_document"
WHERE (EXTRACT('month' FROM "documents_document"."given_on") = 1
AND "documents_document"."given_on"
BETWEEN '1-01-01 00:00:00' and '1-12-31 23:59:59.999999')
ORDER BY "documents_document"."created_on" DESC
我得到的结果:
given_on
------------
2002-01-16
2011-01-25
2012-01-12
2012-01-12
2012-01-12
2012-01-20
2012-01-19
2012-01-13
2012-01-31
2012-01-16
2012-01-31
2012-01-12
...
为什么?
我希望在日期间隔1-01-01 ... 31年1月12日。
您预计1-01-01 ... 1-12-31
......但PostgreSQL的应该是如何知道你的意思吗?
字符串文本是根据当前的区域设置的解释,特别是lc_time
投时timestamp
或date
。 我引用手册这里 :
LC_TIME(串)
设置要为to_char族函数用于格式化的日期和时间,例如语言环境。 可接受的值为系统依赖型; 见第22.1节以获取更多信息。 如果该变量被设置为空字符串(这是默认值),则该值从服务器的一个系统相关的方式执行环境继承。
在你的情况下,被肢解的时间戳文字1-12-31 23:59:59
明显解释为:
D-MM-YY h24:mi:ss
虽然你会希望:
Y-MM-DD h24:mi:ss
3个选项
设置lc_time
为你做,这样的解释文字以同样的方式一个区域。 不知道有一个。
使用to_timestamp()
来解释字符串中明确定义的方式直译-独立于当前的语言环境。 好多了。
SELECT to_timestamp('1-12-31 23:59:59', 'D-MM-YY h24:mi:ss')
更重要的是,使用ISO 8601格式 ( YYYY-MM-DD
)的所有日期时间文字。 这是明确的任何区域 。
SELECT '2001-12-31 23:59:59'::timestamp
重写查询
最后,您的查询是错误的开始。 不同的处理范围查询。 重写查询到:
SELECT d.given_on
FROM documents_document d
WHERE EXTRACT('month' FROM d.given_on) = 1
AND d.given_on >= '2001-01-01 0:0'
AND d.given_on < '2002-01-01 0:0'
ORDER BY d.created_on DESC;
或者更简单的:
SELECT d.given_on
FROM documents_document d
WHERE d.given_on >= '2001-01-01 0:0'
AND d.given_on < '2001-02-01 0:0'
ORDER BY d.created_on DESC;
该新系列类型PostgreSQL 9.2的可能是你的兴趣。
SELECT '1-12-31 23:59:59.999999'::timestamp;
返回2031-01-12 23:59:59.999999
,显然Postgres没有考虑年没有世纪中日第一要素。
你没有说你希望它是什么格式,所以还给原生格式。 也许你甚至认为每个人都表示时间你的方式? 看看可能的格式。 http://www.postgresql.org/docs/8.2/static/functions-formatting.html