PostgreSQL中的时间戳差异(以小时为单位)

90

是否有类似于MySQL的TIMESTAMPDIFF()函数在PostgreSQL中?我知道可以通过减去两个时间戳来得到PostgreSQL的INTERVAL。但我只想获取以整数表示的两个时间戳之间的小时差异。

TIMESTAMPDIFF(HOUR, links.created, NOW())

我只需要以整数表示的两个时间戳之间的小时差异。

这个解决方案适用于我:

SELECT "links_link"."created",
"links_link"."title",
(EXTRACT(EPOCH FROM current_timestamp - "links_link"."created")/3600)::Integer AS "age" 
FROM "links_link"
9个回答

121

首先弹出的东西

EXTRACT(EPOCH FROM current_timestamp-somedate)/3600

可能不太美观,但能畅通道路。如果将间隔除以间隔定义,则可能更美观。

编辑:如果你想要大于零,可以使用 abs 或 greatest(...,0),具体取决于你的意图。

编辑++:我之所以没有使用 age 是因为 age 只有一个参数,引用文档:“从当前日期(午夜)减去”。这意味着除非在午夜运行,否则您无法获得准确的“年龄”。现在这里快到凌晨1点了:

select age(current_timestamp);
       age        
------------------
 -00:52:40.826309
(1 row)

43

在PostgreSQL中获取时间戳大于日期的字段:

SELECT * from yourtable 
WHERE your_timestamp_field > to_date('05 Dec 2000', 'DD Mon YYYY');

在postgresql中,从时间戳中减去分钟:

SELECT * from yourtable 
WHERE your_timestamp_field > current_timestamp - interval '5 minutes'

在PostgreSQL中从时间戳减去小时数:

SELECT * from yourtable 
WHERE your_timestamp_field > current_timestamp - interval '5 hours'

23

迈克尔·克雷林(Michael Krelin)的回答接近但并不完全安全,因为在罕见情况下可能是错误的。问题在于,在PostgreSQL中,区间与夏令时等方面没有上下文关系。区间将月份、天数和秒钟存储为内部事项。在这种情况下,月份并不是问题,因为从两个时间戳中减去只使用天数和秒钟,但“天数”可能会成为问题。

如果您的减法涉及夏令时更改,特定的一天可能会被认为是23或25小时。区间将考虑到这一点,对于了解符号意义下经过的天数很有用,但它将给出实际经过的小时数不正确的数字。区间的时期将只将所有天数乘以24小时。

例如,如果一个完整的“短”日过去了,并且另外一个小时的第二天,区间将记录为一天和一小时。将其转换为纪元/3600就是25小时。但实际上23小时+1小时应该总共是24小时。

因此,更安全的方法是:

(EXTRACT(EPOCH FROM current_timestamp) - EXTRACT(EPOCH FROM somedate))/3600

正如迈克尔在他的跟进评论中提到的那样,您可能还想使用floor()或round()将结果转换为整数值。


12
你可以在时间间隔和时间戳上使用“extract”或“date_part”函数,但我认为这不是你想要的。例如,对于一个间隔为“2天3小时”的间隔,它会返回3。然而,你可以通过指定“epoch”作为所需的时间元素来将间隔转换为秒数:extract(epoch from '2 days, 3 hours'::interval) 返回183600(然后你可以除以3600将秒数转换为小时)。
因此,将所有内容放在一起,你基本上得到了Michael的答案:extract(epoch from timestamp1 - timestamp2)/3600。由于你似乎不关心哪个时间戳先于哪个时间戳,你可能希望用abs来封装它。
SELECT abs(extract(epoch from timestamp1 - timestamp2)/3600)

这确实是最接近的。虽然删除所有小数位不应该是问题,但我对缺少像MySQL这样的内置函数感到相当失望。 - TheLizardKing
由于将进行整数除法,因此不应该有任何小数。 - araqnid
araqnid,我也是这么想的,但我刚试了一下,它确实产生了浮点数。 - Michael Krelin - hacker
如何获取非浮点值?@MichaelKrelin-hacker - Zoran777
@Zoran777 转换成整数? - Michael Krelin - hacker
@MichaelKrelin-hacker,明白了,用round()函数解决了。不管怎样还是谢谢! - Zoran777

