我正在尝试创建一个显示下半小时时间的函数。
所以当前时间是13:40时,我希望它显示14:00而不是13:30。
我所创造的,完成工作但是在最近的半小时时间,而不是未来最近的时间:
CREATE OR REPLACE FUNCTION round_timestamp(
ts timestamptz
,round_secs int
) RETURNS timestamptz AS $$
DECLARE
_mystamp timestamp;
_round_secs decimal;
BEGIN
_round_secs := round_secs::decimal;
_mystamp := timestamptz 'epoch'
+ ROUND((EXTRACT(EPOCH FROM ts))::int / _round_secs) * _round_secs
* INTERVAL '1 second';
RETURN _mystamp;
END; $$ LANGUAGE plpgsql IMMUTABLE;
有关如何使这项工作显示未来最近的半小时间隔的任何想法?
答案 0 :(得分:1)
为了避免使用epoch和浮点算术,你可以依赖日期算术,还有一个好处是让它更清晰:
create or replace function round_tstz(ts timestamptz)
returns timestamptz
as $$
select date_trunc('hour', $1) +
-- what hour will it be in 30 min?
case date_trunc('hour', $1 + interval '30 min')
-- the same: round to next half hour
when date_trunc('hour', $1) then interval '30 min'
-- not the same: round to next hour
else interval '1 hour'
end;
$$ language sql stable;
# select now()::timestamptz(0);
now
------------------------
2014-12-05 14:34:30+01
(1 row)
# select round_tstz(now()), round_tstz(now() + interval '30 min');
round_tstz | round_tstz
------------------------+------------------------
2014-12-05 15:00:00+01 | 2014-12-05 15:30:00+01
(1 row)
答案 1 :(得分:0)
您可以分别使用ceil()
(or ceiling()
) and floor()
向上和向下舍入。
如果您的函数很简单,您也可以在LANGUAGE SQL
中编写它,这使它更简单/可读(并且解析器也可以计划):
CREATE OR REPLACE FUNCTION round_timestamp(ts timestamptz, round_secs int)
RETURNS timestamptz
LANGUAGE SQL
IMMUTABLE
AS $func$
SELECT timestamptz 'epoch'
+ ceiling(EXTRACT(EPOCH FROM ts) / round_secs)
* round_secs
* INTERVAL '1 second'
$func$;
答案 2 :(得分:0)
琐碎的是,在将其缩放回时间戳之前,在向下舍入的时期加1:
CREATE OR REPLACE FUNCTION round_timestamp(ts timestamptz, round_secs int)
RETURNS timestamptz AS $$
BEGIN
RETURN timestamptz 'epoch'
+ (ROUND((EXTRACT(EPOCH FROM ts))::int / round_secs) + 1) * round_secs
* INTERVAL '1 second';
END; $$ LANGUAGE plpgsql IMMUTABLE;
不需要局部变量。
答案 3 :(得分:0)
您需要将X
分钟添加到时间戳中的当前分钟数M
,其中:
X = 30 - M %30 - 30 *(( M %30)= 0):: int
您将除法的余数从30减去30,然后仅当该余数为0时,减去另外30,以便:保留00和:30值并且不会向上舍入。
例如,如果时间是14:11,那么M = 11,你需要增加19分钟到达14:30(30 - 11%30 = 19),14:47,M = 47,你需要增加13分钟才能达到15:00(30-47%30 = 13)。该规则的唯一例外是剩余部分为0的情况,即小时数,例如14:30,15:00等等 - 这就是公式中最后一个项发挥作用的地方 - 减去30 *的乘积( 0或1,取决于除法的剩余部分为30)。
CREATE FUNCTION round_up(timestamptz) RETURNS timestamptz AS $$
SELECT
$1 + '1 minute'::interval * (
30 - (EXTRACT('minute' FROM $1)::int % 30)
- 30 * ((EXTRACT('minute' FROM $1)::int % 30)=0)::int
);
$$ LANGUAGE sql IMMUTABLE;