我需要对我的数据库执行一些日期时间操作,这需要所有created
个时间戳都在同一年。我尝试了这个查询:
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)
如您所见,与原始created
值相比,所有时间戳均为-1小时。更奇怪的是,前一个(2010-12-15 11:07:06
)之前的那个不是。
created
列为timestamp without time zone
类型。
知道我做错了吗?
答案 0 :(得分:1)
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,因此可以安全使用。
答案 1 :(得分:1)
这是jmz提到的子串解决方案:
select to_timestamp('2010'||substring(to_char(created, 'yyyy-mm-dd hh24:mi:ss.ms'), 5), 'yyyy-mm-dd hh24:mi:ss.ms')
答案 2 :(得分:0)
谢谢大家,jmz和a_horse_with_no_name解决方案都可以正常工作。
我也解决了我的问题。问题是to_timestamp返回timestamp with time zone
而我预期timestamp without time zone
。添加类型转换就足够了:
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;