PostgreSQL 中的时间戳操作 - 小时/时区问题

发布于 2024-10-07 00:58:16 字数 1054 浏览 1 评论 0原文

我需要对数据库执行一些日期时间操作,这要求所有创建的时间戳具有相同的年份。我尝试使用此查询:

select created,cast (created - 
    to_timestamp(''||date_part('year', created), 'YYYY') + 
    timestamp '2010-01-01' as timestamp without time zone) 
    from table where created is not null limit 10;

...但结果仅部分令人满意:

       created       |      timestamp      
---------------------+---------------------
 2010-08-29 12:44:05 | 2010-08-29 11:44:05
 2007-06-21 13:49:22 | 2010-06-21 12:49:22
 2007-06-21 15:02:33 | 2010-06-21 14:02:33
 2007-06-21 15:05:26 | 2010-06-21 14:05:26
 1999-09-30 13:00:00 | 2010-09-30 12:00:00
 1997-06-07 13:00:00 | 2010-06-07 12:00:00
 2010-06-15 20:51:01 | 2010-06-15 19:51:01
 2006-08-26 15:33:02 | 2010-08-26 14:33:02
 2009-12-15 11:07:06 | 2010-12-15 11:07:06
 1997-06-28 13:00:00 | 2010-06-28 12:00:00
(10 rows)

如您所见,与原始创建值相比,所有时间戳均为-1小时。更奇怪的是,上一篇(2010-12-15 11:07:06)之前的一篇却不是。

created列是timestamp without time zone类型。

知道我做错了什么吗?

I need to do some date-time operations on my database which require all created timestamps to have the same year. I tried with this query:

select created,cast (created - 
    to_timestamp(''||date_part('year', created), 'YYYY') + 
    timestamp '2010-01-01' as timestamp without time zone) 
    from table where created is not null limit 10;

... but the result is only partially satisfying:

       created       |      timestamp      
---------------------+---------------------
 2010-08-29 12:44:05 | 2010-08-29 11:44:05
 2007-06-21 13:49:22 | 2010-06-21 12:49:22
 2007-06-21 15:02:33 | 2010-06-21 14:02:33
 2007-06-21 15:05:26 | 2010-06-21 14:05:26
 1999-09-30 13:00:00 | 2010-09-30 12:00:00
 1997-06-07 13:00:00 | 2010-06-07 12:00:00
 2010-06-15 20:51:01 | 2010-06-15 19:51:01
 2006-08-26 15:33:02 | 2010-08-26 14:33:02
 2009-12-15 11:07:06 | 2010-12-15 11:07:06
 1997-06-28 13:00:00 | 2010-06-28 12:00:00
(10 rows)

As you can see, all timestamps are -1 hour comparing to original created values. What's even more strange is that the one before last one (2010-12-15 11:07:06) is not.

created column is timestamp without time zone type.

Any idea what I did wrong?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

烈酒灼喉 2024-10-14 00:58:16

SQL 的问题在于它不会将日期转换为另一年的日期。它计算创建的和 2010-01-01 的增量并将其转换为日期。所以你实际上并没有删除年份部分,而是计算它是多久之前的。

这是解决该问题的另一种方法。它只会替换年份,而日期的其余部分保持不变。

SELECT TO_TIMESTAMP('2010-' || CAST(EXTRACT(MONTH FROM created) AS VARCHAR) || '-' || CAST(EXTRACT(DAY FROM created) AS VARCHAR) || ' ' || CAST(EXTRACT(HOUR FROM created) AS VARCHAR) ||':'||CAST(EXTRACT(MINUTE FROM created) AS VARCHAR) ||':'|| CAST(EXTRACT(SECONDS FROM created) AS VARCHAR), 'YYYY-MM-dd HH24:MI:SS') AS timestamp FROM table;

您也可以使用子字符串来执行此操作。 TO_TIMESTAMP() 会将日期 2010-02-29 转换为 2010-03-01,因此可以安全使用。

The problem with your SQL is that it does not turn a date into a date in another year. It calculates deltas for created and 2010-01-01 and converts that to a date. So you're not actually removing the year part, but calculating how long ago it was.

Here's another way to approach the problem. It will just replace the year, leaving the rest of the date untouched.

SELECT TO_TIMESTAMP('2010-' || CAST(EXTRACT(MONTH FROM created) AS VARCHAR) || '-' || CAST(EXTRACT(DAY FROM created) AS VARCHAR) || ' ' || CAST(EXTRACT(HOUR FROM created) AS VARCHAR) ||':'||CAST(EXTRACT(MINUTE FROM created) AS VARCHAR) ||':'|| CAST(EXTRACT(SECONDS FROM created) AS VARCHAR), 'YYYY-MM-dd HH24:MI:SS') AS timestamp FROM table;

You could do this with substrings too. TO_TIMESTAMP() will cast the day 2010-02-29 to 2010-03-01, so it's safe to use.

你的呼吸 2024-10-14 00:58:16

这是jmz提到的子串解决方案:

select to_timestamp('2010'||substring(to_char(created, 'yyyy-mm-dd hh24:mi:ss.ms'), 5), 'yyyy-mm-dd hh24:mi:ss.ms')

This is the substring solution jmz mentioned:

select to_timestamp('2010'||substring(to_char(created, 'yyyy-mm-dd hh24:mi:ss.ms'), 5), 'yyyy-mm-dd hh24:mi:ss.ms')
夏见 2024-10-14 00:58:16

谢谢大家, jmz 和 a_horse_with_no_name 解决方案都工作正常。

我还修复了我的解决方案。问题出在 to_timestamp 上,它返回带时区的时间戳,而我期望不带时区的时间戳。添加类型转换就足够了:

select created,cast (created-to_timestamp(''||
    date_part('year', created), 'YYYY')::timestamp without time zone + 
    timestamp '2010-01-01' as timestamp without time zone) 
    from table;

Thanks guys, both jmz and a_horse_with_no_name solutions work fine.

I also fixed my solution. The problem was with to_timestamp which returns timestamp with time zone and I expected timestamp without time zone. It was enough to add a typecast:

select created,cast (created-to_timestamp(''||
    date_part('year', created), 'YYYY')::timestamp without time zone + 
    timestamp '2010-01-01' as timestamp without time zone) 
    from table;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文