[Dbix-class] Re: Patch for DBIx::Class::InflateColumn::DateTime

Sergio Salvi sergio.lists at salvi.ca
Fri Oct 5 23:26:19 GMT 2007


On 9/19/07, Ash Berlin <ash at firemirror.com> wrote:
> Sergio Salvi wrote:
> > Hi Matt, Ash,
> >
> > I have a patch for DBIx::Class::InflateColumn::DateTime to add support
> > for timezones. It allows one to specify that a DATE or DATETIME field
> > is stored in a specific timezone instead of the default (UTC). It's
> > here: http://scsys.co.uk:8001/9505
>
> DateTime's come out in Floating, not UTC btw.
> >
> > I've checked out trunk, wrote tests and documentation. Could you
> > please look at it and, hopefully, apply it?
> >
> > Thanks,
> > Sergio
>
> Looks like a promising start. Could you just make the following changes:
>
> - Move the TZ into the extra hash:
>
>   starts_at =3D> { data_type =3D> 'datetime', extra =3D> { timezone =3D>
> "America/Chicago" } },
>
> - Make default convert from what ever timezone the incoming $obj is to
> the one set in the column. Without this you can't guarantee that all
> values of the column have the stated timezone.
>
>

(copying the DBIC list now)

Here is the updated patch according to your suggestions. I've added
more tests also.

Let me know what you and others think.

Thanks,
Sergio
-------------- next part --------------
Index: t/89inflate_datetime.t
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- t/89inflate_datetime.t	(revision 3805)
+++ t/89inflate_datetime.t	(working copy)
@@ -10,7 +10,7 @@
 eval { require DateTime::Format::MySQL };
 plan skip_all =3D> "Need DateTime::Format::MySQL for inflation tests" if $=
@;
 =

-plan tests =3D> 8;
+plan tests =3D> 16;
 =

 # inflation test
 my $event =3D $schema->resultset("Event")->find(1);
@@ -42,3 +42,32 @@
 =

 isa_ok($created->created_on, 'DateTime', 'DateTime returned');
 is("$created_cron", '2006-06-23T00:00:00', 'Correct date/time');
+
+
+# Test "timezone" parameter
+my $event_tz =3D $schema->resultset('EventTZ')->create({
+    starts_at =3D> DateTime->new(year=3D>2007, month=3D>12, day=3D>31, tim=
e_zone =3D> "America/Chicago" ),
+    created_on =3D> DateTime->new(year=3D>2006, month=3D>1, day=3D>31,
+        hour =3D> 12, minute =3D> 34, second =3D> 56, time_zone =3D> "Amer=
ica/Chicago" ),
+});
+
+my $starts_at =3D $event_tz->starts_at;
+is("$starts_at", '2007-12-31T00:00:00', 'Correct date/time using timezone'=
);
+
+my $created_on =3D $event_tz->created_on;
+is("$created_on", '2006-01-31T12:34:56', 'Correct timestamp using timezone=
');
+
+my $loaded_event =3D $schema->resultset('EventTZ')->find( $event_tz->id );
+
+isa_ok($loaded_event->starts_at, 'DateTime', 'DateTime returned');
+$starts_at =3D $loaded_event->starts_at;
+is("$starts_at", '2007-12-31T00:00:00', 'Loaded correct date/time using ti=
mezone');
+my $time_zone =3D $starts_at->time_zone->name;
+is("$time_zone", 'America/Chicago', 'Correct timezone');
+
+isa_ok($loaded_event->created_on, 'DateTime', 'DateTime returned');
+$created_on =3D $loaded_event->created_on;
+is("$created_on", '2006-01-31T12:34:56', 'Loaded correct timestamp using t=
imezone');
+$time_zone =3D $created_on->time_zone->name;
+is("$time_zone", 'America/Chicago', 'Correct timezone');
+
Index: t/lib/DBICTest/Schema/EventTZ.pm
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- t/lib/DBICTest/Schema/EventTZ.pm	(revision 3756)
+++ t/lib/DBICTest/Schema/EventTZ.pm	(working copy)
@@ -1,4 +1,4 @@
-package DBICTest::Schema::Event;
+package DBICTest::Schema::EventTZ;
 =

 use strict;
 use warnings;
@@ -10,8 +10,8 @@
 =

 __PACKAGE__->add_columns(
   id =3D> { data_type =3D> 'integer', is_auto_increment =3D> 1 },
-  starts_at =3D> { data_type =3D> 'datetime' },
-  created_on =3D> { data_type =3D> 'timestamp' }
+  starts_at =3D> { data_type =3D> 'datetime', extra =3D> { timezone =3D> "=
America/Chicago" } },
+  created_on =3D> { data_type =3D> 'timestamp', extra =3D> { timezone =3D>=
 "America/Chicago" } },
 );
 =

 __PACKAGE__->set_primary_key('id');
Index: t/lib/DBICTest/Schema.pm
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- t/lib/DBICTest/Schema.pm	(revision 3805)
+++ t/lib/DBICTest/Schema.pm	(working copy)
@@ -34,7 +34,7 @@
     'Producer',
     'CD_to_Producer',
   ),
-  qw/SelfRefAlias TreeLike TwoKeyTreeLike Event NoPrimaryKey/,
+  qw/SelfRefAlias TreeLike TwoKeyTreeLike Event EventTZ NoPrimaryKey/,
   qw/Collection CollectionObject TypedObject/,
   qw/Owners BooksInLibrary/
 );
Index: lib/DBIx/Class/InflateColumn/DateTime.pm
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- lib/DBIx/Class/InflateColumn/DateTime.pm	(revision 3805)
+++ lib/DBIx/Class/InflateColumn/DateTime.pm	(working copy)
@@ -24,6 +24,12 @@
   print "This event starts the month of ".
     $event->starts_when->month_name();
 =

+If you want to set a specific timezone for that field, use:
+
+  __PACKAGE__->add_columns(
+    starts_when =3D> { data_type =3D> 'datetime', extra =3D> { timezone =
=3D> "America/Chicago" } }
+  );
+
 =3Dhead1 DESCRIPTION
 =

 This module figures out the type of DateTime::Format::* class to =

@@ -55,6 +61,11 @@
   return unless defined($info->{data_type});
   my $type =3D lc($info->{data_type});
   $type =3D 'datetime' if ($type =3D~ /^timestamp/);
+  my $timezone;
+  if ( exists $info->{extra} and exists $info->{extra}->{timezone} and def=
ined $info->{extra}->{timezone} ) {
+    $timezone =3D $info->{extra}->{timezone};
+  }
+
   if ($type eq 'datetime' || $type eq 'date') {
     my ($parse, $format) =3D ("parse_${type}", "format_${type}");
     $self->inflate_column(
@@ -62,10 +73,17 @@
         {
           inflate =3D> sub {
             my ($value, $obj) =3D @_;
-            $obj->_datetime_parser->$parse($value);
+            my $dt =3D $obj->_datetime_parser->$parse($value);
+            if ( defined $timezone ) {
+              $dt->set_time_zone($timezone);
+            }
+            return $dt;
           },
           deflate =3D> sub {
             my ($value, $obj) =3D @_;
+            if ( defined $timezone ) {
+              $value->set_time_zone($timezone);
+            }
             $obj->_datetime_parser->$format($value);
           },
         }


More information about the DBIx-Class mailing list