[Fwd: DateTime::Duration comparisions]

2003-11-12 Thread Max Maischein
This was originally to Dave directly. A second mail with a tentative 
patch that somewhat "fixes" the problem discussed below follows in a 
second mail (that I also sent to Dave directly and will forward 
separately). Please comment but CC me, as I don't follow the list!

-max

 Original Message 
Subject: DateTime::Duration comparisions
Date: Tue, 11 Nov 2003 14:49:04 +0100
From: Max Maischein <[EMAIL PROTECTED]>
To: [EMAIL PROTECTED]
Hello Dave,

I just dabbled a bit with DateTime, comparisions and
DateTime::Durations, and I found some things that I don't understand or
did not find in the documentation:
The delta_* methods are not really usefull, since in 90% of the time, I
just want to know if one duration is longer than another - having to do
several comparisions just to find that out is tedious.
I saw in the CHANGES file that you added some other delta_* methods, but
didn't find them in the documentation, so I don't know about these, and
was too lazy to delve into the source for this :-)
I wrote a test file that shows some ugly bugs when dealing with my naive
comparision, most notably that ($dt-$dt)->is_zero() is false. I don't
know why you implemented is_zero() that way, so I can't propose any good
change. My approach would be to make is_zero() not only check the sign
but also check whether all values are zero.
I wrote a simple DateTime::Duration comparision and hacked it into
DateTime::Duration, but my tests fail and I don't understand enough of
the DateTime mechanics to fix them. I saw some references to the
DateTime::Duration problems on the mailing list, but I saw that you
considered removing the comparision operators completely from
DateTime::Duration - I think this would be bad, but I only ended up
looking at DateTime::Duration, as I could not find an easy way to look
at two DateTime objects and find out which one was later, as comparision
for those also isn't implemented (or, once again, I'm too stupid to read
the docs properly).
Can you please take a look at my comparision patch, the included tests
(especially the is_zero() test is bothering me), and tell me where I am
wrong :-)
Thanks for writing DateTime,
-max
--- DateTime.pm
sub _cmp_datetime {
  my ($left,$right,$reverse) = @_;
  ($left,$right) = ($right,$left) if $reverse;
  my $diff = $right - $left;
  warn sprintf "Left  is  %s days and %s minutes.\n",
$left->delta_days,  $left->delta_minutes;
  warn sprintf "Right is  %s days and %s minutes.\n",
$right->delta_days, $right->delta_minutes;
  warn "positive"
if $diff->is_positive;
  warn "negative"
if $diff->is_negative;
  return 0 if $diff->is_zero;
  return 1 if $diff->is_positive;
  return -1 if $diff->is_negative;
  die "This should never happen";
};
---
The test file
---
#!/usr/bin/perl -w
use strict;
use Test::More tests => 7;
use DateTime;
use Data::Dumper;
my $one_hour = DateTime::Duration->new( hours => 1  );

