开发者

How to determine largest resolution of an INTERVAL?

开发者 https://www.devze.com 2023-03-13 06:36 出处:网络
How can I determine the largest resolution of an INTERVAL value?For example:开发者_如何学JAVA INTERVAL \'100 days and 3 seconds\' => day

How can I determine the largest resolution of an INTERVAL value? For example:开发者_如何学JAVA

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


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;


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;
0

精彩评论

暂无评论...
验证码 换一张
取 消