Re: DateTime::Duration 'in_units' does not properly normalize units
On Mon, 13 Dec 2004, Joshua Hoblitt wrote: On Mon, 13 Dec 2004, Dave Rolsky wrote: On Mon, 13 Dec 2004, Joshua Hoblitt wrote: It looks like the normalization is hosed. This method, for the nth time, does not convert between units which do not have a fixed conversion rate. Whooo, I seem to have missed the bus here. Wasn't the entire point of ->in_units so people would stop bitching about the other accessors not doing what they had been trained to expect? How is ->in_units possibly useful otherwise? It will convert between _convertible_ units: years <=> months weeks <=> days hours <=> minutes seconds <=> nanoseconds I for one am getting really tired of all the complaints about DT::Duration. Why don't we just add a bunch of accessors, with really verbose names, that return deltas relative to -01-01T00:00:00 and document the hell out of the fact that this is what's going on. e.g. Something like that sounds reasonable. ->estimated_years ->guessed_months ->imperfect_days, ->imprecise_hours ->loose_minutes, ->rough_seconds ->surmised_nanoseconds ->uncertain_years ->unprecise_months ->unscientific_days ->approximate_hours ->relative_minutes ->seconds_relative_to_0 The names need some work ;) -dave /*=== VegGuide.Org Your guide to all that's veg. ===*/
Re: DateTime::Duration 'in_units' does not properly normalize units
On Mon, Dec 13, 2004 at 06:14:12PM -0800, Yitzchak Scott-Thoennes <[EMAIL PROTECTED]> wrote: > On Mon, Dec 13, 2004 at 07:04:23PM -0600, Dave Rolsky <[EMAIL PROTECTED]> > wrote: > > On Mon, 13 Dec 2004, Dave Rolsky wrote: > > > > >>>How can that be sane? So you ask for minutes and you get fractional > > >>>minutes but you ask for seconds and get zero? > > > > > >Cause really it should just blow up when you give it fractional anything. > > > > Or not. Anyone know of a good way to check that a parameter is one of: > > > > - an integer > > int($param) != $param # works even for values greater than max UV ==, not != :) > > > - infinity > > - NaN > > $param - $param != 0; # indicates +/-Inf or NaN > (differentiate between the two: $param != $param ? "nan" : "infinite") > > > keeping in mind that if I regex a very large number it gets converted to a > > string which may be "1.5853e+18"!
Re: DateTime::Duration 'in_units' does not properly normalize units
On Mon, 13 Dec 2004, Tim Jenness wrote: On Mon, 13 Dec 2004, Dave Rolsky wrote: Maybe it could be something like DT::Duration::Fractional? What do others think? A variant of Duration that assumes standard lengths for day, minutes, hour etc, and with a caveat that it will always add seconds when combined with a DateTime object would be great. If this is the route to be taken, it should be sufficient to create a standard DateTime::Duration object (instead of a subclass) with the duration expressed on as seconds/nanoseconds. Then ->in_units would work as you had expected. Am I volunteering...? Are you? :) Cheers, -J --
Re: DateTime::Duration 'in_units' does not properly normalize units
On Mon, 13 Dec 2004, Dave Rolsky wrote: On Mon, 13 Dec 2004, Joshua Hoblitt wrote: It looks like the normalization is hosed. This method, for the nth time, does not convert between units which do not have a fixed conversion rate. Whooo, I seem to have missed the bus here. Wasn't the entire point of ->in_units so people would stop bitching about the other accessors not doing what they had been trained to expect? How is ->in_units possibly useful otherwise? I for one am getting really tired of all the complaints about DT::Duration. Why don't we just add a bunch of accessors, with really verbose names, that return deltas relative to -01-01T00:00:00 and document the hell out of the fact that this is what's going on. e.g. -- ->estimated_years ->guessed_months ->imperfect_days, ->imprecise_hours ->loose_minutes, ->rough_seconds ->surmised_nanoseconds ->uncertain_years ->unprecise_months ->unscientific_days ->approximate_hours ->relative_minutes ->seconds_relative_to_0 . . __ I'd also point out that it probably won't work well with non-integer units. I'm not sure what'll happen when you try to add 160.2 minutes to a DateTime object, but it won't be anything good, I'm sure. How can that be sane? So you ask for minutes and you get fractional minutes but you ask for seconds and get zero? Cause really it should just blow up when you give it fractional anything. The validation spec doesn't limit the input to integers. Either the implementation or the spec needs to be fixed... -- my %p = validate( @_, { years => { type => SCALAR, default => 0 }, months => { type => SCALAR, default => 0 }, weeks => { type => SCALAR, default => 0 }, days=> { type => SCALAR, default => 0 }, hours => { type => SCALAR, default => 0 }, minutes => { type => SCALAR, default => 0 }, seconds => { type => SCALAR, default => 0 }, nanoseconds => { type => SCALAR, default => 0 }, end_of_month => { type => SCALAR, default => undef, regex => qr/^(?:wrap|limit|preserve)$/ }, } ); -- Cheers, -J --
Re: DateTime::Duration 'in_units' does not properly normalize units
On Mon, 13 Dec 2004, Tim Jenness wrote: Thanks for the reply. So are you saying that DateTime::Duration shouldn't really be used at all if I have units of fractional anything and want to convert that to a duration? I'm supposed to convert it first to hours, minutes and seconds and then instantiate a DateTime::Duration from that? Shouldn't there be DateTime warnings if that is attempted? Yes, yes, and yes, it should, but it doesn't. What I don't understand is why converting a duration from fractional hours, minutes and seconds is not a standard part of the module. It would seem to be an obvious use for it (and I have lots of data sources that use fractional hours or fractional seconds). The problem (as I've reiterated many times) is that the number of seconds per minute is not fixed, nor are the number of hours per day. DateTime::Format::Duration does handle fractional hours, minutes and seconds but I can't see an obvious way to convert a DateTime::Format::Duration object to a DateTime::Duration object without saying something convoluted like: my $dur = DateTime::Duration->new( seconds => DateTime::Format::Duration->new( pattern => '%s')->format_duration_from_deltas( hours => 2.67 )) which can't be the best way of doing this but does result in a Duration object of 9612.2 sec but now I get: hours: 0 minutes: 0 seconds: 9612 nanoseconds: 96120 which also seems bizarre and non-obvious since I would expect in_units('hours') to return '2'. How come seconds from the constructor aren't converted to hours and minutes? See above. I'm not sure what "fixed conversion rate" means in this context but it clearly doesn't mean divide seconds by 3600 to get hours. Yeah, I need to make that clearer. The problem is that with leap seconds, there are a few 3601 second hours out there. As a related aside. What is wrong with addiing 160.2 minutes to a DateTime object? It seems to be a perfectly sensible thing to do if it is first converted to seconds. If you convert the .2 minutes to seconds first, yes, it is perfectly sensible. Sorry to show my ignorance here but I am extremely confused by the fact that I can't come up with any sane usage for a Duration object (I realise that I'm probably being colored by assuming I can switch all my code from Time::Seconds (part of Time::Piece) to DateTime::Duration with minimal pain. DT && DT::Duration are definitely not meant to emulate Time::Piece and Time::Seconds. Time::Seconds is intentionally bogus. For example, it assumes that each year has exactly 365.24225 days! If you have data that assumes a 3600 second hour (for example TAI based data), then you'd have to convert fractional minutes into minutes + seconds before creating a new DT::Duration object. This could be wrapped up in a module easily. Maybe it could be something like DT::Duration::Fractional? What do others think? -dave /*=== VegGuide.Org Your guide to all that's veg. ===*/
Re: DateTime::Duration 'in_units' does not properly normalize units
On Mon, Dec 13, 2004 at 07:04:23PM -0600, Dave Rolsky <[EMAIL PROTECTED]> wrote: > On Mon, 13 Dec 2004, Dave Rolsky wrote: > > >>>How can that be sane? So you ask for minutes and you get fractional > >>>minutes but you ask for seconds and get zero? > > > >Cause really it should just blow up when you give it fractional anything. > > Or not. Anyone know of a good way to check that a parameter is one of: > > - an integer int($param) != $param # works even for values greater than max UV > - infinity > - NaN $param - $param != 0; # indicates +/-Inf or NaN (differentiate between the two: $param != $param ? "nan" : "infinite") > keeping in mind that if I regex a very large number it gets converted to a > string which may be "1.5853e+18"!
Re: DateTime::Duration 'in_units' does not properly normalize units
On Mon, 13 Dec 2004, Dave Rolsky wrote: How can that be sane? So you ask for minutes and you get fractional minutes but you ask for seconds and get zero? Cause really it should just blow up when you give it fractional anything. Or not. Anyone know of a good way to check that a parameter is one of: - an integer - infinity - NaN keeping in mind that if I regex a very large number it gets converted to a string which may be "1.5853e+18"! -dave /*=== VegGuide.Org Your guide to all that's veg. ===*/
Re: DateTime::Duration 'in_units' does not properly normalize units
On Mon, 13 Dec 2004, Joshua Hoblitt wrote: It looks like the normalization is hosed. This method, for the nth time, does not convert between units which do not have a fixed conversion rate. I'd also point out that it probably won't work well with non-integer units. I'm not sure what'll happen when you try to add 160.2 minutes to a DateTime object, but it won't be anything good, I'm sure. use DateTime::Duration; my $dur = DateTime::Duration->new( hours => 2.67 ); print "hours: ",$dur->in_units( 'hours' ), "\n"; Prints 2, as you'd expect print "minutes: ", $dur->in_units( 'minutes' ), "\n"; prints 160.2, which is right print "seconds: ", $dur->in_units( 'seconds' ), "\n"; prints 0 print "nanoseconds: ", $dur->in_units( 'nanoseconds' ), "\n"; also 0 How can that be sane? So you ask for minutes and you get fractional minutes but you ask for seconds and get zero? Cause really it should just blow up when you give it fractional anything. -dave /*=== VegGuide.Org Your guide to all that's veg. ===*/
DateTime::Duration 'in_units' does not properly normalize units
Hi Tim, It looks like the normalization is hosed. Cut 'n Paste-able example: -- use DateTime::Duration; my $dur = DateTime::Duration->new( hours => 2.67 ); print "hours: ",$dur->in_units( 'hours' ), "\n"; print "minutes: ", $dur->in_units( 'minutes' ), "\n"; print "seconds: ", $dur->in_units( 'seconds' ), "\n"; print "nanoseconds: ", $dur->in_units( 'nanoseconds' ), "\n"; -- -J -- On Mon, 13 Dec 2004, Tim Jenness wrote: perldl> $dur = DateTime::Duration->new( hours => 2.67); perldl> print $dur->minutes 40.2 perldl> print $dur->seconds 0 How can that be sane? So you ask for minutes and you get fractional minutes but you ask for seconds and get zero? ! Hang on. perldl> print $dur->in_units( 'minutes' ) 160.2 perldl> print $dur->in_units( 'seconds' ) 0 perldl> so clearly in_units() is doing the right thing except that for 'seconds' it's not working at all perldl> print $dur->in_units( 'hours' ) 2 and neither is hours since that should say 2.67 to be consistent with minutes returning 160.2. I'm extremely confused by this seeming inconsistency. -- Tim Jenness JAC software http://www.jach.hawaii.edu/~timj
Re: DateTime::Duration 'in_units' does not properly normalize units
I once wrote a module to do this (long before DateTime). Note that in the second case the result is exact. Date::Tie is _very_ careful to round errors correctly. use Date::Tie; tie my %date, 'Date::Tie', frac_hour => 2.67; print $date{frac_hour}, "\n"; print $date{hour}, ":", $date{minute}, ":", $date{frac_second}, "\n"; # 02.67 # 02:40:12.0 $date{frac_hour} = 2 + 2/3; print $date{frac_hour}, "\n"; print $date{hour}, ":", $date{minute}, ":", $date{frac_second}, "\n"; # 02.67 # 02:40:00.0 - Flavio S. Glock
Re: DateTime::Duration 'in_units' does not properly normalize units
On Mon, 13 Dec 2004, Dave Rolsky wrote: > On Mon, 13 Dec 2004, Tim Jenness wrote: > > Yeah, I need to make that clearer. The problem is that with leap seconds, > there are a few 3601 second hours out there. > Now it becomes clear. > > As a related aside. What is wrong with addiing 160.2 minutes to a DateTime > > object? It seems to be a perfectly sensible thing to do if it is first > > converted to seconds. > > If you convert the .2 minutes to seconds first, yes, it is perfectly > sensible. > > > Sorry to show my ignorance here but I am extremely confused by the fact > > that I can't come up with any sane usage for a Duration object (I realise > > that I'm probably being colored by assuming I can switch all my code from > > Time::Seconds (part of Time::Piece) to DateTime::Duration with minimal > > pain. > > DT && DT::Duration are definitely not meant to emulate Time::Piece and > Time::Seconds. Time::Seconds is intentionally bogus. For example, it > assumes that each year has exactly 365.24225 days! > > If you have data that assumes a 3600 second hour (for example TAI based > data), then you'd have to convert fractional minutes into minutes + > seconds before creating a new DT::Duration object. This could be wrapped > up in a module easily. > Yes. Okay, I finally understand where you are coming from. Sometimes a duration really is a duration (essentially a number of seconds that can be represented in standardised days, minutes, hours). Or more explicitly, a stopwatch starts and then is stopped. The duration then has no concept of leap seconds, can not be rendered in units of months, since they vary in length, but can be rendered in standard years. The leap second only becomes an issue when the duration is combined with a DateTime object. If it is a duration from a stopwatch then the real thing that matters is the number of seconds. If it is a duration consisting of discrete days, minutes, months, years and seconds then these have to be treated independently. > Maybe it could be something like DT::Duration::Fractional? What do others > think? A variant of Duration that assumes standard lengths for day, minutes, hour etc, and with a caveat that it will always add seconds when combined with a DateTime object would be great. Am I volunteering...? -- Tim Jenness JAC software http://www.jach.hawaii.edu/~timj
Re: DateTime::Duration 'in_units' does not properly normalize units
Dave, Thanks for the reply. So are you saying that DateTime::Duration shouldn't really be used at all if I have units of fractional anything and want to convert that to a duration? I'm supposed to convert it first to hours, minutes and seconds and then instantiate a DateTime::Duration from that? Shouldn't there be DateTime warnings if that is attempted? What I don't understand is why converting a duration from fractional hours, minutes and seconds is not a standard part of the module. It would seem to be an obvious use for it (and I have lots of data sources that use fractional hours or fractional seconds). DateTime::Format::Duration does handle fractional hours, minutes and seconds but I can't see an obvious way to convert a DateTime::Format::Duration object to a DateTime::Duration object without saying something convoluted like: my $dur = DateTime::Duration->new( seconds => DateTime::Format::Duration->new( pattern => '%s')->format_duration_from_deltas( hours => 2.67 )) which can't be the best way of doing this but does result in a Duration object of 9612.2 sec but now I get: hours: 0 minutes: 0 seconds: 9612 nanoseconds: 96120 which also seems bizarre and non-obvious since I would expect in_units('hours') to return '2'. How come seconds from the constructor aren't converted to hours and minutes? I'm not sure what "fixed conversion rate" means in this context but it clearly doesn't mean divide seconds by 3600 to get hours. As a related aside. What is wrong with addiing 160.2 minutes to a DateTime object? It seems to be a perfectly sensible thing to do if it is first converted to seconds. Sorry to show my ignorance here but I am extremely confused by the fact that I can't come up with any sane usage for a Duration object (I realise that I'm probably being colored by assuming I can switch all my code from Time::Seconds (part of Time::Piece) to DateTime::Duration with minimal pain. Tim On Mon, 13 Dec 2004, Dave Rolsky wrote: > On Mon, 13 Dec 2004, Joshua Hoblitt wrote: > > > It looks like the normalization is hosed. > > This method, for the nth time, does not convert between units which do not > have a fixed conversion rate. > > I'd also point out that it probably won't work well with non-integer > units. I'm not sure what'll happen when you try to add 160.2 minutes to a > DateTime object, but it won't be anything good, I'm sure. > > > use DateTime::Duration; > > > > my $dur = DateTime::Duration->new( hours => 2.67 ); > > > > print "hours: ",$dur->in_units( 'hours' ), "\n"; > > Prints 2, as you'd expect > > > print "minutes: ", $dur->in_units( 'minutes' ), "\n"; > > prints 160.2, which is right > > > print "seconds: ", $dur->in_units( 'seconds' ), "\n"; > > prints 0 > > > print "nanoseconds: ", $dur->in_units( 'nanoseconds' ), "\n"; > > also 0 > > >> How can that be sane? So you ask for minutes and you get fractional > >> minutes but you ask for seconds and get zero? > > Cause really it should just blow up when you give it fractional anything. > > > -dave > > /*=== > VegGuide.Org > Your guide to all that's veg. > ===*/ > -- Tim Jenness JAC software http://www.jach.hawaii.edu/~timj