my $one_day_plus_something = DateTime->from_epoch(epoch =>
24*3600+19*60) - DateTime->from_epoch( epoch => 0);
ok( $one_day_plus_something > $one_hour, "One day plus something takes
longer than one hour" )
  or dump_duration( $one_day_plus_something, $one_hour);
is( $one_hour, $one_hour, "One hour equals itself" )
  or dump_duration($one_hour);
ok( $one_hour == $one_hour, "One hour equals itself (via ==)" )
  or dump_duration($one_hour);
is( $one_day_plus_something, $one_day_plus_something, "One day plus
something equals itself" )
  or dump_duration($one_day_plus_something);
ok( ($one_day_plus_something - $one_day_plus_something)->is_zero, "A
difference subtracted from itself is zero" )
  or dump_duration($one_day_plus_something - $one_day_plus_something);
ok( $one_day_plus_something == $one_day_plus_something, "One day plus
something equals itself (via ==)" )
  or dump_duration($one_day_plus_something);
ok( $one_hour < $one_day_plus_something, "One hour is shorter than one
day plus something" );
sub dump_duration {
  diag Dumper($_) for @_;
};





Re: [Fwd: DateTime::Duration comparisions]

2003-11-12 Thread Dave Rolsky
On Tue, 11 Nov 2003, Max Maischein wrote:

> I saw in the CHANGES file that you added some other delta_* methods, but
> didn't find them in the documentation, so I don't know about these, and
> was too lazy to delve into the source for this :-)

These are for DateTime objects.  I'm now regretting the fact that both
classes have delta_* methods.  Sigh ...

> I wrote a test file that shows some ugly bugs when dealing with my naive
> comparision, most notably that ($dt-$dt)->is_zero() is false. I don't
> know why you implemented is_zero() that way, so I can't propose any good
> change. My approach would be to make is_zero() not only check the sign
> but also check whether all values are zero.

Yeah, the is_* bits for durations are all screwed up.  I'm considering
removing them, because I'm not sure we can fix them and still do
interesting thing with durations.

> DateTime::Duration problems on the mailing list, but I saw that you
> considered removing the comparision operators completely from
> DateTime::Duration - I think this would be bad, but I only ended up

DateTime::Duration has never had comparison methods or overloading, so
this would be difficult to remove ;)

> looking at DateTime::Duration, as I could not find an easy way to look
> at two DateTime objects and find out which one was later, as comparision
> for those also isn't implemented (or, once again, I'm too stupid to read
> the docs properly).

Now I'm really confused.  DateTime.pm objects have _always_ had a compare
method, plus they overload comparison operators.


-dave

/*===
House Absolute Consulting
www.houseabsolute.com
===*/


Re: [Fwd: DateTime::Duration comparisions]

2003-11-13 Thread Max Maischein
(I am too stupid - I forgot to CC the list)

 Original Message 
Subject: Re: [Fwd: DateTime::Duration comparisions]
Date: Thu, 13 Nov 2003 10:16:25 +0100
From: Max Maischein <[EMAIL PROTECTED]>
To: Dave Rolsky <[EMAIL PROTECTED]>
References: <[EMAIL PROTECTED]> 
<[EMAIL PROTECTED]>

Dave Rolsky wrote:
I wrote a test file that shows some ugly bugs when dealing with my naive
comparision, most notably that ($dt-$dt)->is_zero() is false. I don't
know why you implemented is_zero() that way, so I can't propose any good
change. My approach would be to make is_zero() not only check the sign
but also check whether all values are zero.


Yeah, the is_* bits for durations are all screwed up.  I'm considering
removing them, because I'm not sure we can fix them and still do
interesting thing with durations.
At least the is_zero thing can easily be fixed. For the other is_*
methods, only my ugly approximation or some other threshold-based
approach can be made. I now understand some of the problems you face,
but I still think that a ::Duration should DWIM as far as possible.
looking at DateTime::Duration, as I could not find an easy way to look
at two DateTime objects and find out which one was later, as comparision
for those also isn't implemented (or, once again, I'm too stupid to read
the docs properly).
Now I'm really confused.  DateTime.pm objects have _always_ had a compare
method, plus they overload comparison operators.
Somehow I must have been really stupid that day, as now, DateTime
comparision works ...
  perl -MDateTime -le
"$a=DateTime->from_epoch(epoch=>0);$b=DateTime->now(); print
$a>$b?'a>b':''; print $a<$b?'a
I think my problem arose because I tried to check whether the distance
between two points in time was larger than 30 minutes, which meant that
I had to compare two DateTime::Duration objects, which isn't/wasn't
possible. More on this in the next mail :-)
-max




Re: [Fwd: DateTime::Duration comparisions]

2003-11-14 Thread Jonathan Swartz
I guess this boils down to four choices:

1) give an arbitrary answer
2) give a reasonable answer that may depend on the current time (add both
durations to the current time and compare the resulting times)
3) give an answer if it is correct for all times, throw an exception
otherwise
4) always throw an exception

