Stylus Studio XML Editor

Table of contents

Appendices

E.1 Algorithm

Algorithm

Essentially, this calculation is equivalent to separating D into <year,month> and <day,hour,minute,second> fields. The <year,month> is added to S. If the day is out of range, it is pinned to be within range. Thus April 31 turns into April 30. Then the <day,hour,minute,second> is added. This latter addition can cause the year and month to change.

Leap seconds are handled by the computation by treating them as overflows. Essentially, a value of 60 seconds in S is treated as if it were a duration of 60 seconds added to S (with a zero seconds field). All calculations thereafter use 60 seconds per minute.

Thus the addition of either PT1M or PT60S to any dateTime will always produce the same result. This is a special definition of addition which is designed to match common practice, and -- most importantly -- be stable over time.

A definition that attempted to take leap-seconds into account would need to be constantly updated, and could not predict the results of future implementation's additions. The decision to introduce a leap second in UTC is the responsibility of the [IERS]. They make periodic announcements as to when leap seconds are to be added, but this is not known more than a year in advance. For more information on leap seconds, see [USNavy].

The following is the precise specification. These steps must be followed in the same order. If a field in D is not specified, it is treated as if it were zero. If a field in S is not specified, it is treated in the calculation as if it were the minimum allowed value in that field, however, after the calculation is concluded, the corresponding field in E is removed (set to unspecified).

  • Months (may be modified additionally below)

    • temp := S[month] + D[month]

    • E[month] := modulo(temp, 1, 13)

    • carry := fQuotient(temp, 1, 13)

  • Years (may be modified additionally below)

    • E[year] := S[year] + D[year] + carry

  • Zone

    • E[zone] := S[zone]

  • Seconds

    • temp := S[second] + D[second]

    • E[second] := modulo(temp, 60)

    • carry := fQuotient(temp, 60)

  • Minutes

    • temp := S[minute] + D[minute] + carry

    • E[minute] := modulo(temp, 60)

    • carry := fQuotient(temp, 60)

  • Hours

    • temp := S[hour] + D[hour] + carry

    • E[hour] := modulo(temp, 24)

    • carry := fQuotient(temp, 24)

  • Days

    • if S[day] > maximumDayInMonthFor(E[year], E[month])

      • tempDays := maximumDayInMonthFor(E[year], E[month])

    • else if S[day] < 1

      • tempDays := 1

    • else

      • tempDays := S[day]

    • E[day] := tempDays + D[day] + carry

    • START LOOP

      • IF E[day] < 1

        • E[day] := E[day] + maximumDayInMonthFor(E[year], E[month] - 1)

        • carry := -1

      • ELSE IF E[day] > maximumDayInMonthFor(E[year], E[month])

        • E[day] := E[day] - maximumDayInMonthFor(E[year], E[month])

        • carry := 1

      • ELSE EXIT LOOP

      • temp := E[month] + carry

      • E[month] := modulo(temp, 1, 13)

      • E[year] := E[year] + fQuotient(temp, 1, 13)

      • GOTO START LOOP

Examples:

104 dateTime duration result
center112000-01-12T12:13:14Z center11P1Y3M5DT7H10M3.3S center112001-04-17T19:23:17.3Z
center112000-01 center11-P3M center111999-10
center112000-01-12 center11PT33H center112000-01-13