10

如何在PostgreSQL中计算时间戳之间的相差秒数?

SELECT (
    (extract (epoch from (
        '2012-01-01 18:25:00'::timestamp - '2012-01-01 18:25:02'::timestamp
                         )
             )
    )
)::integer

输出结果为:

-2

因为时间戳相差两秒。取该数字,除以60得到分钟数,再次除以60得到小时数。


1

extract(hour from age(now(),links.created)) 可以给你一个向下取整的小时差计数。


6
三年过去了,我开始怀疑。另外:如果您尝试执行 select extract(hour from '11 mons 30 days 23:00:00'::interval); ,您将只会得到“23”,而不是以小时表示的11个月、30天和23小时(约为8660小时)。 - A.H.

0
为了避免时代转换,您可以提取天数,将其乘以24,并将小时的提取添加到其中。 < p > < code > select current_timestamp,(current_timestamp - interval '500' hour),(extract(day from(current_timestamp -(current_timestamp - interval '500' hour))* 24)+ extract(hour from(current_timestamp -(current_timestamp - interval '500' hour))));

-1

关于MySQL的timestampdiff我不知道,但对于MSSQL的datediff(hour, start, end),在PostgreSQL中最好的等效方法是floor(extract(epoch from end - start)/3600),因为在MSSQL中选择datediff(hour,'2021-10-31 18:00:00.000', '2021-10-31 18:59:59.999')返回0。


1
目前你的回答不够清晰,请编辑并添加更多细节,以帮助其他人理解它如何回答问题。你可以在帮助中心找到有关如何编写好答案的更多信息。 - hakre

-2

对于很多喜欢利用数据库函数的开发者来说,这可能听起来有些疯狂。

但是在经历了为mysql和postgrsql与php创建和调试应用程序时对比日期函数的问题后,我得出的结论(对于自己而言)是,最简单、最不会出现SQL问题的方法就是不利用任何函数。

为什么?因为如果你在像PHP这样的中间件语言中进行开发,PHP拥有所有这些函数,并且它们很容易像比较整数一样在应用程序代码中实现。PostgreSQL时间戳与UNIX时间戳不相等,MySQL的UNIX时间戳也不等同于PostgresQL或Oracle的时间戳……如果使用数据库时间戳,则在移植时变得更加困难。

所以,只需使用一个整数,而不是时间戳,作为自1970年1月1日午夜以来的秒数,无需考虑数据库时间戳,使用gmdate()存储所有内容为GMT时间,以避免时区问题。

如果您需要从其他数据中搜索、排序或比较日期、月份、年份、星期几或任何其他字段,在您的应用程序中,使用INTEGER类型表示time_day、time_hour、time_seconds或任何要索引的内容将使数据库更平稳、可移植。在大多数情况下,您只需使用一个字段:INTEGER time_created NOT NULL。

(在您的数据库行中使用更多字段是我发现的唯一缺点,但这并不会引起太多麻烦或喝咖啡 :))

php的日期函数非常出色,可以比较日期, 但在mysql或postgresql中比较日期?不需要...使用整数sql比较

我意识到在插入函数中使用CURRENT_TIMESTAMP可能会看起来更容易。哈! 不要被愚弄。

如果time-initialized是postgresql时间戳,则无法执行DELETE FROM SESSION_TABLE WHERE time-initialized < '2 days' 但是你可以这样做:

DELETE FROM SESSION_TABLE WHERE time_initialized < '$yesterday'

只要在php中将$yesterday设置为自1970年以来昨天的秒数即可。

这比在postgresql选择语句中比较时间戳更容易维护会话记录。

SELECT age(),SELECT extract()和asbtime本身就很头疼。这只是我的观点。

您可以使用php日期对象进行加法,减法,<,>等操作

_peter_sysko U4EA Networks,Inc.


5
那么,您如何确保只有有效日期进入您的“整数日期”?您在哪里检查2012-02-29是否有效?您怎么知道时间 02:14 是否适用于3月24日?(提示:由于DST规则,它并不在所有地方都是有效的)。删除很容易:DELETE FROM SESSION_TABLE WHERE time-initialized < current_date - interval '2' day - user330315

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接