Read XSLT 2.0 and XPath 2.0 Programmer's Reference, 4th Edition Online
Authors: Michael Kay
The decision to allow arithmetic using the two subtypes
xs:yearMonthDuration
and
xs:dayTimeDuration
, while not allowing it using the parent type
xs:duration
, is slightly perverse, since any
xs:duration
value can be decomposed into an
xs:yearMonthDuration
and an
xs:dayTimeDuration
. But by now, you should be used to the idea that the handling of durations in XML Schema and XPath has a few rough edges.
Let's start by seeing how to add an
xs:dayTimeDuration
to an
xs:dateTime
. This is reasonably straightforward. An
xs:dayTimeDuration
represents an exact number of seconds. When you add this to an
xs:dateTime
you get the value that represents the instant in time that is this number of seconds later (or earlier, if the duration is negative) than the original, in the same timezone. (The algorithm ignores the leap seconds that can be inserted arbitrarily into the calendar to handle variations in the earth's speed of rotation.)
If you're adding an
xs:dayTimeDuration
to an
xs:date
, rather than to an
xs:dateTime
, you can get the right answer by considering the
xs:dateTime
at
00:00:00
on the date in question and then ignoring the time part of the result.
If you're adding the duration to an
xs:time
, the result is taken modulo 24 hours. For example,
03:00:00
plus
P1D
is
03:00:00
, and
03:00:00
plus
PT36H
is
15:00:00
.
If you're adding an
xs:yearMonthDuration
to an
xs:date
, the rules are slightly more complicated. What is 31
st
January plus one month? The answer given by the specification is that it is 28
th
February, or 29
th
February if it's a leap year.
Adding an
xs:yearMonthDuration
to an
xs:dateTime
is the same as adding it to the date part of the
xs:dateTime
, and returning the time portion unchanged. Adding an
xs:yearMonthDuration
to an
xs:time
is not allowed, because it would always return the value unchanged.
Duration Plus Duration
You can only add or subtract two durations of the same type. The allowed combinations of operands are:
Operand 1 | Operand 2 | Result |
xs:yearMonthDuration | xs:yearMonthDuration | xs:yearMonthDuration |
xs:dayTimeDuration | xs:dayTimeDuration | xs:dayTimeDuration |
The operator can be either
+
or
-
.
The rules are reasonably obvious (at any rate, they appear to be obvious to the writer of the specification, which simply says that the result is the sum or difference of the two durations). Remember that an
xs:yearMonthDuration
is equivalent to an
xs:integer
number of months, and an
xs:dayTimeDuration
is equivalent to an
xs:decimal
number of seconds. The addition and subtraction of two durations, whether they are positive or negative in sign, thus reduces to simple arithmetic on numbers.
For example, subtracting
PT6H
(6 hours) from
P1D
(one day) gives
PT18H
(18 hours).
Only binary
+
and
-
can be used with durations: the unary
+
and
-
operators, for no particularly good reason, are constrained to work only with numbers. The easiest way to turn a positive duration into an equivalent negative duration is to multiply it by
-1
, as described in the next section.