【问题标题】:How to determine largest resolution of an INTERVAL?如何确定 INTERVAL 的最大分辨率?
【发布时间】:2011-06-16 15:32:22
【问题描述】:

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

  • INTERVAL '100 days and 3 seconds' => 一天
  • TIME '20:05' - TIME '12:01:01' => 小时
  • AGE(NOW(), NOW() - INTERVAL '1 MONTH') => 月

【问题讨论】:

    标签: sql postgresql intervals


    【解决方案1】:

    这个问题不是 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
    

    关于 cmets 的另一个问题:

    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;
    

    【讨论】:

    • 关闭并继续做某事。但是,如原始帖子中所示,我想知道“100 天”是以天为单位指定的,而不是“证明”它以月为单位指定的间隔。
    • 是的,我想。话又说回来,为什么不将类似上述的东西包装到一个函数中,该函数将返回应该选择年或月的日期?
    • 您可以直接比较两个区间。即选择区间1>区间2;您也可以提取 ('epoch',...) ,这将提取自 1970 年 1 月 1 日以来的秒数 +/-。
    • @Denis,我不确定我是否理解您的建议(“应领取年份的返回日”)。 +1,无论如何,你能充实你提出的功能吗?
    • @Scott,不错,但比较两个间隔不会告诉我最大的时间单位:INTERVAL '30 HOUR' 大于 INTERVAL '1 DAY',但比例分别是 HOUR 和 DAY。两者都不会转换为秒。
    【解决方案2】:

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

    请注意您对“一个月”的理解,因为儒略月与 hour 或 minute 不同(例如,二月份有多少天?或者如何year 中有很多天?实际上并不总是 30 或 365,PostgreSQL 会正确更新。根据 IRC 上的一次有趣对话,将 1 month::INTERVAL 添加到 1 月 30 日将导致 2 月的最后一天因为它增加了struct tm 的tm_mon 成员(在这种情况下,回滚到之前的有效日期)。


    啊哈!我现在得到了这个问题(或者至少我是这么认为的)。您正在寻找给定INTERVAL 的最大“非零整数单元”。

    PostgreSQL 没有返回该信息的内置函数。我认为您将不得不链接条件和返回类型。一些例子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 结构是复合的,不是微秒数。否则,日期/时间算法无法合理地处理夏令时变化或不同长度的月份等情况。
    • 您提出了几个优点。让我相应地更新我的帖子。
    • 谢谢,肖恩。我了解存储类型和间隔日期/时间算法。你有这个问题的答案吗?
    • 哦!我现在明白你的问题了。您正在寻找给定INTERVAL 的最大非小数单位,对吗?人力资源管理系统。用建议编辑问题。
    猜你喜欢
    • 2014-09-29
    • 2016-08-01
    • 1970-01-01
    • 2013-04-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-24
    相关资源
    最近更新 更多