in reply to Unexplained Behavior in Date::Calc

The module is working as advertised. There's this concept out there of performing mathematical operations on non-anchored date fragments which is not really that useful in the real world, presuming you want accurate answers.

When dealing with absolute dates (meaning YMDHMS, rather than non-anchored date fragments) you are better off converting both dates into seconds-since-epoch, computing the delta, then applying this delta (in seconds) to any target dates of interest. (all math happens in the world of seconds).

This is still fraught with potential errors, however, including DST issues and leap-seconds.

Check out the collection of nodes in the Q&A section QandASection: dates and times.

I'd also suggest looking into the Perl DateTime Suite if you're interested in detailed, and correct, date calculations.

Matt

Replies are listed 'Best First'.
Re: Re: Unexplained Behavior in Date::Calc
by Madams (Pilgrim) on Dec 02, 2003 at 01:57 UTC

    I've just got to give you a ++ for the pointer to Perl DateTime Suite,I just browsed it, now I'm gonna try it.

    Also when stating that the module is working as advertised, Delta_DHMS() does, right in its name, tell you that it DOESN'T know or care about years; else it would have been named Delta_YDHMS(). That said all the functions should use absolute dates. (It's a feature;) .)


    _________________

    madams@scc.net

    messaging note:
    s/(Subject:.*)/$1 <pass:SIGUSR2003>/

      Both Delta_DHMS() and Delta_YMDHMS() correspond to their companion functions Add_Delta_DHMS() and Add_Delta_YDHMS(). In both cases, the results from Delta_* can be passed to the Add_Delta_* function, along with the first date, in order to get the second date. Accordingly, the complimentary operation is supported if you reverse the sign of each value of the delta and pass to Add_Delta_* along with the second date.

      From the POD:

      In any case, adding the result of this function to the first date/time + value ($year1,$month1,$day1, $hour1,$min1,$sec1) always gives the se +cond date/time value ($year2,$month2,$day2, $hour2,$min2,$sec2) again +, and adding the negative result (all elements of the result vector n +egated) to the second date/time value gives the first date/time value +.

      As you can see, the specification for what Delta_YMDHMS() and Delta_DHMS() return is defined in terms of complimentary operations, not any particular representation of values. So in your example (hr/day labels fixed):

      Today_and_Now value: 2003-12-1-14-52-15
           End time value: 2004-4-1-0-0-0
      
      Function     |Yrs  |Mons |Days |Hrs  |Mins |Secs
      -------------------------------------------------
      Delta_DHMS   |  N/A|  N/A|  121|    9|    7|   45
      Delta_YMDHMS |    1|   -8|    0|  -14|  -52|  -15
      
      Add_Delta_YMDHMS() (no modulo, no carry):
      
        original: 2003 |  12 |   1 |  14 |  52 |  15
      +    delta:    1 |  -8 |   0 | -14 | -52 | -15
      -------------------------------------------------
             end: 2004 |   4 |   1 |   0 |   0 |   0
      -    delta:    1 |  -8 |   0 | -14 | -52 | -15
      -------------------------------------------------
        original: 2003 |  12 |   1 |  14 |  52 |  15
      
      Add_Delta_DHMS() (modulo, columnar carry, calendrical):
      
            math:|   calendrical   |mod24|mod60|mod60
      -------------------------------------------------
        original:       2003-12-01 |  14 |  52 |  15
      +    delta:              121 |   9 |   7 |  45
      -------------------------------------------------
             end:       2004-04-01 |   0 |   0 |   0
      -    delta:              121 |   9 |   7 |  45
      -------------------------------------------------
        original:       2003-12-01 |  14 |  52 |  15
      
      
      As you can see, there's no actual calendrical or modulo/carrying calculations going on with Delta_YMDHMS(). Delta_DHMS(), on the other hand, does do it that way.

      Nowhere in the documentation does it state that the Delta_* functions perform their arithmetic in the same fashion, or represent their results the same way. They are merely guaranteed to provide symmetry for the Add_Delta_* functions.

      Matt