On Thu, Oct 29, 2009 at 04:18:12PM +0200, Damyan Ivanov wrote:
> Note that constructors of Date::Simple (the base class) work both when 
> called as functions (D::S::today) and when called as a class methods 
> (D::S->today) so perhaps upstream overlooked the problem in the 
> subclasses.
> 
> -- 
> dam

While trying to write a patch to fix this, I found that calling the d8 and ymd 
constructors as a class method did not work in the base class or any of the 
subclasses, producing message such as:
$ perl -MDate::Simple -e 'print Date::Simple->d8('20100102');'
Usage: Date::Simple::_d8(obj_or_class, d8) at /usr/lib/perl5/Date/Simple.pm 
line 70.

This seems to be caused by "return $_[0]->SUPER::_d8(@_);" which ends up with 
_d8 being called with two copies of the class name or object. This bug is fixed 
by replacing the above with "return shift->SUPER::_d8(@_);" and the 
corresponding change for _ymd.

I attach a patch which makes the above changes and copies the constructors from 
the base class into the three subclasses (D8, Fmt and ISO) which appears to fix 
both bugs.

Test script:
echo "Base:"
perl -MDate::Simple -e 'print Date::Simple::today()."\n";'
perl -MDate::Simple -e 'print Date::Simple->today()."\n";'
perl -MDate::Simple -e 'print Date::Simple::ymd(2010,01,02)."\n";'
perl -MDate::Simple -e 'print Date::Simple->ymd(2010,01,02)."\n";'
perl -MDate::Simple -e 'print Date::Simple::d8('20100102')."\n";'
perl -MDate::Simple -e 'print Date::Simple->d8('20100102')."\n";'
echo "Fmt:"
perl -MDate::Simple::Fmt -e 'print Date::Simple::Fmt::today()."\n";'
perl -MDate::Simple::Fmt -e 'print Date::Simple::Fmt->today()."\n";'
perl -MDate::Simple::Fmt -e 'print Date::Simple::Fmt::ymd(2010,01,02)."\n";'
perl -MDate::Simple::Fmt -e 'print Date::Simple::Fmt->ymd(2010,01,02)."\n";'
perl -MDate::Simple::Fmt -e 'print Date::Simple::Fmt::d8('20100102')."\n";'
perl -MDate::Simple::Fmt -e 'print Date::Simple::Fmt->d8('20100102')."\n";'
echo "D8:"
perl -MDate::Simple::D8 -e 'print Date::Simple::D8::today()."\n";'
perl -MDate::Simple::D8 -e 'print Date::Simple::D8->today()."\n";'
perl -MDate::Simple::D8 -e 'print Date::Simple::D8::ymd(2010,01,02)."\n";'
perl -MDate::Simple::D8 -e 'print Date::Simple::D8->ymd(2010,01,02)."\n";'
perl -MDate::Simple::D8 -e 'print Date::Simple::D8::d8('20100102')."\n";'
perl -MDate::Simple::D8 -e 'print Date::Simple::D8->d8('20100102')."\n";'
echo "ISO:"
perl -MDate::Simple::ISO -e 'print Date::Simple::ISO::today()."\n";'
perl -MDate::Simple::ISO -e 'print Date::Simple::ISO->today()."\n";'
perl -MDate::Simple::ISO -e 'print Date::Simple::ISO::ymd(2010,01,02)."\n";'
perl -MDate::Simple::ISO -e 'print Date::Simple::ISO->ymd(2010,01,02)."\n";'
perl -MDate::Simple::ISO -e 'print Date::Simple::ISO::d8('20100102')."\n";'
perl -MDate::Simple::ISO -e 'print Date::Simple::ISO->d8('20100102')."\n";'

