houseabsolute / DateTime-TimeZone

Time zone object base class and factory
https://metacpan.org/release/DateTime-TimeZone/
Other
9 stars 25 forks source link

Darwin Australia returning wrong offset #49

Closed redstorm1 closed 2 years ago

redstorm1 commented 2 years ago

Darwin is returning offset of +950 instead of +930 which causes results to be out by 20 minutes.

Ubuntu running Datetime-1.5.4.tar.gz

Darwin offset 950 Auckland offest 1200

DateTime-TimeZone/lib/DateTime/TimeZone/Australia/Darwin.pm

the offset is 34200 in the Darwin.pm file which is 950 which is wrong.

It should be 33480 seconds offset.

autarch commented 2 years ago

Two things ...

  1. Please share a code example demonstrating this.
  2. Do you have the latest version of DateTime::TimeZone installed?
redstorm1 commented 2 years ago
  1. yes updated all perl libs
  2. setting the servers timezone to Australia/Darwin returns correct offset of 930 in bash shell

!/usr/bin/perl

use DateTime; use DateTime::TimeZone;

my $tzone = 'Australia/Darwin'; my $tz = DateTime::TimeZone->new( name => $tzone );

my $dt = DateTime->now(); my $offset = $tz->offset_for_datetime($dt)/36; print "Darwin Offset: $offset\n"; $tzone = 'Pacific/Auckland'; $tz = DateTime::TimeZone->new( name => $tzone ); $offset = $tz->offset_for_datetime($dt)/36; print "Auckland Offset: $offset\n";

Auckland is 1200 Darwin should be 930 but is returning 950 (9.5hours is 9h 30m not 9h50m)

autarch commented 2 years ago

The $tz->offset_for_datetime($dt) method returns the offset in seconds. So for Darwin it's returning 34,200, which is 9.5 hours (an hour being 3600 seconds).

perl -E 'say 34200 / 3600'
9.5
autarch commented 2 years ago

BTW, there are some options for printing out the zone information in other ways using the DateTime->format_cldr method. See https://metacpan.org/pod/DateTime#CLDR-Patterns for your formatting options. Here's an example:

$> perl -MDateTime -E 'say DateTime->now(time_zone => q{Australia/Darwin})->format_cldr(q{ZZZZZ})'
+09:30
n1vux commented 2 years ago

Ahh, yes, i see: the line in the user script

$offset = $tz->offset_for_datetime($dt)/36;

is converting seconds to the very non-intuitive units of hundredths of hours (I guess that's centiHours?), not minutes nor hours:minutes as is more usual and intuitive.

Hence *`9.5 3600 / 36 == 950`** .

Interpreting this centiHours integer as HHMM character string is attractive, but wrong.

I concur.

redstorm1 commented 2 years ago

Thanks, i see where I have gone wrong now, will operate in epoch till needing to display human readable I think will solve my issue, using ceniHours this approach breaks when a offset is not an hour boundary. Thanks not a bug....

n1vux commented 2 years ago

will operate in epoch till needing to display human readable

excellent plan !

breaks when a offset is not an hour boundary

You are not alone!

A lot of TZ code trips on the edge-cases that crop up when first confronting time-zones ±0:30 to "normal", and sometimes again when (maybe a decade later) finally confronting the much rarer, ±0:15 (Nepal, Chatham Is., ACWST).

(Anyone who hasn't tripped on this is perhaps fibbing, or runs everything in NY or Zulu (UTC for the win!), or just old like me and doesn't remember every bug from decades ago anymore. :wink: )

(Edge-case use-case unit testing is your friend !)

(One of the advantages of collaborating with developers in India (or Darwin) is that one rapidly becomes acutely aware of half hour zones (at least), since 1/7 of the world's population is in IST UTC+05:30. But assuming that all TZ are ±HH:[03]0 will eventually bite on the 15' ones; and one can't even assume abs(HH) <= 12 as there are a couple wrap-arounds at the International Date Line (IDL) !!)