Re: Strptime issues
[EMAIL PROTECTED] wrote: > > Sounds good .. and it's as simple as using > DateTime->today as the base, which may well be a > good default behaviour for ->to_datetime when no > base is in the object or none is passed in the call. So this is what we've got so far: 0.0102 2003-11-06 - to_datetime() uses "today" as a base date, if none was given. The following methods are affected by this change: epoch, hires_epoch, is_dst, utc_rd_values, utc_rd_as_seconds, sprintf("%s") - can_be_datetime() - has_date(), has_time() - defined_fields() method, contributed by Rick Measham - to_datetime() sets fields in a known order, instead of hash-order. Based on a patch by Rick Measham - Included has() method, contributed by Rick Measham 0.0101 2003-11-03 - runs in Perl 5.00503. Dave Rolsky & Flavio S. Glock, creating a cvs conflict :) - there is no set_locale() in DateTime. Modified from a patch by Rick Measham - fixed an infinite loop in _format_nanoseconds. Patch by Rick Measham This is a sample of the new API: $dti = $dti->to_datetime; if ( $dti->can_be_datetime ) { $dti = $dti->to_datetime } else { print "only @{[ $dti->defined_fields ]} are set" } if ( $dti->can_be_datetime && $dti->has_date ) ... if ( $dti->has_date && $dti->has_time ) ... if ( $dti->has_year ) ... if ( $dti->has( qw( year month day hour ) ) ) ... - Flavio S. Glock
Re: Re: Strptime issues
> Flavio S. Glock <[EMAIL PROTECTED]> wrote: > > How about to extend the 'to_datetime' method, instead of creating a > new > one: > >if ($dti->can_be_datetime) { > $dti = $dti->to_datetime >} > Sounds good .. and it's as simple as using DateTime->today as the base, which may well be a good default behaviour for ->to_datetime when no base is in the object or none is passed in the call. Cheers! Rick
Re: Strptime issues
Rick Measham wrote: > >if ($dti->can_be_datetime) { > $dti->become_datetime >} implemented as: if ($dti->can_be_datetime) { $dti = $dti->become_datetime } because changing the class of '$dti' is a bit hard. How about to extend the 'to_datetime' method, instead of creating a new one: if ($dti->can_be_datetime) { $dti = $dti->to_datetime } - Flavio S. Glock
Re: Re: Strptime issues
> Flavio S. Glock <[EMAIL PROTECTED]> wrote: > > sub has { > > I implemented this in CVS with tests, but I believe it > should be 2 separate methods instead. What do you think? I'm cool with two different methods ... it really is two different things. Maybe there's also a need for has_any('hour', 'minute') which returns true if it has either of hours or minutes. > > > * can_be_datetime / become_datetime > > sub can_be_datetime { > I think any dti that has_year can become a datetime. > For example, DT::I->new( year=>2003 )->become_datetime->datetime > 2003-01-01T00:00:00 Hmmm ... I think this is OK, but I'd like some way then to control what is required. $dti->become_datetime if $dti->can_be_datetime('minutes') requires: -MM-DD HH:MM -MM-DD HH:MM:SS -MM-DD HH:MM:SS.N and not -MM-DD HH:MM:xx.N That is, it must have years to minutes and no holes.
Re: Strptime issues
[EMAIL PROTECTED] wrote: > > > Flavio S. Glock <[EMAIL PROTECTED]> wrote: > > > > * keys or defined_fields > > returns the list of names of "defined" fields > > sub has { ># called with parameters you get true or false ># called with no params and you get a list of fields I implemented this in CVS with tests, but I believe it should be 2 separate methods instead. What do you think? > > * can_be_datetime / become_datetime > > sub can_be_datetime { ># -MM-DD ># -MM-DD HH:MM ># -MM-DD HH:MM:SS ># -MM-DD HH:MM:SS.N I think any dti that has_year can become a datetime. For example, DT::I->new( year=>2003 )->become_datetime->datetime 2003-01-01T00:00:00 Or perhaps, allow any dti without 'holes': -MM -MM-DD -MM-DD HH -MM-DD HH:MM -MM-DD HH:MM:SS -MM-DD HH:MM:SS.N this excludes, for example: --DD - Flavio S. Glock
Re: Re: Re: Strptime issues
> [EMAIL PROTECTED] <[EMAIL PROTECTED]> wrote: > sub has_time { $_[0]->has{'hour', 'minute'} } Maybe should be: sub has_time { return 1 if ($_[0]->has('hour', 'minute') and not $_[0]->has('nanosecond')); return 1 if ($_[0]->has('hour', 'minute', 'second')) return 0 } Which only returns true if we have HH:MM or HH:MM:SS or HH:MM:SS.N+. The older version allowed us to get true for HH:MM:xx.N+ which is not really a time. Same caveat: Above code passes all tests on the perl installed in my head. Havn't tried any of it with the much fussier software version. perl -v This is perl, v5.8.0 built for ricks-brain-1.0
Re: Re: Strptime issues
[webmail logged me out, so sorry if you get ++ copies] > Flavio S. Glock <[EMAIL PROTECTED]> wrote: > So this is the current list of proposed DT::Incomplete methods that > are > "waiting for votes": > > * epoch > $epoch = $dti->epoch if $dti->can_be_datetime; Sounds good sub epoch { my $self = shift; return undef unless $self->can_be_datetime; return $self->clone->become_datetime->epoch; } > * has_date / has_time Sounds good, see below and: sub has_time { $_[0]->has{'hour', 'minute'} } sub has_date { $_[0]->has{'year', 'month', 'day'} } > * keys or defined_fields > returns the list of names of "defined" fields sub has { # called with parameters you get true or false # called with no params and you get a list of fields my $self = shift; if (@_) { foreach (@_) { return 0 unless exists $self->{has}{$_} } return 1 } return keys %{$self->{has}} } Which gives: print "Got hour" if $dti->has('hour'); print "Got time" if $dti->has('hour', 'minute') and print "Object has " . join(', ', @{$dti->has} ); > * join( $dti ) > join the "defined" keys of two DT::Incomplete objects 'join' feels like 'append'. 'union' feels better, but relates to sets. Maybe 'merge'? Also consider 'overlay'. dti1 2003-xx-21Txx:18:xx.12345 dti2 2003-09-22T15:17:xx.x merge: 2003-09-21T15:18:xx.12345 overlay: 2003-09-22T15:17:xx.12345 Note that $dti1->overlay($dti2) is the same as $dti2->merge($dti1); sub merge { # not 'submerge'!!! my $self = shift; my $dti = shift; die "Argument to merge must be a DateTime or DateTime::Incomplete" unless ref($dti)=~/^DateTime(::Incomplete)?$/; # There must be a better way to do this: $self->{has}{year} ||= $dti->year; $self->{has}{month} ||= $dti->month; $self->{has}{day} ||= $dti->day; $self->{has}{hour} ||= $dti->hour; $self->{has}{minute} ||= $dti->minute; $self->{has}{second} ||= $dti->second; $self->{has}{nanosecond} ||= $dti->nanosecond; $self->{has}{time_zone} ||= $dti->time_zone; $self->{has}{locale} ||= $dti->locale; return $self } sub overlay { $_[0] = $_[1]->clone->merge( $_[0] ) } ### PROBABLY A VERY UN-KOSHER WAY TO DO IT! ### > * is_incomplete / is_complete sub is_complete { $_[0]->has('year', 'month', 'day', 'hour', 'minute', 'second', 'nanosecond') } sub is_incomplete { ($_[0]->is_complete) ? 0 : 1 } > * can_be_datetime / become_datetime sub can_be_datetime { my $self = shift; # -MM-DD HH:MM:SS # -MM-DD HH:MM:SS.N return 1 if $self->has('year', 'month', 'day', 'hour', 'minute', 'second'); # -MM-DD HH:MM # -MM-DD HH:MM::SS, but is already caught return 1 if $self->has('year', 'month', 'day', 'hour', 'minute') and not $self->has('nanosecond'); # -MM-DD return 1 if $self->has('year', 'month', 'day') and not ($self->has('hour') or $self->has('minute') or $self->has('second') or $self->has('nanosecond') ); return 0; } sub become_datetime { my $self = shift; return undef unless $self->can_be_datetime; my $dt = DateTime->new( year => $self->year, month => $self->month, day => $self->day, ); $dt->set_time_zone( $self->time_zone ) if $self->has('time_zone'); $dt->set( locale => $self->locale ) if $self->has('locale'); $dt->set( hour => $self->hour, minute => $minute ) if $self->has('hour', 'minute'); $dt->set( second => $self->second ) if $self->has('second'); $dt->set( nanosecond => $self->nanosecond ) if $self->has('nanosecond'); $self = $dt; DOES THAT DO THE TRICK, OR IS IT MORE COMPLEX? return $self; } Above code passes all tests on the perl installed in my head. Havn't tried any of it with the much fussier software version. perl -v This is perl, v5.8.0 built for ricks-brain-1.0
Re: Strptime issues
Rick Measham wrote: > > If so, maybe a method inside Incomplete would be good: >if ($dti->can_be_datetime) { > $dti->become_datetime >} I've put this in the TODO. So this is the current list of proposed DT::Incomplete methods that are "waiting for votes": * epoch $epoch = $dti->epoch if $dti->can_be_datetime; * has_date / has_time * keys or defined_fields returns the list of names of "defined" fields * join( $dti ) join the "defined" keys of two DT::Incomplete objects * is_incomplete / is_complete * can_be_datetime / become_datetime - Flavio S. Glock
Re: Strptime issues
Rick Measham wrote: > > I'm adapting Strptime to return DateTime::Incomplete objects when it > gets an incomplete datetime. The old behaviour was to return the lowest > possible value. > > eg. 'November 2003' used to return 2003-11-01T00:00:00, but will now > return 2003-11-xxTxx:xx:xx > > I'm currently checking to see if a datetime is possible and only > returning incomplete if not. Is that a good idea? How about it to be an option in the Strptime constructor? my $Strp = new DateTime::Format::Strptime( pattern => '%T', locale => 'en_AU', time_zone => 'Melbourne/Australia', incomplete => 'never' | 'always' | 'maybe' ); > If so, maybe a method inside Incomplete would be good: >if ($dti->can_be_datetime) { > $dti->become_datetime >} > or else an incomplete could automatically convert itself to a DateTime > once it had enough information?!?!? > > I figure an Incomplete can become a DateTime if: > > We have a Year, Month and Day, but no time (becomes 00:00:00) -or- > We have a Year, Month, Day, Hour and Minute -or- > We have a Year, Month, Day, Hour, Minute and Second -or- > We have a Year, Month, Day, Hour, Minute, Second and Nanosecond That's ok to me. Do you already have code to do this? > 3. Keep the current (shonky) behaviour That's not too bad, except that DT::Incomplete is a bit slower than DateTime. - Flavio S. Glock
Re: Strptime issues
Rick Measham wrote: > > I'm adapting Strptime to return DateTime::Incomplete objects when it > gets an incomplete datetime. The old behaviour was to return the lowest > possible value. > > eg. 'November 2003' used to return 2003-11-01T00:00:00, but will now > return 2003-11-xxTxx:xx:xx > > I'm currently checking to see if a datetime is possible and only > returning incomplete if not. Is that a good idea? > > If so, maybe a method inside Incomplete would be good: >if ($dti->can_be_datetime) { > $dti->become_datetime >} > or else an incomplete could automatically convert itself to a DateTime > once it had enough information?!?!? I think automatic conversion is not a good thing. I'm thinking about the other alternatives... The patches were applied - thanks. - Flavio S. Glock
Re: Re: Strptime issues
> David Hood <[EMAIL PROTECTED]> wrote: > Perhaps you should return only the information that is given, in an > iso 8601 > compliant format, so for November 2003 you could simply return > 2003-11. The Nah, that's not going to happen. The entire point of the module is to get a DateTime object. So it's either going to be a full DateTime or a DateTime::Incomplete. Also: What's the ISO format for "11pm November"?
Re: Strptime issues
Perhaps you should return only the information that is given, in an iso 8601 compliant format, so for November 2003 you could simply return 2003-11. The iso standard is probably useful, especially for things like day of month for an implied year (--MM-DD) etc. Perhaps format::iso could then be used to create only an incomplete datetime if there isn't enough information to create a full datetime object. Cheers, David - Original Message - From: "Rick Measham" <[EMAIL PROTECTED]> To: <[EMAIL PROTECTED]> Sent: Monday, November 03, 2003 5:09 PM Subject: Strptime issues > I'm adapting Strptime to return DateTime::Incomplete objects when it > gets an incomplete datetime. The old behaviour was to return the lowest > possible value. > > eg. 'November 2003' used to return 2003-11-01T00:00:00, but will now > return 2003-11-xxTxx:xx:xx > > I'm currently checking to see if a datetime is possible and only > returning incomplete if not. Is that a good idea? > > If so, maybe a method inside Incomplete would be good: >if ($dti->can_be_datetime) { > $dti->become_datetime >} > or else an incomplete could automatically convert itself to a DateTime > once it had enough information?!?!? > > I figure an Incomplete can become a DateTime if: > > We have a Year, Month and Day, but no time (becomes 00:00:00) -or- > We have a Year, Month, Day, Hour and Minute -or- > We have a Year, Month, Day, Hour, Minute and Second -or- > We have a Year, Month, Day, Hour, Minute, Second and Nanosecond > > But maybe that's just me. > > > My other option with Strptime are: > > 1. Always return an Incomplete object, but I doubt that's what people > would want/expect. > > 2. Always return an Incomplete unless we are given a base, in which case > the base fills in the blanks. This would mean if you have a full > datetime specifier in some format you still need to pass a DateTime into > the strptime object in order to receive a DateTime in return: > > $strptime = new DateTime::Format::Strptime( base => DateTime->today, > pattern=$pattern ); > $strptime->parse_datetime("Nov 3, 2003"); > # Returns DateTime: 2003-11-03T00:00:00 > > $strptime = new DateTime::Format::Strptime( pattern=$pattern ); > $strptime->parse_datetime("Nov 3, 2003"); > # Returns DateTime::Incomplete: 2003-11-03Txx:xx:xx > > 3. Keep the current (shonky) behaviour > > > Cheers! > Rick > > > > > > > >