On 9/19/07, Ash Berlin <[EMAIL PROTECTED]> 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 => { data_type => 'datetime', extra => { timezone =>
> "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
Index: t/89inflate_datetime.t
===================================================================
--- t/89inflate_datetime.t      (revision 3805)
+++ t/89inflate_datetime.t      (working copy)
@@ -10,7 +10,7 @@
 eval { require DateTime::Format::MySQL };
 plan skip_all => "Need DateTime::Format::MySQL for inflation tests" if $@;
 
-plan tests => 8;
+plan tests => 16;
 
 # inflation test
 my $event = $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 = $schema->resultset('EventTZ')->create({
+    starts_at => DateTime->new(year=>2007, month=>12, day=>31, time_zone => 
"America/Chicago" ),
+    created_on => DateTime->new(year=>2006, month=>1, day=>31,
+        hour => 12, minute => 34, second => 56, time_zone => "America/Chicago" 
),
+});
+
+my $starts_at = $event_tz->starts_at;
+is("$starts_at", '2007-12-31T00:00:00', 'Correct date/time using timezone');
+
+my $created_on = $event_tz->created_on;
+is("$created_on", '2006-01-31T12:34:56', 'Correct timestamp using timezone');
+
+my $loaded_event = $schema->resultset('EventTZ')->find( $event_tz->id );
+
+isa_ok($loaded_event->starts_at, 'DateTime', 'DateTime returned');
+$starts_at = $loaded_event->starts_at;
+is("$starts_at", '2007-12-31T00:00:00', 'Loaded correct date/time using 
timezone');
+my $time_zone = $starts_at->time_zone->name;
+is("$time_zone", 'America/Chicago', 'Correct timezone');
+
+isa_ok($loaded_event->created_on, 'DateTime', 'DateTime returned');
+$created_on = $loaded_event->created_on;
+is("$created_on", '2006-01-31T12:34:56', 'Loaded correct timestamp using 
timezone');
+$time_zone = $created_on->time_zone->name;
+is("$time_zone", 'America/Chicago', 'Correct timezone');
+
Index: t/lib/DBICTest/Schema/EventTZ.pm
===================================================================
--- 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 => { data_type => 'integer', is_auto_increment => 1 },
-  starts_at => { data_type => 'datetime' },
-  created_on => { data_type => 'timestamp' }
+  starts_at => { data_type => 'datetime', extra => { timezone => 
"America/Chicago" } },
+  created_on => { data_type => 'timestamp', extra => { timezone => 
"America/Chicago" } },
 );
 
 __PACKAGE__->set_primary_key('id');
Index: t/lib/DBICTest/Schema.pm
===================================================================
--- 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
===================================================================
--- 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 => { data_type => 'datetime', extra => { timezone => 
"America/Chicago" } }
+  );
+
 =head1 DESCRIPTION
 
 This module figures out the type of DateTime::Format::* class to 
@@ -55,6 +61,11 @@
   return unless defined($info->{data_type});
   my $type = lc($info->{data_type});
   $type = 'datetime' if ($type =~ /^timestamp/);
+  my $timezone;
+  if ( exists $info->{extra} and exists $info->{extra}->{timezone} and defined 
$info->{extra}->{timezone} ) {
+    $timezone = $info->{extra}->{timezone};
+  }
+
   if ($type eq 'datetime' || $type eq 'date') {
     my ($parse, $format) = ("parse_${type}", "format_${type}");
     $self->inflate_column(
@@ -62,10 +73,17 @@
         {
           inflate => sub {
             my ($value, $obj) = @_;
-            $obj->_datetime_parser->$parse($value);
+            my $dt = $obj->_datetime_parser->$parse($value);
+            if ( defined $timezone ) {
+              $dt->set_time_zone($timezone);
+            }
+            return $dt;
           },
           deflate => sub {
             my ($value, $obj) = @_;
+            if ( defined $timezone ) {
+              $value->set_time_zone($timezone);
+            }
             $obj->_datetime_parser->$format($value);
           },
         }
_______________________________________________
List: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/dbix-class
IRC: irc.perl.org#dbix-class
SVN: http://dev.catalyst.perl.org/repos/bast/DBIx-Class/
Searchable Archive: http://www.grokbase.com/group/[EMAIL PROTECTED]

Reply via email to