# New Ticket Created by  Zefram 
# Please include the string:  [perl #127006]
# in the subject line of all future correspondence about this issue. 
# <URL: https://rt.perl.org/Ticket/Display.html?id=127006 >


> my $a = DateTime.new(:year(2000), :hour(13), :timezone(3600)); $a.Str
2000-01-01T13:00:00+01:00
> DateTime.new($a.Instant, :timezone(3630)).Str
DateTime formatter: offset 3630 not divisible by 60  in block <unit> at 
<unknown file>:1
2000-01-01T13:00:30+01:00

These two DateTime objects obviously represent the same point in time,
but they are being converted to ISO 8601 format as if they represent
different times, 30 seconds apart.  As the warning message alludes to,
ISO 8601 doesn't permit a seconds component in the zone offset, so there
is a problem in representing the zone offset.  But that doesn't prevent
the point in time being represented correctly.

To deal with non-minute timezones, you have a choice of three
not-entirely-satisfactory options.  Firstly, you could round the zone
offset (which you are almost doing) and adjust the represented local time
accordingly (which you are not doing), so the 3630 conversion above would
yield either "2000-01-01T13:00:00+01:00" or "2000-01-01T13:01:00+01:01".
Secondly, you could use the obvious extension of the ISO 8601 format
to a seconds component, outputting "2000-01-01T13:00:30+01:00:30".
Or finally you could signal an error (not just a warning) when trying
to represent a zone offset that's not an integral minute.

Incidentally, for offsets of -1 to -59 inclusive, your truncation of the
timezone offset isn't clearing the negative sign, so is producing the
invalid output "-00:00".  The zero offset is required to be represented
with a "+" sign.  If you take the rounding option described above,
anything that rounds to a zero-minutes offset must yield "+00:00" or
"Z" in the output.

-zefram

Reply via email to