The output using version 3.03.03 is:
Base:
2010-01-02
2010-01-02
2010-01-02
Usage: Date::Simple::_ymd(obj_or_class, y, m, d) at 
/usr/lib/perl5/Date/Simple.pm line 97.
2010-01-02
Usage: Date::Simple::_d8(obj_or_class, d8) at /usr/lib/perl5/Date/Simple.pm 
line 70.
Fmt:
Can't call method "_today" on an undefined value at 
/usr/lib/perl5/Date/Simple/Fmt.pm line 11.
2010-01-02
Can't call method "_ymd" without a package or object reference at 
/usr/lib/perl5/Date/Simple/Fmt.pm line 12.
2010-01-02
Can't call method "_d8" without a package or object reference at 
/usr/lib/perl5/Date/Simple/Fmt.pm line 10.
2010-01-02
D8:
Can't call method "_today" on an undefined value at 
/usr/lib/perl5/Date/Simple/D8.pm line 11.
20100102
Can't call method "_ymd" without a package or object reference at 
/usr/lib/perl5/Date/Simple/D8.pm line 12.
20100102
Can't call method "_d8" without a package or object reference at 
/usr/lib/perl5/Date/Simple/D8.pm line 10.
20100102
ISO:
Can't call method "_today" on an undefined value at 
/usr/lib/perl5/Date/Simple/ISO.pm line 11.
2010-01-02
Can't call method "_ymd" without a package or object reference at 
/usr/lib/perl5/Date/Simple/ISO.pm line 12.
2010-01-02
Can't call method "_d8" without a package or object reference at 
/usr/lib/perl5/Date/Simple/ISO.pm line 10.
2010-01-02

The output with the patched version is:
Base:
2010-01-02
2010-01-02
2010-01-02
2010-01-02
2010-01-02
2010-01-02
Fmt:
2010-01-02
2010-01-02
2010-01-02
2010-01-02
2010-01-02
2010-01-02
D8:
20100102
20100102
20100102
20100102
20100102
20100102
ISO:
2010-01-02
2010-01-02
2010-01-02
2010-01-02
2010-01-02
2010-01-02

Thanks,
Chris
diff -ur libdate-simple-perl-3.03.03/lib/Date/Simple/D8.pm libdate-simple-perl-3.03.03-fixed/lib/Date/Simple/D8.pm
--- libdate-simple-perl-3.03.03/lib/Date/Simple/D8.pm	2008-01-11 22:30:50.000000000 +0000
+++ libdate-simple-perl-3.03.03-fixed/lib/Date/Simple/D8.pm	2010-01-02 05:12:46.000000000 +0000
@@ -7,9 +7,50 @@
 *EXPORT_OK   = *Date::Simple::EXPORT_OK;
 *EXPORT_TAGS = *Date::Simple::EXPORT_TAGS;
 
-sub d8    { shift->_d8(@_) }
-sub today { shift->_today(@_) }
-sub ymd   { shift->_ymd(@_) }
+sub d8 {
+
+    # called as function
+    if ( $#_ == 0 ) {
+        return __PACKAGE__->_d8(@_);
+    }
+
+    # called as method
+    else {
+        if ( ref $_[0] eq 'SCALAR' ) {
+            return shift->SUPER::_d8(@_);
+        }
+        else {
+            return shift->_d8(@_);
+        }
+    }
+}
+
+sub today {
+    if ( $#_ == -1 ) {
+        return __PACKAGE__->_today(@_);
+    }
+    else {
+        return shift->_today(@_);
+    }
+}
+
+sub ymd {
+
+    # called as function
+    if ( $#_ == 2 ) {
+        return __PACKAGE__->_ymd(@_);
+    }
+
+    # called as method
+    else {
+        if ( ref $_[0] eq 'SCALAR' ) {
+            return shift->SUPER::_ymd(@_);
+        }
+        else {
+            return shift->_ymd(@_);
+        }
+    }
+}
 
 1;
 
diff -ur libdate-simple-perl-3.03.03/lib/Date/Simple/Fmt.pm libdate-simple-perl-3.03.03-fixed/lib/Date/Simple/Fmt.pm
--- libdate-simple-perl-3.03.03/lib/Date/Simple/Fmt.pm	2008-01-11 22:31:17.000000000 +0000
+++ libdate-simple-perl-3.03.03-fixed/lib/Date/Simple/Fmt.pm	2010-01-02 05:12:46.000000000 +0000
@@ -7,9 +7,50 @@
 *EXPORT_OK   = *Date::Simple::EXPORT_OK;
 *EXPORT_TAGS = *Date::Simple::EXPORT_TAGS;
 