The current behavior is (1). I still favor (2), because it never throws an
exception. The problem with (3) is that if you write code that compares
arbitrary durations, it will work most of the time (e.g. during testing) but
will occasionally throw an exception (e.g. once you're in the wild). It also
seems more complicated to implement and document, though maybe not by much.

Jon

- Original Message -
From: "Doug Treder" <[EMAIL PROTECTED]>
To: <[EMAIL PROTECTED]>
Cc: "Jonathan Swartz" <[EMAIL PROTECTED]>; "Dave Rolsky" <[EMAIL PROTECTED]>;
"Max Maischein" <[EMAIL PROTECTED]>; "datetime @ perl . org"
<[EMAIL PROTECTED]>
Sent: Friday, November 14, 2003 4:49 PM
Subject: Re: [Fwd: DateTime::Duration comparisions]


> The "fuzzy logic" that was being described earlier on the list is more
> attractive.  There are definitely edge cases where two durations cannot
> be compared and should throw exception.  But  most of the spectrum is
> actually comparable, depending on the units being compared: 30 seconds
> is always less than 31 seconds, 1 day is always less than 1 month.  In
> fact just taking the worst case for every unit still leaves most of the
> spectrum comparable.  You can determine a span of "worst fuzziness" for
> each unit (months are fuzzy for at least 3 days, possibly 4) and throw
> exceptions if the duration comes within that range.
>
> -D
>
>
> [EMAIL PROTECTED] wrote:
>
> >Jonathan Swartz <[EMAIL PROTECTED]> wrote:
> >
> >
> >>Yes, that is technically true. However, it
> >>
> >>
> >is -so- intuitive and
> >
> >
> >>tempting to
> >>compare two durations (because other
> >>
> >>
> >mathemetical operators work, and
> >
> >
> >>because you can compare two datetimes),
> >>
> >>
> >that IMO it would be
> >
> >
> >>appropriate to
> >>specifically overload those operators to
> >>
> >>
> >throw an error. Or to have
> >
> >
> >>it
> >>compare them anchored at the current time.
> >>
> >>
> >Anything but letting it
> >
> >
> >>compare
> >>the reference values.
> >>
> >>
> >
> >I think Jon has a very astute point here. I
> >used to just compare durations without
> >thinking. It was only when I started getting
> >strange errors that I looked through the
> >module and realised there was no comparison
> >overloads.
> >
> >If you look at 'closest' in the old
> >Event::Easter you'll see this. Unfortunately
> >the tests provided returned the right thing
> >when comparing the references. Of course this
> >was just a fluke and only allowed the tests
> >to pass.
> >
> >I would prefer to see these overloads die,
> >preferably painfully, so that people realise
> >they can't overload duration comparissons.
> >
> >However, at the same time, I'd like to
> >implement $dtdur->compare($dtdur2, $basedt)
> >which would return the normal -1, 0 or 1 from
> >$basedt. If $basedt is not set, then
> >DateTime->now is used.
> >
> >This would mean we could die with
> >"DateTime::Duration cannot overload
> >comparison operators. For more information
> >see perldoc DateTime::Duration. To compare
> >durations see the compare method in the same
> >document".
> >
> >Cheers!
> >Rick
> >
> >
> >
> >
> >
>
>



Re: [Fwd: DateTime::Duration comparisions]

2003-11-14 Thread Dave Rolsky
On Fri, 14 Nov 2003, Jonathan Swartz wrote:

> I guess this boils down to four choices:
>
> 1) give an arbitrary answer
> 2) give a reasonable answer that may depend on the current time (add both
> durations to the current time and compare the resulting times)
> 3) give an answer if it is correct for all times, throw an exception
> otherwise
> 4) always throw an exception
>
> The current behavior is (1). I still favor (2), because it never throws an
> exception. The problem with (3) is that if you write code that compares
> arbitrary durations, it will work most of the time (e.g. during testing) but
> will occasionally throw an exception (e.g. once you're in the wild). It also
> seems more complicated to implement and document, though maybe not by much.

I agree.  Working quietly most of the time and occasionally throwing an
exception that will be hard to explain ("Duration exceeds fuzzy comparison
limits") is not a good behavior.

I don't mind the idea of adding a compare() class method that accepts a
base datetime and uses DateTime->now, per Rick's suggestion.

Overloading comparison to explicitly die also seems reasonable.  It's
annoying the first time it happens, but as I said in my "Industrial
Strength Perl" presentation, it's better to die before you've screwed up
all your data than afterwards.


-dave

/*===
House Absolute Consulting
www.houseabsolute.com
===*/


Re: [Fwd: DateTime::Duration comparisions]

2003-11-14 Thread Joshua Hoblitt
On Fri, 14 Nov 2003, Dave Rolsky wrote:

> I don't mind the idea of adding a compare() class method that accepts a
> base datetime and uses DateTime->now, per Rick's suggestion.

I proposed something just short of this *months* ago and nobody even responded to my 
RFC.

DT::Q could be either used by this 'compare' class or be extended to include 
comparison operators.  Two DT::Q objects could be compared deterministically.

-J

--
> From [EMAIL PROTECTED] Fri Nov 14 17:40:01 2003
> Date: Sun, 17 Aug 2003 16:02:09 -1000 (HST)
> From: Joshua Hoblitt <[EMAIL PROTECTED]>
> To: DateTime <[EMAIL PROTECTED]>
> Subject: [RFC] DateTime::Quantitative was Re: Subtraction Broken?
>
> I'm not too sure about the name.  I wanted to make sure it couldn't be confused with 
> DateTime::Duration and still be meaningful.
>
> Is this the best approach?  I can't see this type of functionality being cleanly 
> implemented in DT::Duration.
>
> -J
>
> --
> DateTime::Quantitative - returns duration values normalized to a fixed point in time
>
> ->new( datetime => $dt, duration => $dtd )
>
> Like DT::Duration it would provide:
>
> ->years;
> ->months;
> ->weeks;
> ->days;
> ->hours;
> ->minutes;
> ->seconds;
> ->nanoseconds;
> ->sign;
> ->is_positive
> ->is_zero
> ->is_negative
>
> In addition:
>
> ->clone
>
> ->datetime
> ->duration
>
> returns the component object
>
> If DT::Q is mutable (might not be a good idea) it would also include:
>
> ->set_datetime( object => $dt )
> ->set_duration( object => $dtd )
>
> updates the component object
>
> No math operators would be overloaded but perhaps stringification would be allowed.
>


Re: [Fwd: DateTime::Duration comparisions]

2003-11-15 Thread Rick Measham
Doug Treder wrote:
> The "fuzzy logic" that was being described earlier on the list is more
> attractive.  There are definitely edge cases where two durations
cannot
> be compared and should throw exception.  But  most of the spectrum is
> actually comparable, depending on the units being compared: 30 seconds
> is always less than 31 seconds, 1 day is always less than 1 month.  In
> fact just taking the worst case for every unit still leaves most of
the
> spectrum comparable.  You can determine a span of "worst fuzziness"
for
> each unit (months are fuzzy for at least 3 days, possibly 4) and throw
> exceptions if the duration comes within that range.


I really, really, really don't like this. If I get two durations I want
to be able to compare them or not compare them. I don't want to have to
handle the 'fuzzy' bits. Here's how you'd have to handle 'might
compare':

my $cmp = eval{ ($dtdurr1 < $dtdurr2) };

if ($@) {
$cmp = DateTime->now()->add_durration( $dt_durr1 )
<
   DateTime->now()->add_durration( $dt_durr2 );
$cmp_from_now++;
}

if ($cmp) {
print "dtdurr2 is the larger";
print ($cmp_from_now) 
   ? " using now() as a base"
   : " for any base";
}


__END__

However, to compare with compare() is much easier:

if ($dtdurr1->compare($dtdurr2) == -1) {
print "dtdurr2 is the larger using now() as a base"
}


And, to make comparing easier, we could add is_less_than and
is_greater_than and is_equal_to:

sub is_greater_than { (return shift->compare( @_ ) ==  1) }
sub is_less_than{ (return shift->compare( @_ ) == -1) }
sub is_equal_to { (return shift->compare( @_ ) ==  0) }



Of course, you could always write DateTime::Utils::DurationFuzzyCompare
which could either take a Duration for its new() parameter, or could be 
Class::ClassDecorator on top of DateTime::Duration.

Cheers!
Rick



Re: [Fwd: DateTime::Duration comparisions]

2003-11-15 Thread Max Maischein
Dave Rolsky wrote:
I guess this boils down to four choices:

1) give an arbitrary answer
2) give a reasonable answer that may depend on the current time (add both
durations to the current time and compare the resulting times)
3) give an answer if it is correct for all times, throw an exception
otherwise
4) always throw an exception
The current behavior is (1). I still favor (2), because it never throws an
exception. The problem with (3) is that if you write code that compares
arbitrary durations, it will work most of the time (e.g. during testing) but
will occasionally throw an exception (e.g. once you're in the wild). It also
seems more complicated to implement and document, though maybe not by much.


I agree.  Working quietly most of the time and occasionally throwing an
exception that will be hard to explain ("Duration exceeds fuzzy comparison
limits") is not a good behavior.
I agree, while it would be explainable in hindsight, it's not good to 
have scripts blow up because they hit boundaries, even if the 
programmers should rethink his algorithm...

I don't mind the idea of adding a compare() class method that accepts a
base datetime and uses DateTime->now, per Rick's suggestion.
I wouldn't want to use DateTime->now(), but a global DateTime object 
that is initialized at script startup - that way you always get 
consistent comparisions throughout the run of the script (much like -M).

Overloading comparison to explicitly die also seems reasonable.  It's
annoying the first time it happens, but as I said in my "Industrial
Strength Perl" presentation, it's better to die before you've screwed up
all your data than afterwards.
Overloading comparision to die might be sensible if it were clear that 
the situations where comparision is meaningless were happening often, 
but I'm not convinced - in most cases, there is a sensible way of 
comparing two DT::Ds even without a reference point in time, and with a 
reference point in time the dubious situations become even fewer - so 
I'm in favour of (2), as this solves the problem I am interested in (and 
what good are durations if you can't look at two and decide which one is 
longer?)

-max

PS: I didn't know that this was some hornets nest I stirred up again - 
it was just a problem I wanted to solve for myself ...



Re: [Fwd: DateTime::Duration comparisions]

2003-11-15 Thread Dave Rolsky
On Sat, 15 Nov 2003, Max Maischein wrote:

> PS: I didn't know that this was some hornets nest I stirred up again -
> it was just a problem I wanted to solve for myself ...

Almost every facet of DateTime stuff is a hornet's nest.  It seems simple
at first, but the deeper you get into it, the weirder it becomes.


-dave

/*===
House Absolute Consulting
www.houseabsolute.com
===*/