PostgreSQL: between with datetime

≡放荡痞女 提交于 2019-12-03 02:15:15

You expected 1-01-01 ... 1-12-31 ... but how is PostgreSQL supposed to know what you mean by that?

String literals are interpreted according to your current locale settings, in particular lc_time when cast to timestamp or date. I quote the manual here:

lc_time (string)

Sets the locale to use for formatting dates and times, for example with the to_char family of functions. Acceptable values are system-dependent; see Section 22.1 for more information. If this variable is set to the empty string (which is the default) then the value is inherited from the execution environment of the server in a system-dependent way.

In your case, the mutilated timestamp literal 1-12-31 23:59:59 is obviously interpreted as:

D-MM-YY h24:mi:ss

While you would have hoped for:

Y-MM-DD h24:mi:ss

3 options

  1. Set lc_time to a locale that interprets such a literal in the same way as you do. Not sure there is one.

  2. Use to_timestamp() to interpret the string literal in a well defined way - independent of the current locale. Much better.

    SELECT to_timestamp('1-12-31 23:59:59', 'D-MM-YY h24:mi:ss')
    
  3. Better yet, use ISO 8601 format (YYYY-MM-DD) for all datetime literals. That is unambiguous with any locale.

    SELECT '2001-12-31 23:59:59'::timestamp
    

Rewrite query

Finally, your query is faulty to begin with. Handle a range query differently. Rewrite your query to:

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;

Or, simpler yet:

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;

The new range types of PostgreSQL 9.2 may be of interest to you.

SELECT '1-12-31 23:59:59.999999'::timestamp; returns 2031-01-12 23:59:59.999999, apparently Postgres does not consider year-without-century as first element in the date.

You didn't say what format you wanted it in. So it gives back the native format. Perhaps you even assumed that everyone denotes time the way you do? Have a look at the possible formats. http://www.postgresql.org/docs/8.2/static/functions-formatting.html

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!