floating timezone warning
Johannes Plunien [Sun, 26 Oct 2008 20:57:28 +0000 (21:57 +0100)]
lib/DBIx/Class/InflateColumn/DateTime.pm
t/89inflate_datetime.t
t/lib/DBICTest/Schema/EventTZ.pm

index 393a178..dc33f24 100644 (file)
@@ -47,6 +47,42 @@ It's also possible to explicitly skip inflation:
     starts_when => { data_type => 'datetime', inflate_datetime => 0 }
   );
 
+=head1 WARNING
+
+You'll notice some warning about floating timezone if you set timezone in your schema but
+didn't set it when creating/updating a row:
+
+  __PACKAGE__->add_columns(
+    starts_when => { data_type => 'datetime', extra => { timezone => "America/Chicago" } }
+  );
+
+  my $event = $schema->resultset('EventTZ')->create({
+    starts_at => DateTime->new(year=>2007, month=>12, day=>31, ),
+  });
+
+To avoid this, you have three options:
+
+=over
+
+=item Fix your broken code
+
+  my $event = $schema->resultset('EventTZ')->create({
+    starts_at => DateTime->new(year=>2007, month=>12, day=>31, time_zone => "America/Chicago" ),
+  });
+
+=item Suppress the warning by doing either ...
+
+  __PACKAGE__->add_columns(
+    starts_when => { data_type => 'datetime', extra => { timezone => "America/Chicago", floating_tz_ok => 1 } }
+  );
+
+=item ... or ...
+
+Set environment variable DBIC_FLOATING_TZ_OK to some true value.
+
+=back
+
+
 =head1 DESCRIPTION
 
 This module figures out the type of DateTime::Format::* class to 
@@ -111,6 +147,7 @@ sub register_column {
     $timezone = $info->{extra}{timezone};
   }
 
+  my $floating_tz_ok   = $info->{extra}{floating_tz_ok} ? 1 : 0;
   my $undef_if_invalid = $info->{datetime_undef_if_invalid};
 
   if ($type eq 'datetime' || $type eq 'date') {
@@ -128,7 +165,14 @@ sub register_column {
           },
           deflate => sub {
             my ($value, $obj) = @_;
-            $value->set_time_zone($timezone) if $timezone;
+            if ($timezone) {
+                warn "You're using a floating timezone, please see the documentation of"
+                  . " DBIx::Class::InflateColumn::DateTime for an explanation"
+                  if ref( $value->time_zone ) eq 'DateTime::TimeZone::Floating'
+                      and not $floating_tz_ok
+                      and not $ENV{DBIC_FLOATING_TZ_OK};
+                $value->set_time_zone($timezone);
+            }
             $obj->_datetime_parser->$format($value);
           },
         }
index 2cc3030..54cc1ad 100644 (file)
@@ -10,7 +10,7 @@ my $schema = DBICTest->init_schema();
 eval { require DateTime::Format::MySQL };
 plan skip_all => "Need DateTime::Format::MySQL for inflation tests" if $@;
 
-plan tests => 27;
+plan tests => 28;
 
 # inflation test
 my $event = $schema->resultset("Event")->find(1);
@@ -77,6 +77,25 @@ $created_on = $loaded_event->created_on;
 is("$created_on", '2006-01-31T12:34:56', 'Loaded correct timestamp using timezone');
 is($created_on->time_zone->name, 'America/Chicago', 'Correct timezone');
 
+# Test floating timezone warning
+# We expect one warning
+SKIP: {
+    skip "ENV{DBIC_FLOATING_TZ_OK} was set, skipping", 1 if $ENV{DBIC_FLOATING_TZ_OK};
+    $SIG{__WARN__} = sub {
+        like(
+            shift,
+            qr/You're using a floating timezone, please see the documentation of DBIx::Class::InflateColumn::DateTime for an explanation/,
+            'Floating timezone warning'
+        );
+    };
+    my $event_tz_floating = $schema->resultset('EventTZ')->create({
+        starts_at => DateTime->new(year=>2007, month=>12, day=>31, ),
+        created_on => DateTime->new(year=>2006, month=>1, day=>31,
+            hour => 13, minute => 34, second => 56, ),
+    });
+    delete $SIG{__WARN__};
+};
+
 # This should fail to set
 my $prev_str = "$created_on";
 $loaded_event->update({ created_on => '0000-00-00' });
index 9922962..8445aa1 100644 (file)
@@ -11,7 +11,7 @@ __PACKAGE__->table('event');
 __PACKAGE__->add_columns(
   id => { data_type => 'integer', is_auto_increment => 1 },
   starts_at => { data_type => 'datetime', extra => { timezone => "America/Chicago" } },
-  created_on => { data_type => 'timestamp', extra => { timezone => "America/Chicago" } },
+  created_on => { data_type => 'timestamp', extra => { timezone => "America/Chicago", floating_tz_ok => 1 } },
 );
 
 __PACKAGE__->set_primary_key('id');