The standard for this is a Duration, defined by ISO 8601.
Note that an Interval is a different concept (also defined by the same ISO), although both are closely related:
- A Duration defines an amount of time (like "1 hour and 10 minutes" or "2 years, 3 months and 4 days"). But it doesn't tell you when it starts or ends ("1 hours and 10 minutes" relative to what?). It's just the amount of time, by itself.
- An Interval (quoting wikipedia) is "the intervening time between two time points". It has a defined start and end dates, but you can use a Duration to define it, as it can have 4 different formats:
- Start and end, such as
2007-03-01T13:00:00Z/2008-05-11T15:30:00Z
- Start and duration, such as
2007-03-01T13:00:00Z/P1Y2M10DT2H30M
- Duration and end, such as
P1Y2M10DT2H30M/2008-05-11T15:30:00Z
- Duration only, such as
P1Y2M10DT2H30M
, with additional context information
Cases 1, 2 and 3 are equivalent (all have the same start and end dates). The only difference is that in cases 2 and 3, the duration P1Y2M10DT2H30M
is used to calculate the other date (in case 2, you add it to the start date, and in case 3 you subtract it from the end date).
As you can notice above, the standard format for a Duration is P[n]Y[n]M[n]DT[n]H[n]M[n]S
, where:
- P is the duration designator (for period) placed at the start of the duration representation.
- Y is the year designator that follows the value for the number of years.
- M is the month designator that follows the value for the number of months.
- W is the week designator that follows the value for the number of weeks.
- D is the day designator that follows the value for the number of days.
- T is the time designator that precedes the time components of the representation.
- H is the hour designator that follows the value for the number of hours.
- M is the minute designator that follows the value for the number of minutes.
- S is the second designator that follows the value for the number of seconds.
So, "1 year and 10 months" is represented as P1Y10M
and "1 hour and 10 minutes" is PT1H10M
(note that the T
is required to resolve the potencial ambiguity between 1 month (P1M
) and 1 minute (PT1M
), as they use the same letter M
as designator).
As @MattJohnson commented, the math with dates it's not always obvious, so the equivalence between different durations can't be what we normally expect.
For the examples below, I'm using Java 8 (just to show how durations can be tricky). Note that the java.time
API uses 2 different classes (Period
and Duration
), but the idea for both is the same (they're both amounts of time).
A duration of 1 month is equivalent to how many days? It depends:
// 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
So, adding 1 month to January 1st results in February 1st - in this case, 1 month is equivalent 31 days (A.K.A. adding a 1 month duration (P1M
) is equivalent to adding a 31 days duration (P31D
)), and adding 1 month to February 1st results in March 1st (in this case, 1 month = 29 days, because 2016 is a leap year).
1 day = 24 hours? Not always. If there's a Daylight Saving Time shift involved, you can get strange results:
// 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]
In S?o Paulo, at October 15th, 2017, DST starts (clocks are moved forward by 1 hour), so:
- If you add 24 hours to October 14th at 10 AM, you'll get October 15th at 11 AM
- But if you add 1 day, you'll get October 15th at 10 AM
So, in this case, 1 day = 23 hours - it means that adding a 1 day duration (P1D
) is equivalent to adding a 23 hours duration (PT23H
)
When DST ends, is the opposite: clocks move back 1 hour, and 1 day will be equivalent to 25 hours.
So, the standard defines the format and meaning of the amounts of time concepts, but the equivalence between different durations will depend on the context (although it might sound non-intuitive that 1 day is not always 24 hours, but date/time math is not as obvious as we'd like).