Postgresql 有两种不同的时间戳数据类型,在什么时候应该使用哪一种令人困惑。这两种类型是:
-
timestamp(也称为timestamp without time zone)很可能是table_a中的类型
-
timestamp with time zone这是to_timestamp()返回的数据类型
您必须确保将苹果与苹果或一对与一对进行比较,不要将它们混合使用,否则您可能会得到不良结果。
如果您的table_a.time_1 是timestamp with time zone,那么您在问题中提供的代码将可以正常工作。
如果您的table_a.time_1 是timestamp,那么您将需要更改您的代码:
SELECT *
FROM table_a
WHERE time_1 >= to_timestamp('11/01/2014 10:00 PDT', 'MM/DD/YYYY HH24:MI TZ') at time zone 'utc';
最后一部分 (at time zone 'utc') 将从指定的时间戳中去除时区 (PDT),并将时间戳转换为 UTC。
编辑:在这个答案中帮助您的 cmets...
为了了解如何翻译时区,您需要了解两种形式的时间戳之间的区别。你会明白为什么你需要在下面理解这一点。正如我在上面指出的,两种形式的时间戳之间的区别令人困惑。有一个good manual page,但现在请继续阅读。
要了解的主要内容是 两个 版本实际上都没有存储时区(尽管有名称)。如果您添加一个额外的单词“translation”,命名会更有意义。想想“没有时区转换的时间戳”和“有时区转换的时间戳”。
timestamp with time zone翻译根本不存储时区。它旨在存储可能来自世界任何地方的时间戳,并且不会丢失它们的含义。因此,当输入一个时,您必须提供它来自的时区,否则 postgresql 将假定它来自the time zone of your current session。 Postgresql 自动将其从给定的时区转换为服务器的内部时区。你不需要知道那是什么时区,因为 postgresql 在给你值之前总是会从这个内部时区翻译回来。当您检索值(例如:SELECT my_time FROM foo)时,postgresql 会将时间戳转换为当前会话的时区。或者,您可以指定要转换为的时区(例如:SELECT my_time AT TIME ZONE 'PDT' FROM foo)。
考虑到这一点,更容易理解的是,timestamp没有时区转换从您指定的时间起永远不会更改。 Postgresql 会将11:00:00 视为发生在12:00:00 之前,即使您的意思是美国的11 个和英国的12 个。很容易看出为什么这可能不是您想要的。
一个非常常见的编程错误是认为timestamp with time zone 位于特定时区。它不是。它在您要求的任何时区。如果你没有指定你想要的时区,那么 postgresql 会假设你在当前会话时区想要它。
您已声明您的字段是timestamp with time zone,它们都位于UTC。这在技术上是不正确的。您的会话时区很可能是 UTC,因此 postgresql 会为您提供 UTC 格式的所有内容。
所以你有一个timestamp with time zone 并且你想知道这些时间在 PDT 中是什么时候?简单:SELECT my_time AT TIME ZONE 'PDT' FROM foo。
了解AT TIME ZONE '...' 语法在timestamp 和timestamp with time zone 之间切换很重要。
-
timestamp AT TIME ZONE 'PDT' 转换为 timestamp with time zone 并告诉 postgresql 转换为 PDT 时区。
-
timestamp with time zone AT TIME ZONE 'PDT' 转换为 timestamp 告诉 postgresql 将其解释为来自“PDT”。
这种对称性意味着要反转AT TIME ZONE 'foo',您只需使用AT TIME ZONE 'foo'。换句话说,SELECT anything AT TIME ZONE 'PDT' AT TIME ZONE 'PDT' 将始终保持 anything 不变。