Bug 545299, XML-RPC WebService should take and return dates and times in UTC. POD
2010-03-04 Justin Wood <Callek@gmail.com> Bug 545299, XML-RPC WebService should take and return dates and times in UTC. Code part, r+=mkanat git-svn-id: svn://10.0.0.236/trunk@259875 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
parent
74e30442c8
commit
f3b0ed2a5a
@ -1 +1 @@
|
||||
7041
|
||||
7042
|
||||
@ -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) = @_;
|
||||
sub datetime_format_outbound {
|
||||
my ($self, $date) = @_;
|
||||
|
||||
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;
|
||||
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();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -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'),
|
||||
};
|
||||
}
|
||||
|
||||
@ -172,9 +168,7 @@ Use L</time> instead.
|
||||
|
||||
=item B<Description>
|
||||
|
||||
Returns the timezone of the server Bugzilla is running on. This is
|
||||
important because all dates/times that the webservice interface
|
||||
returns will be in this timezone.
|
||||
Returns the timezone that Bugzilla expects dates and times in.
|
||||
|
||||
=item B<Params> (none)
|
||||
|
||||
@ -183,12 +177,21 @@ returns will be in this timezone.
|
||||
A hash with a single item, C<timezone>, that is the timezone offset as a
|
||||
string in (+/-)XXXX (RFC 2822) format.
|
||||
|
||||
=item B<History>
|
||||
|
||||
=over
|
||||
|
||||
=item As of Bugzilla B<3.6>, the timezone returned is always C<+0000>
|
||||
(the UTC timezone).
|
||||
|
||||
=back
|
||||
|
||||
=back
|
||||
|
||||
|
||||
=item C<time>
|
||||
|
||||
B<UNSTABLE>
|
||||
B<EXPERIMENTAL>
|
||||
|
||||
=over
|
||||
|
||||
@ -207,8 +210,8 @@ A struct with the following items:
|
||||
|
||||
=item C<db_time>
|
||||
|
||||
C<dateTime> The current time in Bugzilla's B<local time zone>, according
|
||||
to the Bugzilla I<database server>.
|
||||
C<dateTime> The current time in UTC, according to the Bugzilla
|
||||
I<database server>.
|
||||
|
||||
Note that Bugzilla assumes that the database and the webserver are running
|
||||
in the same time zone. However, if the web server and the database server
|
||||
@ -217,8 +220,8 @@ rely on for doing searches and other input to the WebService.
|
||||
|
||||
=item C<web_time>
|
||||
|
||||
C<dateTime> This is the current time in Bugzilla's B<local time zone>,
|
||||
according to Bugzilla's I<web server>.
|
||||
C<dateTime> This is the current time in UTC, according to Bugzilla's
|
||||
I<web server>.
|
||||
|
||||
This might be different by a second from C<db_time> since this comes from
|
||||
a different source. If it's any more different than a second, then there is
|
||||
@ -227,26 +230,23 @@ rely on the C<db_time>, not the C<web_time>.
|
||||
|
||||
=item C<web_time_utc>
|
||||
|
||||
The same as C<web_time>, but in the B<UTC> time zone instead of the local
|
||||
time zone.
|
||||
Identical to C<web_time>. (Exists only for backwards-compatibility with
|
||||
versions of Bugzilla before 3.6.)
|
||||
|
||||
=item C<tz_name>
|
||||
|
||||
C<string> The long name of the time zone that the Bugzilla web server is
|
||||
in. Will usually look something like: C<America/Los Angeles>
|
||||
C<string> The literal string C<UTC>. (Exists only for backwards-compatibility
|
||||
with versions of Bugzilla before 3.6.)
|
||||
|
||||
=item C<tz_short_name>
|
||||
|
||||
C<string> The "short name" of the time zone that the Bugzilla web server
|
||||
is in. This should only be used for display, and not relied on for your
|
||||
programs, because different time zones can have the same short name.
|
||||
(For example, there are two C<EST>s.)
|
||||
|
||||
This will look something like: C<PST>.
|
||||
C<string> The literal string C<UTC>. (Exists only for backwards-compatibility
|
||||
with versions of Bugzilla before 3.6.)
|
||||
|
||||
=item C<tz_offset>
|
||||
|
||||
C<string> The timezone offset as a string in (+/-)XXXX (RFC 2822) format.
|
||||
C<string> The literal string C<+0000>. (Exists only for backwards-compatibility
|
||||
with versions of Bugzilla before 3.6.)
|
||||
|
||||
=back
|
||||
|
||||
@ -256,6 +256,10 @@ C<string> The timezone offset as a string in (+/-)XXXX (RFC 2822) format.
|
||||
|
||||
=item Added in Bugzilla B<3.4>.
|
||||
|
||||
=item As of Bugzilla B<3.6>, this method returns all data as though the server
|
||||
were in the UTC timezone, instead of returning information in the server's
|
||||
local timezone.
|
||||
|
||||
=back
|
||||
|
||||
=back
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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;
|
||||
@ -288,7 +290,9 @@ API via: C<http://bugzilla.yourdomain.com/xmlrpc.cgi>
|
||||
=head1 PARAMETERS
|
||||
|
||||
C<dateTime> fields are the standard C<dateTime.iso8601> XML-RPC field. They
|
||||
should be in C<YYYY-MM-DDTHH:MM:SS> format (where C<T> is a literal T).
|
||||
should be in C<YYYY-MM-DDTHH:MM:SS> format (where C<T> is a literal T). As
|
||||
of Bugzilla B<3.6>, Bugzilla always expects C<dateTime> fields to be in the
|
||||
UTC timezone, and all returned C<dateTime> values are in the UTC timezone.
|
||||
|
||||
All other fields are standard XML-RPC types.
|
||||
|
||||
@ -306,6 +310,14 @@ Normally, XML-RPC does not allow empty values for C<int>, C<double>, or
|
||||
C<dateTime.iso8601> fields. Bugzilla does--it treats empty values as
|
||||
C<undef> (called C<NULL> or C<None> in some programming languages).
|
||||
|
||||
Bugzilla accepts a timezone specifier at the end of C<dateTime.iso8601>
|
||||
fields that are specified as method arguments. The format of the timezone
|
||||
specifier is specified in the ISO-8601 standard. If no timezone specifier
|
||||
is included, the passed-in time is assumed to be in the UTC timezone.
|
||||
Bugzilla will never output a timezone specifier on returned data, because
|
||||
doing so would violate the XML-RPC specification. All returned times are in
|
||||
the UTC timezone.
|
||||
|
||||
Bugzilla also accepts an element called C<< <nil> >>, as specified by the
|
||||
XML-RPC extension here: L<http://ontosys.com/xml-rpc/extensions.php>, which
|
||||
is always considered to be C<undef>, no matter what it contains.
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user