Hi Edgar,

Edgar Meij wrote:
Months will be converted to days with factor 30.5 which will sure give more
"precise" result


Thought of that as well, but I read this from the DateManip pages:

...it is NOT known how many days form a month. As a result, the part of the
delta containing month/year and the part with sec/min/hr/day must be treated
separately. For example, ``Mar 31, 12:00:00'' plus a delta of 1month 2days
would yield ``May 2 12:00:00''. The year/month is first handled while
keeping the same date. Mar 31 plus one month is Apr 31 (but since Apr only
has 30 days, it becomes Apr 30). Apr 30 + 2 days is May 2. As a result, in
the case where two dates are entered, the resulting delta can take on two
different forms...

Hmm indeed. I've played a little with Date::Manip and this is what I've got:

  date_begin=20040301   date_end=20040401
  DateCalc(mode-0): +0:0:4:3:0:0:0 -> 2678400
  DateCalc(mode-1): +0:1:0:0:0:0:0 -> 2629800
  DateCalc(mode-2): +0:1:0:0:0:0:0 -> 2629800

The usual(1) and business(2) mode returned 1 month which got multiplied by
30.5 days/month, and that gave an error. I'd call it rather insignificant
in this context (response times that span across such large interval).

  date_begin=20040401   date_end=20040501
  DateCalc(mode-0): +0:0:4:2:0:0:0 -> 2592000
  DateCalc(mode-1): +0:1:0:0:0:0:0 -> 2629800
  DateCalc(mode-2): +0:1:0:0:0:0:0 -> 2629800

The error will be approx +/- 0.5 day (or greater when February comes in).
Talking about differences between calculcated seconds for mode-0 (real)
and mode-1 (with months approximated).

For usual things (cases resolved in less than a month) there's no error:

  date_begin=20041129   date_end=20041202
  DateCalc(mode-0): +0:0:0:3:0:0:0 -> 259200
  DateCalc(mode-1): +0:0:0:3:0:0:0 -> 259200
  DateCalc(mode-2): +0:0:0:3:0:0:0 -> 259200

  date_begin=20041029   date_end=20041102
  DateCalc(mode-/): +0:0:0:4:0:0:0 -> 345600
  DateCalc(mode-1): +0:0:0:4:0:0:0 -> 345600
  DateCalc(mode-2): +0:0:0:2:0:0:0 -> 172800
    (-2 due to: All Saints' Day and a Sunday)

  date_begin=20040430   date_end=20040505
  DateCalc(mode-0): +0:0:0:5:0:0:0 -> 432000
  DateCalc(mode-1): +0:0:0:5:0:0:0 -> 432000
  DateCalc(mode-2): +0:0:0:3:0:0:0 -> 259200
        (-2 due to: Labour Day and a Sunday)

  date_begin=20040330   date_end=20040505
  DateCalc(mode-/): +0:0:5:1:0:0:0 -> 3110400
  DateCalc(mode-1): +0:1:0:5:0:0:0 -> 3061800
  DateCalc(mode-2): +0:1:0:3:0:0:0 -> 2889000

The question is: does it matter? It's an error of less than 5% on large
intervals which will be extremely rare (I hope), and as such removed
from statistical analysis as extremes (to prevent them from spoiling
bell shaped normal-like distribution curve).

If it does, how can we improve precision on that? The obvious answer is
to use all three modes: business, usual and precise and determine is
there a difference between the first two, and if there is -- break the
interval into months and calculate real length of each in a loop.
But, would it make more sense? For me, business month is no different
than real month. It only matters when a weekend cuts in in mid-sized
intervals of time.

In the attachment is the Perl script which I used for testing.

Kind Regards,

Damir

#!/usr/bin/perl -w

use strict;
use warnings;
use Date::Manip;

my ($date_a, $date_b, $delta, $err, $sec);

$date_a = ParseDate('2004-10-29 11:59:59')
  or die "Date A bad!\n";

$date_b = ParseDate('2004-11-02 11:59:59')
  or die "Date B bad!\n";

print "\n  date_begin=$date_a  date_end=$date_b\n";

$delta = DateCalc($date_a,$date_b,\$err)
  or die "Failed DateCalc(/):$err, $!";
$sec = interval_to_sec($delta);
print "  DateCalc(mode-0): $delta -> $sec\n";

$delta = DateCalc($date_a,$date_b,\$err, 1)
  or die "Failed DateCalc(1):$err, $!";
$sec = interval_to_sec($delta);
print "  DateCalc(mode-1): $delta -> $sec\n";

$delta = DateCalc($date_a,$date_b,\$err, 2)
  or die "Failed DateCalc(2):$err, $!";
$sec = interval_to_sec($delta);
print "  DateCalc(mode-2): $delta -> $sec\n";


# parse interval string and yield seconds
sub interval_to_sec {
    my ($intv) = @_;
    my ($sec) = 0;
    my $sign = ($intv =~ /^-/) ? -1 : 1;
    my @f = reverse(split(/:/, $intv));
    # use just 5 least significant fields
    $sec  = $f[0];
    $sec += $f[1] * 60;
    $sec += $f[2] * 3600;
    $sec += $f[3] * 86400;
    $sec += $f[4] * 604800;   # 7 days
    $sec += $f[5] * 2629800;  # 30.4 days (365.25 / 12)
    $sec += $f[6] * 31557600; # 365.25 days (Julian year)
    return $sign * $sec;
}
_______________________________________________
OTRS mailing list: otrs - Webpage: http://otrs.org/
Archive: http://lists.otrs.org/pipermail/otrs
To unsubscribe: http://lists.otrs.org/cgi-bin/listinfo/otrs
Support oder Consulting für Ihr OTRS System?
=> http://www.otrs.de/

Reply via email to