date/time 间隔格式是否有名称,如“1h10m”

Is there a name for date/time interval format like "1h10m"

即使在软件之外,以截断的方式传达时间或日期间隔也很常见。例如:1h10m 转换为 "One hour and ten minutes."

这可以抽象为一组规则。例如:日期间隔表示为 _h_m、(等等)的组合,其中 _ 字符表示非负整数或浮点数,它们合计为一个日期间隔对象。

允许混用天数、小时数、分钟数。例如,0.5d1h60m 将是 14h 的同义词。

是否有任何类似的标准定义?

您可以使用时刻:http://momentjs.com/docs/#/durations/

moment.duration(100); // 100 milliseconds
moment.duration(60000).humanize(); // a minute

在上面的链接文档中阅读更多内容。要获取所有单位值,您可能需要使用 ISO8601 格式:

moment.duration(1, 'd').toISOString() // "P1D"

例如,"P3Y6M4DT12H30M5S" 表示持续时间 "three years, six months, four days, twelve hours, thirty minutes, and five seconds"。 直接在http://momentjs.com/docs/#/durations/as-iso-string/

下阅读更多

此标准是 持续时间,由 ISO 8601 定义。 请注意,Interval 是一个不同的概念(也是由同一 ISO 定义的),尽管两者密切相关:

  • A Duration 定义了 amount 的时间(例如“1 小时 10 分钟”或“2 年 3 个月零 4天”)。但它不会告诉您何时开始或结束(“1 小时 10 分钟”相对于什么?)。这只是时间本身。
  • 间隔(引用维基百科)是"the intervening time between two time points"。它有定义的开始和结束日期,但您可以使用 Duration 来定义它,因为它可以有 4 种不同的格式:
    1. 开始和结束,如2007-03-01T13:00:00Z/2008-05-11T15:30:00Z
    2. 开始和持续时间,例如2007-03-01T13:00:00Z/P1Y2M10DT2H30M
    3. 时长和结束,例如P1Y2M10DT2H30M/2008-05-11T15:30:00Z
    4. 仅持续时间,例如 P1Y2M10DT2H30M具有额外的上下文信息

情况 1、2 和 3 是等效的(都有相同的开始和结束日期)。唯一的区别是,在情况 2 和 3 中,持续时间 P1Y2M10DT2H30M 用于计算另一个日期(在情况 2 中,您将其添加到开始日期,而在情况 3 中,您从结束日期中减去它) .


正如您在上面注意到的,Duration 的标准格式是 P[n]Y[n]M[n]DT[n]H[n]M[n]S,其中:

  • P 是放置在持续时间表示开头的持续时间指示符(用于期间)。
  • Y 是年份值后面的年份指示符。
  • M 是月份值后面的月份指示符。
  • W 是周数值后面的周指示符。
  • D 是天数值后面的日期指示符。
  • T 是表示的时间组件之前的时间指示符。
  • H 是小时数值后面的小时指示符。
  • M 是分钟数后的分钟指示符。
  • S 是秒数值之后的第二个指示符。

因此,“1 年零 10 个月”表示为 P1Y10M,“1 小时 10 分钟”表示为 PT1H10M(请注意,需要 T 才能解析1 个月 (P1M) 和 1 分钟 (PT1M) 之间可能存在歧义,因为它们使用相同的字母 M 作为指示符。


正如@MattJohnson 评论的那样,带日期的数学并不总是显而易见的,因此不同持续时间之间的等价性不可能是我们通常期望的。

对于下面的示例,我使用的是 Java 8(只是为了说明持续时间是多么棘手)。请注意,java.time API 使用了 2 个不同的 类(PeriodDuration),但两者的想法是相同的(它们都是时间)。

  • 1个月相当于多少天?这取决于:

    // one month period
    Period oneMonth = Period.parse("P1M");
    // January 1st
    LocalDate jan = LocalDate.of(2016, 1, 1);
    System.out.println(jan); // 2016-01-01
    // January 1st plus 1 month period = February 1st
    LocalDate feb = jan.plus(oneMonth);
    System.out.println(feb); // 2016-02-01
    // February 1st plus 1 month period = March 1st
    LocalDate mar = feb.plus(oneMonth);
    System.out.println(mar); // 2016-03-01
    
    // difference between Jan 1st and Feb 1st = 31 days
    System.out.println(ChronoUnit.DAYS.between(jan, feb)); // 31
    // difference between Feb 1st and Mar 1st = 29 days (2016 is leap year)
    System.out.println(ChronoUnit.DAYS.between(feb, mar)); // 29
    

因此,1 月 1 日 st 加上 1 个月会导致 February 1st - 在这种情况下,1 个月相当于 31 天(A.K.A。添加 1 个月的持续时间 (P1M) 相当于添加 31持续天数 (P31D)),并在 February 1st 上加上 1 个月导致 3月1日st(这里1个月=29天,因为2016年是闰年)

  • 1 天 = 24 小时?不总是。如果涉及 Daylight Saving Time 班次,您会得到奇怪的结果:

    // 1 day period
    Period oneDay = Period.parse("P1D");
    // 24 hours period
    Duration twentyFourHours = Duration.parse("PT24H");
    // in Sao Paulo, summer time starts at Oct 15, at midnight
    // getting a date one day before DST change, at 10:00 AM
    ZonedDateTime z = ZonedDateTime.of(2017, 10, 14, 10, 0, 0, 0, ZoneId.of("America/Sao_Paulo"));
    System.out.println(z); // 2017-10-14T10:00-03:00[America/Sao_Paulo]
    
    // add 1 day - gets the same hour (10:00 AM)
    System.out.println(z.plus(oneDay)); // 2017-10-15T10:00-02:00[America/Sao_Paulo]
    
    // add 24 hours - gets 11:00 AM because of DST shift (at midnight, clocks moved forward 1 hour)
    System.out.println(z.plus(twentyFourHours)); // 2017-10-15T11:00-02:00[America/Sao_Paulo]
    

在圣保罗,2017 年 10 月 15 日,DST 开始(时钟向前移动 1 小时),因此:

  • 如果您将 24 小时 添加到 10 月 14 日th 上午 10 点,您我会在 10 月 15 日 11 上午
  • 但是如果您添加 1 天,您将在 获得 10 月 15th 10上午

因此,在这种情况下,1 天 = 23 小时 - 这意味着添加 1 天的持续时间 (P1D) 相当于添加 23 小时的持续时间 (PT23H)

夏令时结束时则相反:时钟后退1小时,1天相当于25小时。

因此,该标准定义了时间量概念的格式和含义,但不同持续时间之间的等价性将取决于上下文(尽管 1 天并不总是 24 小时听起来不直观,但date/time 数学并不像我们想要的那么明显。