-sub d8    { shift->_d8(@_) }
-sub today { shift->_today(@_) }
-sub ymd   { shift->_ymd(@_) }
+sub d8 {
+
+    # called as function
+    if ( $#_ == 0 ) {
+        return __PACKAGE__->_d8(@_);
+    }
+
+    # called as method
+    else {
+        if ( ref $_[0] eq 'SCALAR' ) {
+            return shift->SUPER::_d8(@_);
+        }
+        else {
+            return shift->_d8(@_);
+        }
+    }
+}
+
+sub today {
+    if ( $#_ == -1 ) {
+        return __PACKAGE__->_today(@_);
+    }
+    else {
+        return shift->_today(@_);
+    }
+}
+
+sub ymd {
+
+    # called as function
+    if ( $#_ == 2 ) {
+        return __PACKAGE__->_ymd(@_);
+    }
+
+    # called as method
+    else {
+        if ( ref $_[0] eq 'SCALAR' ) {
+            return shift->SUPER::_ymd(@_);
+        }
+        else {
+            return shift->_ymd(@_);
+        }
+    }
+}
 
 sub new {
     my ( $class, $fmt, @args ) = @_;
diff -ur libdate-simple-perl-3.03.03/lib/Date/Simple/ISO.pm libdate-simple-perl-3.03.03-fixed/lib/Date/Simple/ISO.pm
--- libdate-simple-perl-3.03.03/lib/Date/Simple/ISO.pm	2008-01-11 22:30:00.000000000 +0000
+++ libdate-simple-perl-3.03.03-fixed/lib/Date/Simple/ISO.pm	2010-01-02 05:12:46.000000000 +0000
@@ -7,9 +7,50 @@
 *EXPORT_OK   = *Date::Simple::EXPORT_OK;
 *EXPORT_TAGS = *Date::Simple::EXPORT_TAGS;
 
-sub d8    { shift->_d8(@_); }
-sub today { shift->_today(@_); }
-sub ymd   { shift->_ymd(@_); }
+sub d8 {
+
+    # called as function
+    if ( $#_ == 0 ) {
+        return __PACKAGE__->_d8(@_);
+    }
+
+    # called as method
+    else {
+        if ( ref $_[0] eq 'SCALAR' ) {
+            return shift->SUPER::_d8(@_);
+        }
+        else {
+            return shift->_d8(@_);
+        }
+    }
+}
+
+sub today {
+    if ( $#_ == -1 ) {
+        return __PACKAGE__->_today(@_);
+    }
+    else {
+        return shift->_today(@_);
+    }
+}
+
+sub ymd {
+
+    # called as function
+    if ( $#_ == 2 ) {
+        return __PACKAGE__->_ymd(@_);
+    }
+
+    # called as method
+    else {
+        if ( ref $_[0] eq 'SCALAR' ) {
+            return shift->SUPER::_ymd(@_);
+        }
+        else {
+            return shift->_ymd(@_);
+        }
+    }
+}
 
 1;
 
diff -ur libdate-simple-perl-3.03.03/lib/Date/Simple.pm libdate-simple-perl-3.03.03-fixed/lib/Date/Simple.pm
--- libdate-simple-perl-3.03.03/lib/Date/Simple.pm	2008-01-11 23:03:51.000000000 +0000
+++ libdate-simple-perl-3.03.03-fixed/lib/Date/Simple.pm	2010-01-02 05:09:05.000000000 +0000
@@ -64,10 +64,10 @@
     # called as method
     else {
         if ( ref $_[0] eq 'SCALAR' ) {
-            return $_[0]->SUPER::_d8(@_);
+            return shift->SUPER::_d8(@_);
         }
         else {
-            return $_[0]->_d8(@_);
+            return shift->_d8(@_);
         }
     }
 }
@@ -91,10 +91,10 @@
     # called as method
     else {
         if ( ref $_[0] eq 'SCALAR' ) {
-            return $_[0]->SUPER::_ymd(@_);
+            return shift->SUPER::_ymd(@_);
         }
         else {
-            return $_[0]->_ymd(@_);
+            return shift->_ymd(@_);
         }
     }
 }

Reply via email to