Using Class::Date

From ClassDBI

The Class::Date package can be very useful with Class::DBI.

For example:

Package Film;
__PACKAGE__->has_a (created_date => 'Class::Date',
inflate => 'new',
deflate => 'string');

You can even do this as shorthand (thanks to Bodo Shulze for the tip):

Film->has_a( created_date => 'Class::Date' );

-- then, later --

my $film = Film->retrieve($id);
print $film->created_date;
# prints current date/time format

print $film->created_date->mdy;
# prints mm/dd/yy

print ($film->created_date - Class::Date->now)->day;
# prints number of days, to the decimal place

print $film->created_date->string
# prints mysql string 'yyyy-mm-dd hh:mm:ss'

$film->created_date("2004-2-20");
# change created date

$film->created_date(undef);
$film->update;
# undef Class::Date value will default to current date when deflated

An additional example, from Bodo:

package main;
use Foo;
use Class::Date;

Foo->create({ date => Class::Date->now });
# ...
my $row = Foo->retrieve($id);
my $date = $row->date;

In string context the $date object automatically gets stringified.

If you want a different output format, change the has_a() to something like:

Foo->has_a( date    => 'Class::Date',
   inflate => sub {              # German date format   
               $Class::Date::DATE_FORMAT = "%d.%m.%Y - %H:%M:%S"; 
               Class::Date->new(shift) }
   );

-- Bodo

There is more info about Class::Date at http://hacks.dlux.hu/Class-Date/manual.html.

A Comment from Shngn:

The following code relies on the database's date format when it converts the date to a string on a query:

Film->has_a( created_date => 'Class::Date' );

This won't work with the default Oracle date format of 'DD-MON-YY' (6-DEC-1977 for example). This can be fixed in Oracle by changing the default date format.

-- Shngn


MySQL date fields can have the value '0000-00-00 00:00:00' in some databases (and other values that may not be parsed). In that scenario, you might to use the following method which turns such values into undefined values.

 # Generic is better
 sub date_field_inflate($) {
   my $fieldname = shift;
   
   return sub {
       my $arg = shift;
       my $class = shift;
   
       if ( substr($arg, 0, 4) eq "0000" ) {
           $class->{$fieldname} = undef;
           return undef;
       }
       return Class::Date->new($arg)
   }
 }
 
 # Then
 __PACKAGE__->has_a(some_date=> 'Class::Date',
   inflate => date_field_inflate('some_date'),
   deflate => 'string'
 );

-- Romuald