Date and duration arithmetic

Hi,

In Section 2.5 (Arithmetic Expressions) of the XPath 2.0 WD, rule 5
states that if the two operands are of different types, one is
promoted to the type of the other, following the rules in the F&O WD.

How does this fit in with arithmetic involving dates and durations? I
think that this is supposed to be (and should be!) supported by
operators, since the F&O WD defines op:get-duration,
op:get-end-dateTime and op:get-start-dateTime in the 'operators'
namespace.

The arithmetic that seems to make sense to me is more wide-ranging
than these three functions. I'd also like to see:

  duration  +  duration   =>   duration

  duration  -  duration   =>   duration

  duration  *  decimal    =>   duration
  decimal   *  duration   =>   duration

  duration div decimal    =>   duration
  duration div duration   =>   decimal

  duration mod decimal    =>   duration
  duration mod duration   =>   duration

  - duration              =>   duration

From the casting rules in the F&O WD, it looks as if any date or time
data type can be cast to dateTime without problems, so defining these
arithmetic operators would be sufficient to deal with other date and
time formats too.
  
Some examples:

  "Will these two films be able to fit onto my tape?"
     $film1/@duration + $film2/@duration < $tape/@length

  "So how much room do I have left on my tape after this film?"
     $tape/@length - $film/@duration

  "Will the film fit on the tape with long play?"
     $tape/@length * 2 > $film/@duration
  or:
     $tape/@length > $film/@duration div 2

  "How many episodes can I fit on my tape?"
     floor($tape/@length div $episode/@duration)

  "How much room will be left at the end of the tape after I record as
   many episodes as I can?"
     $tape/@duration mod $episode/@duration

Obviously, some of this arithmetic might be troublesome depending on
the form that the duration takes. In particular:

 - duration div decimal
 - duration mod decimal
 - duration div duration
 - duration mod duration
 
If a duration is specified in years and months, it might be hard to
divide it. For example, P2M div 2 is fine, but P1M div 2 is not; P3M
mod P2M is fine, but P3M mod P14D is not. (Actually, similar
considerations apply if you can multiply a duration by a decimal
number, since the decimals might have fractional components.)

It would be helpful if the calculations that can be done were done
without converting the durations to days/hours/minutes/seconds.

For the others, I think there are three options:
  - make it an error
  - convert to a duration using days/hours/minutes/seconds using the
    average year (and month) length (to a certain accuracy)
  - use the duration between the current dateTime and the current
    dateTime plus the relevant duration, which can be calculated in
    terms of days/hours/minutes/seconds (this has the disadvantage of
    potentially being different if the query/transformation is run on
    different days of the year, which could lead to interesting 'phase
    of the moon' bugs :)


While I'm on the subject, I think that xf:add-days() is superfluous if
you allow date + duration. Rather than:

  xf:add-days($date, $days)

you could do:

  $date + concat('P', $days, 'D')

(Assuming that XPath were intelligent enough to notice that the only
 thing that can be added to a date is a duration, and therefore
 converted the string to a duration.)

I think supporting this would be a lot more flexible than just having
xf:add-days (which on top of everything else only works on a date).
  
Cheers,

Jeni
---
Jeni Tennison
http://www.jenitennison.com/

Received on Wednesday, 16 January 2002 15:12:16 UTC