]> git.ipfire.org Git - thirdparty/bugzilla.git/commitdiff
Bug 545299, XML-RPC WebService should take and return dates and times in UTC. Code...
authorJustin Wood <Callek@gmail.com>
Thu, 4 Mar 2010 19:39:53 +0000 (14:39 -0500)
committerJustin Wood <Callek@gmail.com>
Thu, 4 Mar 2010 19:39:53 +0000 (14:39 -0500)
Bugzilla/WebService.pm
Bugzilla/WebService/Bugzilla.pm
Bugzilla/WebService/Server.pm
Bugzilla/WebService/Server/JSONRPC.pm
Bugzilla/WebService/Server/XMLRPC.pm

index 21c6b8175f92235328e511cb7efe88295537741b..3db28142e9dbfed14ee4555e74aff4541503d4a3 100644 (file)
@@ -21,6 +21,8 @@ package Bugzilla::WebService;
 use strict;
 use Date::Parse;
 use XMLRPC::Lite;
+use Bugzilla::Util qw(datetime_from);
+use Scalar::Util qw(blessed)
 
 # Used by the JSON-RPC server to convert incoming date fields apprpriately.
 use constant DATE_FIELDS => {};
@@ -36,21 +38,24 @@ sub login_exempt {
 sub type {
     my ($self, $type, $value) = @_;
     if ($type eq 'dateTime') {
-        $value = datetime_format($value);
+        $value = $self->datetime_format_outbound($value);
     }
     return XMLRPC::Data->type($type)->value($value);
 }
 
-sub datetime_format {
-    my ($date_string) = @_;
-
-    my $time = str2time($date_string);
-    my ($sec, $min, $hour, $mday, $mon, $year) = localtime $time;
-    # This format string was stolen from SOAP::Utils->format_datetime,
-    # which doesn't work but which has almost the right format string.
-    my $iso_datetime = sprintf('%d%02d%02dT%02d:%02d:%02d',
-        $year + 1900, $mon + 1, $mday, $hour, $min, $sec);
-    return $iso_datetime;
+sub datetime_format_outbound {
+    my ($self, $date) = @_;
+
+    my $time = $date;
+    if (blessed($date)) {
+        # We expect this to mean we were sent a datetime object
+        $time->set_time_zone('UTC');
+    } else {
+        # We always send our time in UTC, for consistency.
+        # passed in value is likely a string, create a datetime object
+        $time = datetime_from($date, 'UTC');
+    }
+    return $iso_datetime = $time->iso8601();
 }
 
 
index 6e74900b9a84d707c30ad7eb109f51c294b827dd..a66871dc67982f5a69bed8ab3eefd494d4e858a3 100644 (file)
@@ -21,6 +21,7 @@ package Bugzilla::WebService::Bugzilla;
 use strict;
 use base qw(Bugzilla::WebService);
 use Bugzilla::Constants;
+use Bugzilla::Util qw(datetime_from);
 
 use DateTime;
 
@@ -49,32 +50,27 @@ sub extensions {
 
 sub timezone {
     my $self = shift;
-    my $offset = Bugzilla->local_timezone->offset_for_datetime(DateTime->now());
-    $offset = (($offset / 60) / 60) * 100;
-    $offset = sprintf('%+05d', $offset);
-    return { timezone => $self->type('string', $offset) };
+    # All Webservices return times in UTC; Use UTC here for backwards compat.
+    return { timezone => $self->type('string', "+0000") };
 }
 
 sub time {
     my ($self) = @_;
+    # All Webservices return times in UTC; Use UTC here for backwards compat.
+    # Hardcode values where appropriate
     my $dbh = Bugzilla->dbh;
 
     my $db_time = $dbh->selectrow_array('SELECT LOCALTIMESTAMP(0)');
+    $db_time = datetime_from($db_time, 'UTC');
     my $now_utc = DateTime->now();
 
-    my $tz = Bugzilla->local_timezone;
-    my $now_local = $now_utc->clone->set_time_zone($tz);
-    my $tz_offset = $tz->offset_for_datetime($now_local);
-
     return {
         db_time       => $self->type('dateTime', $db_time),
-        web_time      => $self->type('dateTime', $now_local),
+        web_time      => $self->type('dateTime', $now_utc),
         web_time_utc  => $self->type('dateTime', $now_utc),
-        tz_name       => $self->type('string', $tz->name),
-        tz_offset     => $self->type('string', 
-                                     $tz->offset_as_string($tz_offset)),
-        tz_short_name => $self->type('string', 
-                                     $now_local->time_zone_short_name),
+        tz_name       => $self->type('string', 'UTC'),
+        tz_offset     => $self->type('string', '+0000'),
+        tz_short_name => $self->type('string', 'UTC'),
     };
 }
 
index 9571e80307f9fb59038322fda24ad85f9f14a574..21f0f787c25132002712b9bab35942c3e37edb7d 100644 (file)
@@ -19,6 +19,7 @@ package Bugzilla::WebService::Server;
 use strict;
 
 use Bugzilla::Error;
+use Bugzilla::Util qw(datetime_from);
 
 sub handle_login {
     my ($self, $class, $method, $full_method) = @_;
@@ -29,4 +30,12 @@ sub handle_login {
     Bugzilla->login();
 }
 
+sub datetime_format_inbound {
+    my ($self, $time) = @_;
+    
+    my $converted = datetime_from($time, Bugzilla->local_timezone);
+    $time = $converted->ymd() . ' ' . $converted->hms();
+    return $time
+}
+
 1;
index f929b28ac86b8bae74219241464491c3a0e9328f..d07901a7f4d7213ec7a2213abf4bcaf081221bcb 100644 (file)
@@ -27,7 +27,6 @@ use base qw(JSON::RPC::Server::CGI Bugzilla::WebService::Server);
 use Bugzilla::Error;
 use Bugzilla::WebService::Constants;
 use Bugzilla::WebService::Util qw(taint_data);
-use Bugzilla::Util qw(datetime_from);
 
 sub new {
     my $class = shift;
@@ -77,20 +76,17 @@ sub type {
     }
     elsif ($type eq 'dateTime') {
         # ISO-8601 "YYYYMMDDTHH:MM:SS" with a literal T
-        $retval = $self->datetime_format($value);
+        $retval = $self->datetime_format_outbound($value);
     }
     # XXX Will have to implement base64 if Bugzilla starts using it.
 
     return $retval;
 }
 
-sub datetime_format {
-    my ($self, $date_string) = @_;
-
-    # YUI expects ISO8601 in UTC time; uncluding TZ specifier
-    my $time = datetime_from($date_string, 'UTC');
-    my $iso_datetime = $time->iso8601() . 'Z';
-    return $iso_datetime;
+sub datetime_format_outbound {
+    my $self = shift;
+    # YUI expects ISO8601 in UTC time; including TZ specifier
+    return $self->SUPER::datetime_format_outbound(@_) . 'Z';
 }
 
 
@@ -192,10 +188,10 @@ sub _argument_type_check {
             my $value = $params->{$field};
             if (ref $value eq 'ARRAY') {
                 $params->{$field} = 
-                    [ map { $self->_bz_convert_datetime($_) } @$value ];
+                    [ map { $self->datetime_format_inbound($_) } @$value ];
             }
             else {
-                $params->{$field} = $self->_bz_convert_datetime($value);
+                $params->{$field} = $self->datetime_format_inbound($value);
             }
         }
     }
@@ -220,14 +216,6 @@ sub _argument_type_check {
     return $params;
 }
 
-sub _bz_convert_datetime {
-    my ($self, $time) = @_;
-    
-    my $converted = datetime_from($time, Bugzilla->local_timezone);
-    $time = $converted->ymd() . ' ' . $converted->hms();
-    return $time
-}
-
 sub handle_login {
     my $self = shift;
 
index f06c81fc7764367b85eac6649c430d2485a66ca3..04e38c4a00411d7fb5bdbde1bcf5ca1f029697b1 100644 (file)
@@ -106,10 +106,12 @@ sub decode_value {
     
     # We convert dateTimes to a DB-friendly date format.
     if ($type eq 'dateTime.iso8601') {
-        # We leave off the $ from the end of this regex to allow for possible
-        # extensions to the XML-RPC date standard.
-        $value =~ /^(\d{4})(\d{2})(\d{2})T(\d{2}):(\d{2}):(\d{2})/;
-        $value = "$1-$2-$3 $4:$5:$6";
+        if ($value !~ /T.*[\-+Z]/i) {
+           # The caller did not specify a timezone, so we assume UTC.
+           # pass 'Z' specifier to datetime_from to force it
+           $value = $value . 'Z';
+        }
+        $value = $self->datetime_format_inbound($value);
     }
 
     return $value;