例子:
- 如果当前时间是 2018-05-17 22:45:30 并且期望的时间间隔是
INTERVAL '5 minute'
,那么期望的输出是 2018-05-17 22:50:00。 - 如果当前时间是 2018-05-17 22:45:30 并且期望的时间间隔是
INTERVAL '10 minute'
,那么期望的输出是 2018-05-17 22:50:00。 - 如果当前时间是 2018-05-17 22:45:30 并且期望的时间间隔是
INTERVAL '1 hour'
,那么期望的输出是 2018-05-17 23:00:00。 - 如果当前时间是 2018-05-17 22:45:30 并且期望的时间间隔是
INTERVAL '1 day'
,那么期望的输出是 2018-05-18 00:00:00。
假设数据类型
timestamp
.date
或的某些细节不同timestamptz
。任何时间间隔的通用解决方案都可以根据纪元值和整数除法进行截断。涵盖了您的所有示例。
你的任务的特殊困难:你想要天花板,而不是地板(这更常见)。小心上下限以避免极端情况错误:您不想增加确切的底值。(或者我假设。)
对于内置的常见时间间隔
date_trunc()
(例如1 hour
和1 day
您的示例),您可以使用快捷方式。天数的定义取决于会话的时区设置 withtimestamptz
(但不是 withtimestamp
)。一个自然的选择是 with
ceil()
。在我的测试中有点慢,但更干净。简短的演示
'5 min'计算的“技巧”是在截断前减去1 µs的最小时间间隔,然后加上相应的时间间隔以有效地得到上限。
EXTRACT()
返回时间戳中的秒数,一个double precision
小数位到微秒的数字。我们需要trunc()
,因为plain cast tointeger
会四舍五入,而我们需要截断。这样我们就可以避免增加恰好落在上界的时间戳。不过,它有点脏,因为最小时间间隔是当前 Postgres 版本的实现细节。不过改变的可能性很小。有关的:
'10 min'计算更简单
ceil()
,我们不需要通过减去 1 µs 来移动边界。清洁器。但是ceil()
在我的测试中稍微贵一点。扩展测试用例
db<>在这里摆弄
我为全天添加了一个替代快捷方式:
ts1::date + 1
. 演员表date
截断到一整天,我们可以加integer
1 来增加一天。函数包装
您后来透露您与 合作,因此我们可以从表达式
timestamptz
中删除。AT TIME ZONE
在我的测试中,声明函数
STABLE
产生了最佳性能,因为它允许函数内联。我本来希望IMMUTABLE
是最好的,但是该声明对内部允许内联的内容更加挑剔。有关的:在我的测试中快一点:
更清洁的国际海事组织:
称呼:
为方便起见,您可以使用替代方法重载每个函数
interval
as$2
:只需使用提取的秒数调用第一个版本。然后你也可以调用:
以每 3 个案例为例:
所以基本上在
你应该更换:
当然替换
now()
为您正在处理的时间戳。这可以在根据您提供的间隔值和步骤为您的特定时间戳创建的函数中抽象出来。
不确定是否了解您想要的确切截断,因此您可能需要替换
round
为ceil
.假设
INTEGER_DATETIMES
(构建选项)这几年来一直是时间戳存储的默认方法。您可以创建一个从
timestamp
(或timestamp with timezone
) 到的转换bigint
,然后将它们作为整数的微秒数进行操作2000-01-01 00:00
,然后再转换回timestamp
(with timezone
)您现在可以使用整数运算(如
/
.向前推进到下两周:
所以
免责声明,这仅适用于固定大小的间隔,不规则大小的间隔,如 'month' 和 'year' 将被折叠成 '30 days' 和 '365.25 days' 。
(ts>0)::int
需要,而不是1
因为负数向零舍入,所以不需要增量。(从 boolean 到 int 的转换使我们得到 0 或 1 作为结果)