如何确定 INTERVAL 的最大分辨率?

发布于 2024-11-15 18:50:23 字数 222 浏览 2 评论 0原文

如何确定 INTERVAL 值的最大分辨率?例如:

  • INTERVAL '100 天零 3 秒' =>日期
  • 时间 '20:05' - 时间 '12:01:01' =>小时
  • AGE(NOW(), NOW() - INTERVAL '1 MONTH') =>月

How can I determine the largest resolution of an INTERVAL value? For example:

  • INTERVAL '100 days and 3 seconds' => day
  • TIME '20:05' - TIME '12:01:01' => hour
  • AGE(NOW(), NOW() - INTERVAL '1 MONTH') => month

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

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

发布评论

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

评论(2

谜泪 2024-11-22 18:50:23

这个问题并不是 100% 清楚,所以答案可能正是你正在寻找的,也可能不是你正在寻找的,但是......

有一个 justify_interval() 函数,您可能想研究一下。

test=# select justify_interval(INTERVAL '100 days 3 seconds');
    justify_interval     
-------------------------
 3 mons 10 days 00:00:03
(1 row)

test=# select justify_interval(TIME '20:05' - TIME '12:01:01');
 justify_interval 
------------------
 08:03:59
(1 row)

test=# select justify_interval(AGE(NOW(), NOW() - INTERVAL '1 MONTH'));
 justify_interval 
------------------
 1 mon
(1 row)

因为提取年份,然后是月份,然后是日期等,直到您得出非零答案:

test=# select extract('mon' from interval '3 mons 10 days 00:00:03');
 date_part 
-----------
         3

在评论中回复您的其他问题:

create function max_res(interval) returns interval as $
select case
       when extract('year' from justify_interval($1)) > 0 or
            extract('mon' from justify_interval($1)) > 0 or
            extract('day' from justify_interval($1)) > 0
       then '1 day'
       when extract('hour' from justify_interval($1)) > 0
       then '1 hour'
       when ...
       end;
$ language sql immutable strict;

The question isn't 100% clear so the answer may or may not be exactly what you're looking for, but...

There is a justify_interval() function, which you might want to look into.

test=# select justify_interval(INTERVAL '100 days 3 seconds');
    justify_interval     
-------------------------
 3 mons 10 days 00:00:03
(1 row)

test=# select justify_interval(TIME '20:05' - TIME '12:01:01');
 justify_interval 
------------------
 08:03:59
(1 row)

test=# select justify_interval(AGE(NOW(), NOW() - INTERVAL '1 MONTH'));
 justify_interval 
------------------
 1 mon
(1 row)

For there extract the year, then month, then day, etc. until you come up with a non-zero answer:

test=# select extract('mon' from interval '3 mons 10 days 00:00:03');
 date_part 
-----------
         3

Re your other question in comments:

create function max_res(interval) returns interval as $
select case
       when extract('year' from justify_interval($1)) > 0 or
            extract('mon' from justify_interval($1)) > 0 or
            extract('day' from justify_interval($1)) > 0
       then '1 day'
       when extract('hour' from justify_interval($1)) > 0
       then '1 hour'
       when ...
       end;
$ language sql immutable strict;
玉环 2024-11-22 18:50:23

INTERVAL 是 12 个字节,并且是包含月、日和微秒的结构,范围为 +/- 178000000 年。由于它存储此信息的方式,它的最大大小始终固定为 178000000 年。

请小心理解“一个月”,因为儒略月不是像小时分钟那样的常量(例如,有多少天)二月?或者一年有多少天?实际上并不总是 30 或 365,PostgreSQL 根据 IRC 上的有趣对话正确更新了内容,添加了 1 个月<。 /code>::到一月的间隔 因为它会增加 struct tm 的 tm_mon 成员(在这种情况下,会回滚到之前的有效日期)。


30 号将导致 2 月的最后一天, 您正在寻找给定的 INTERVAL 的最大“非零整数单位”。

我现在得到了这个问题(或者至少我这么认为) 。 我认为在返回该信息的函数中。您将必须链接条件类型和返回类型一些示例 PL 代码:

t := EXTRACT(EPOCH FROM my_time_input);
IF t >= 31104000 THEN
  RETURN 'year';
ELSIF t >= 2592000 THEN
  RETURN 'month';
ELSIF t >= 604800 THEN
  RETURN 'week';
ELSIF t >= 86400 THEN
  RETURN 'day';
ELSIF t >= 3600 THEN
  RETURN 'hour';
ELSIF t >= 60 THEN
  RETURN 'minute'
ELSIF t > 1 THEN
  RETURN 'seconds';
ELSIF t == 1 THEN
  RETURN 'second';
ELSE
  RETURN resolve_largest_sub_second_unit(my_time);
END IF;

INTERVAL is 12 bytes and is a struct containing months, days and microseconds and has a range of +/- 178000000 years. It always has a fixed max size of 178000000 years due to the way that it stores this information.

Be careful with your understanding of "a month" because the Julian month is not a constant in the same way that an hour or a minute is (e.g. how many days are in the month of February? Or how many days are there in a year? It's not always 30 or 365 in reality and PostgreSQL updates things correctly. per an interesting conversation on IRC, Adding 1 month::INTERVAL to January 30th will result in whatever the last day of February because it increments the tm_mon member of struct tm (and in this case, rolls back to the previous valid date).


Ah ha! I get the question now (or at least I think so). You're looking to determine the largest "non-zero integer unit" for a given INTERVAL.

PostgreSQL doesn't have a built-in function that returns that information. I think you're going to have to chain a conditional and return type. Some example PL code:

t := EXTRACT(EPOCH FROM my_time_input);
IF t >= 31104000 THEN
  RETURN 'year';
ELSIF t >= 2592000 THEN
  RETURN 'month';
ELSIF t >= 604800 THEN
  RETURN 'week';
ELSIF t >= 86400 THEN
  RETURN 'day';
ELSIF t >= 3600 THEN
  RETURN 'hour';
ELSIF t >= 60 THEN
  RETURN 'minute'
ELSIF t > 1 THEN
  RETURN 'seconds';
ELSIF t == 1 THEN
  RETURN 'second';
ELSE
  RETURN resolve_largest_sub_second_unit(my_time);
END IF;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文