Skip Menu |

Preferred bug tracker

Please visit the preferred bug tracker to report your issue.

This queue is for tickets about the DateTime CPAN distribution.

Report information
The Basics
Id: 7599
Status: resolved
Priority: 0/
Queue: DateTime

People
Owner: DROLSKY [...] cpan.org
Requestors: J2N-FORGET [...] orange.fr
Cc:
AdminCc:

Bug Information
Severity: (no value)
Broken in: (no value)
Fixed in: (no value)



Subject: DateTime: Bugs in documentation and strftime
#!/usr/local/bin/perl use strict; use warnings; use DateTime; my $dt = DateTime->new(year => 2004, month => 8, day => 16, hour => 15, minute => 30 , nanosecond => 123456789, locale => 'en'); # Should print '%{day_name}', prints '30onday'! print $dt->strftime('%%{day_name}%n'); # Should print '%6N', prints '123456' print $dt->strftime('%%6N%n'); __END__ The included patch fixes some bugs in the documentation. It does not fix the strftime bugs. Rather, here are some propositions to fix strftime. The problem is that the string is scanned three times and the 2nd scan is done after the first substitution, the 3rd scan is done after the first and second substitutions. $f =~ s/%{(\w+)}/1st subs/sgex; # regex from Date::Format - thanks Graham! $f =~ s/%([%a-zA-Z])/2nd subst/sgex; # %3N $f =~ s/%(\d+)N/3rd subst/sgex; There are three ways to fix it. The first comes from DT::C::FrenchRevolutionary the recently released version 0.07, which deals with C<%{method}> specifiers. I have simplified it to discard the specifiers like C<%EY> and C<%Oj> and I have not introduced nanosecond support. $f =~ s/ %([%a-zA-Z]) # $1 stores plain specifier (possibly "%%") | %{(\w+)} # $2 stores method name / $2 ? ($self->can($2) ? $self->$2() : "\%{$2}") : ($formats{$1} ? $formats{$1}->($self) : $1) /sgex; With this method, the string is scanned once and the substitution string does the dispatch. Supporting nanoseconds is left as an exercise... The second way uses a gimmick inspired from DT::F::Strptime, version 1.05 my $str = 'some#peculiar@string=which$does:not!appear-in+the+format'; $f =~ s/%%/$str/g; $f =~ s/%{(\w+)}/1st subs/sgex; # %{method} $f =~ s/%([a-zA-Z])/2nd subst/sgex; # %x, *not* including %% $f =~ s/%(\d+)N/3rd subst/sgex; # %3N $f =~ s/$str/%/g; A third version, not tested, would be: $f = join '%', map { s/%{(\w+)}/1st subs/sgex; # %{method} s/%([a-zA-Z])/2nd subst/sgex; # %x s/%(\d+)N/3rd subst/sgex; # %3N } split /%%/, $f; Note that if somebody writes a DateTime::Locale::Fiction::Rodenburry::Klingon module in which Monday is "krf%Ysq!" and January is "psek%3Nvtdl#", the second and third versions will still give wrong results with a format such as "%{day_name} %B". I have not found any pathological situation which would give wrong results with the first version. I have even imagined a paranoid variant of the second way: my $str; do { $str = generate_random_string() } until index($f, $str) < 0 && index($str, '%') < 0; # etc. to fix the obvious bug of the "sane" variant of the second way, but it fails in funny ways, depending on which random string is generated. Example: $f = 'xy%%xy%%xy%%' and $str = 'xyxyxy' Anyhow, both the paranoid and the sane versions fails with the "Klingon locale". Jean Forget
--- /home/p80/modules/DateTime-0.22/lib/DateTime.pm Tue Jul 20 22:47:46 2004 +++ /var/tmp/DateTime.new Thu Sep 9 21:19:53 2004 @@ -1695,10 +1694,6 @@ Invalid parameter types (like an array reference) will cause the constructor to die. -DateTime does not check if second values greater than 59 are valid -based on current leap seconds, and invalid values simply cause an -overflow. - All of the parameters are optional except for "year". The "month" and "day" parameters both default to 1, while the "hour", "minute", and "second", and "nanosecond" parameters all default to 0. @@ -2456,7 +2451,7 @@ There are other subtract/delta methods in DateTime.pm to generate different types of durations. These methods are C<subtract_datetime()>, C<subtract_datetime_absolute()>, -C<delta_md()>, L<delta_days()>, and C<delta_ms()>. +C<delta_md()>, C<delta_days()>, and C<delta_ms()>. =head2 Overloading @@ -2532,7 +2527,7 @@ The ISO 8601 year with century as a decimal number. The 4-digit year corresponding to the ISO week number (see %V). This has the same -format and value as %y, except that if the ISO week number belongs to +format and value as %Y, except that if the ISO week number belongs to the previous or next year, that year is used instead. (TZ) =item * %g