| SPOPS documentation | Contained in the SPOPS distribution. |
SPOPS::Tool::DateConvert - Convert dates to objects to/from your datastore
# Class configuration with date convertion rule and metadata
my $spops = {
class => 'This::Class',
isa => [ 'SPOPS::DBI' ],
field => [ 'email', 'language', 'birthtime' ],
id_field => 'email',
base_table => 'test_table',
rules_from => [ 'SPOPS::Tool::DateConvert' ],
convert_date_field => [ 'birthtime' ],
convert_date_class => 'Time::Piece',
convert_date_format => '%Y-%m-%d %H:%M:%S',
};
SPOPS::Initialize->process({ config => { test => $spops } });
my $item = This::Class->fetch(55);
print "Birthdate field isa: ", ref( $item->{birthtime} ), "\n";
--> Birthdate field isa: Time::Piece
# Format some other way
print "Birthday occurred on day ", $item->{birthtime}->strftime( '%j' ),
"which was a ", $item->{birthtime}->strftime( '%A' ), "\n";
# When creating a new object, just set the correct type of object as
# the field value
my $newborn = This::Class->new({ email => 'foo@bar.com',
language => 'en',
birthtime => Time::Piece->new });
$newborn->save;
This SPOPS tool converts data coming from the database into a date object, and translates the date object into the proper format before it's put back into the database.
This tool uses three configuration fields:
convert_date_field (\@)
An arrayref of fields that will be converted.
If not specified or if empty no action will be taken.
convert_date_class ($)
Class for date object to be instantiated. Supported classes are:
If not specified, 'DateTime' will be used.
convert_date_format ($)
Format (in strftime format) for date conversions. All implementations will likely use this for converting the object to a string. Some implementations (like Time::Piece and DateTime) will use this for parsing the date from the database into the date object as well.
If not specified, '%Y-%m-%d %H:%M:%S' will be used.
Uses the DateTime::Format::Strptime and
convert_date_format to translate the date from the database.
Uses the DateTime strftime() method from along with
convert_date_format configuration to translate the date into a
string.
Uses the strptime() method and convert_date_format to translate
the date from the database.
Uses the strftime() method along with convert_date_format
configuration to translate the date into a string.
Uses the new() method to translate the date from the database.
Uses the strftime() method along with convert_date_format
configuration to translate the date into a string.
If necessary, make this a factory and refactor if clauses into subclasses for the different implementations.
Chris Winters <chris@cwinters.com>
| SPOPS documentation | Contained in the SPOPS distribution. |
package SPOPS::Tool::DateConvert; # $Id: DateConvert.pm,v 1.10 2004/02/26 01:01:37 lachoy Exp $ use strict; use Log::Log4perl qw( get_logger ); use SPOPS; my $log = get_logger(); my $DEFAULT_DATE_CLASS = 'DateTime'; my $DEFAULT_DATE_FORMAT = '%Y-%m-%d %H:%M:%S'; my %REQUIRED = (); sub ruleset_factory { my ( $class, $ruleset ) = @_; push @{ $ruleset->{post_fetch_action} }, \&convert_to_object; push @{ $ruleset->{pre_save_action} }, \&convert_to_string; push @{ $ruleset->{post_save_action} }, \&convert_to_object; $log->is_info && $log->info( "DateConvert added post_fetch, pre/post_save rules to [$class]" ); return __PACKAGE__; } sub convert_to_object { my ( $self ) = @_; my ( $date_fields, $date_class ) = _init( $self ); unless ( ref $date_fields eq 'ARRAY' and scalar @{ $date_fields } ) { $log->warn( "Using date conversion for ", ref( $self ), " but there ", "are no date fields in 'convert_date_field'" ); return 1; } foreach my $field ( @{ $date_fields } ) { $self->{ $field } = eval { _create_date_object( $self, $date_class, $self->{ $field } ) }; return undef if ( $@ ); } return 1; } sub _create_date_object { my ( $self, $date_class, $date ) = @_; return undef unless ( $date ); if ( ref $date eq $date_class ) { return $date; } if ( $date_class eq 'Class::Date' ) { return Class::Date->new( $date ); } elsif ( $date_class eq 'Time::Piece' ) { my $date_format = $self->CONFIG->{convert_date_format} || $DEFAULT_DATE_FORMAT; return Time::Piece->strptime( $date, $date_format ); } elsif ( $date_class eq 'DateTime' ) { my $date_format = $self->CONFIG->{convert_date_format} || $DEFAULT_DATE_FORMAT; return DateTime::Format::Strptime->new( pattern => $date_format ) ->parse_datetime( $date ); } die "Given date class [$date_class] is not supported for conversion\n"; } sub convert_to_string { my ( $self ) = @_; my ( $date_fields, $date_class ) = _init( $self ); unless ( ref $date_fields eq 'ARRAY' and scalar @{ $date_fields } ) { $log->warn( "Using date conversion for ", ref( $self ), " but there ", "are no date fields in 'convert_date_field'" ); return 1; } foreach my $field ( @{ $date_fields } ) { $self->{ $field } = _create_date_string( $self, $date_class, $self->{ $field } ); } return 1; } sub _create_date_string { my ( $self, $date_class, $date_object ) = @_; # NULLs are ok... unless ( $date_object ) { return undef; } # Strings are semi-ok... unless ( ref( $date_object ) ) { $log->info( "Expected date object of type '$date_class' but item ", "is not a reference, which probably means it's a ", "string representation of a date ($date_object). ", "Hope it's in the right format, it's going in as is." ); return $date_object } # ... but getting something that's not an object when we expect # something is a different matter and deserves a warning unless ( ref( $date_object ) eq $date_class ) { $log->warn( "Expected date object of type '$date_class' but ", "got '", ref( $date_object ), "'; not converting." ); return undef; } my $date_format = $self->CONFIG->{convert_date_format} || $DEFAULT_DATE_FORMAT; if ( $date_class eq 'Class::Date' ) { return $date_object->strftime( $date_format ); } elsif ( $date_class eq 'Time::Piece' ) { return $date_object->strftime( $date_format ); } elsif ( $date_class eq 'DateTime' ) { return $date_object->strftime( $date_format ); } die "Given date class [$date_class] is not supported for conversion\n"; } sub _init { my ( $self ) = @_; my $date_fields = $self->CONFIG->{convert_date_field}; return () unless ( ref $date_fields eq 'ARRAY' and scalar @{ $date_fields } ); my $date_class = $self->CONFIG->{convert_date_class} || $DEFAULT_DATE_CLASS; unless ( $REQUIRED{ $date_class } ) { _require_class( $date_class ); } return ( $date_fields, $date_class ); } sub _require_class { my ( $date_class ) = @_; eval "require $date_class"; if ( $@ ) { die "Cannot bring in date library $date_class: $@\n"; } $REQUIRED{ $date_class }++; # HACK! if ( $date_class eq 'DateTime' ) { require DateTime::Format::Strptime; $REQUIRED{ 'DateTime::Format::Strptime' }++; } } 1; __END__