# time zone offset calc with localtime and gmtime

#### Do you have a question? Post it now! No Registration Necessary.  Now with pictures!

•  Subject
• Author
• Posted on

Hi there,

I want to calculate the time zone offset (as an integer), and I don't want
to depend on other modules.
I want to verify if the following code is correct:

<code>
my @lctime = localtime();
my @gmtime = gmtime();
# index 2 represent the hours
# index 8 represent isdst (daylight saving time boolean (0/1))

\$tzoffset = ((\$lctime[2] - \$lctime[8])-(\$gmtime[2] - \$gmtime[8]))%24);

</code>

I figured that if DST is applied locally, the clock is one hour ahead of
"normal" GMT (which hasn't DST applied), so this hour has to be deducted
from the time difference. If the GMT has DST set on, this hour has to be
added to the time difference, hence the double deduction.

Can anyone tell me if my my assumptions are correct?

TIA,

-leendert bottelberghs

## Re: time zone offset calc with localtime and gmtime

On Mon, 04 Apr 2005 17:07:04 +0200, "Leendert Bottelberghs"

>Hi there,
>
>I want to calculate the time zone offset (as an integer), and I don't want
>to depend on other modules.
>I want to verify if the following code is correct:
>
><code>
>my @lctime = localtime();
>my @gmtime = gmtime();
># index 2 represent the hours
># index 8 represent isdst (daylight saving time boolean (0/1))
>
>\$tzoffset = ((\$lctime[2] - \$lctime[8])-(\$gmtime[2] - \$gmtime[8]))%24);
>
></code>
>
>I figured that if DST is applied locally, the clock is one hour ahead of
>"normal" GMT (which hasn't DST applied), so this hour has to be deducted
>from the time difference. If the GMT has DST set on, this hour has to be
>added to the time difference, hence the double deduction.
>
>Can anyone tell me if my my assumptions are correct?
>
>TIA,
>
>-leendert bottelberghs
>

\$tzoffset, if you are going to make it an integer should be in units
of 1 second, not hours. There a places in the world where the offset
is not a whole hour. (e.g., Newfoundland, Tehran, Kabul, Rangoon,
Kathmandu, Darwin)

## Re: time zone offset calc with localtime and gmtime

Leendert Bottelberghs wrote:
> I want to calculate the time zone offset (as an integer), and I don't want
> to depend on other modules.

Why not?

> I figured that if DST is applied locally, the clock is one hour ahead of
> "normal"

That may be true in many countries, but can you rely on it?

> If the GMT has DST set on,

AFAIK, that's never happening.

--
Email: http://www.gunnar.cc/cgi-bin/contact.pl

## Re: time zone offset calc with localtime and gmtime

On Mon, 04 Apr 2005 17:34:31 +0200, Gunnar Hjalmarsson wrote:
>> I want to calculate the time zone offset (as an integer), and I don't
>> want to depend on other modules.
>
> Why not?

For different reasons:
- I use this in a module that will be used in mod_perl. I want to keep the
number of loaded modules as concise as possible, because of the server
memory overhead; - I want to be able to distribute this module without
people having to install other modules;

>> I figured that if DST is applied locally, the clock is one hour ahead
>> of "normal"
>
> That may be true in many countries, but can you rely on it?

I truly don't know. That's part of the reason I posted this ;) Anyone...?

>> If the GMT has DST set on,
>
> AFAIK, that's never happening.

I thought so. Thanx for your response,

-leendert bottelberghs

## Re: time zone offset calc with localtime and gmtime

> I truly don't know. That's part of the reason I posted this ;) Anyone...?

You may want to bring this up on the DateTime mailing list
datetime-subscribe@perl.org.

Mothra

## Re: time zone offset calc with localtime and gmtime

Leendert Bottelberghs wrote:

> - I use this in a module that will be used in mod_perl. I want to keep the
> number of loaded modules as concise as possible, because of the server
> memory overhead; - I want to be able to distribute this module without
> people having to install other modules;

Well, is it safe to use the modules that come bundled with perl, so
you might as well use them.
-Joe

## Re: time zone offset calc with localtime and gmtime

On Tue, 05 Apr 2005 00:35:32 -0700, Joe Smith wrote:
> Leendert Bottelberghs wrote:
>
>> - I use this in a module that will be used in mod_perl. I want to keep the
>> number of loaded modules as concise as possible, because of the server
>> memory overhead; - I want to be able to distribute this module without
>> people having to install other modules;
>
> Well, is it safe to use the modules that come bundled with perl, so
> you might as well use them.

You're absolutely right. Which standard module would you recommend?

-leendert

## Re: time zone offset calc with localtime and gmtime

Leendert Bottelberghs wrote:

> I want to calculate the time zone offset (as an integer)

The international standard for time zone offset is a five-character
string.  A plus or minus sign, two digits for hours, two digits for
minutes.

Date: Mon, 04 Apr 2005 17:07:04 +0200
NNTP-Posting-Date: Mon,  4 Apr 2005 15:06:45 +0000 (UTC)
US-Pacific-Date: Mon, 04 Apr 2005 08:06:45 -0800 (PDT)

The last two digits are not always "00".

grep ' [-+][0-9][0-9][1-9]' /usr/lib/perl5/site_perl/5.8.3/Date/Manip.pm
#"nst   -0330 ".  # Newfoundland Standard  nst=North Sumatra +0630
"nft    -0330 ".  # Newfoundland
"ndt    -0230 ".  # Newfoundland Daylight
"it     +0330 ".  # Iran
"ist    +0530 ".  # Indian Standard
"nst    +0630 ".  # North Sumatra       nst=Newfoundland Std -0330
"acst   +0930 ".  # Australian Central Standard
"cast   +0930 ".  # Central Australian Standard
"acdt   +1030 ".  # Australian Central Daylight
"cadt   +1030 ".  # Central Australian Daylight

-Joe

## Re: time zone offset calc with localtime and gmtime

On Tue, 05 Apr 2005 00:46:45 -0700, Joe Smith wrote:
> Leendert Bottelberghs wrote:
>> I want to calculate the time zone offset (as an integer)
> The international standard for time zone offset is a five-character
> string.  A plus or minus sign, two digits for hours, two digits for
> minutes.

Youre right. So I have to use POSIX to be able to calculate the difference
in seconds. I now have the following to calculate and format the time
offset:

<code>
# calculate the time difference in seconds;
my \$secoffset = timelocal(localtime()) - timelocal(gmtime());

# translate it to minutes and apply the DLT difference
my \$minoffset = (\$secoffset / 60) + ((gmtime)[8] - (localtime)[8])*60;

# translate it to "hour-format", so that 90 will be 130,
# and -90 will be -130
my \$tzoffset = int(\$minoffset/60)*100 +
(\$minoffset/abs(\$minoffset))*(\$minoffset%60);

# apply final formatting, including +/- sign and 4 digits.
my \$tzstr = sprintf "%+05d", \$tzoffset;

</code>

Maybe I'll use Date::Manip after all.

-leendert bottelberhs

## Re: time zone offset calc with localtime and gmtime

> Maybe I'll use Date::Manip after all.
>
> -leendert bottelberhs

Yor are reinventing what we already have done in the DateTime Project

use strict;
use warnings;
use diagnostics;
use DateTime;

my \$dt = DateTime->now(time_zone => 'America/Chicago');

print \$dt->offset();

printed results
me.pl
-18000

Hope this helps

## Re: time zone offset calc with localtime and gmtime

On Tue, 05 Apr 2005 06:20:15 -0700, Mothra wrote:
>
> Yor are reinventing what we already have done in the DateTime Project

I know, and I'm not entirely happy with it. But there are good reasons for
it. First of all, I couldn't get the DateTime module installed with CPAN.
Besides the fact that it depends on about a douzen other modules (and it
installs about 60), it just wouldn't compile (running RH8, perl 5.8.0). It
returned:

<snippet>
/usr/bin/make  -- NOT OK
Running make test
Can't test without successful make
Running make install
</snippet>

The second reason I already mentioned: it depends on loads of other
modules. Since the module I'm writing is part of a larger project, I don't
want to force other people (on varying OSs) to install this large amount
of third-party modules.

> use strict;
> use warnings;
> use diagnostics;
> use DateTime;
>
>
> my \$dt = DateTime->now(time_zone => 'America/Chicago');
>
> print \$dt->offset();

Do you have to specify the timezone manually? And can the offset be
formatted in the "standard" timezone-offset way automatically with this
module?

Thanx for you time and response,

-leendert bottelberghs

## Re: time zone offset calc with localtime and gmtime

> On Tue, 05 Apr 2005 06:20:15 -0700, Mothra wrote:
> >
> > Yor are reinventing what we already have done in the DateTime Project
>
> I know, and I'm not entirely happy with it. But there are good reasons for
> it. First of all, I couldn't get the DateTime module installed with CPAN.
> Besides the fact that it depends on about a dozen other modules (and it
> installs about 60), it just wouldn't compile (running RH8, perl 5.8.0). It
> returned:

datetime@perl.org if you are having problems installing DateTime
we need to know about it.

>
> The second reason I already mentioned: it depends on loads of other
> modules. Since the module I'm writing is part of a larger project, I don't
> want to force other people (on varying OSs) to install this large amount
> of third-party modules.

You would be better off installing DateTime that reinventing the wheel. As
far
as I know it is the only suite of modules that incorporate the Olson
Timezone
Database. Timezone conversion is fully supported (along with offsets)

>
> > use strict;
> > use warnings;
> > use diagnostics;
> > use DateTime;
> >
> >
> > my \$dt = DateTime->now(time_zone => 'America/Chicago');
> >
> > print \$dt->offset();
>
> Do you have to specify the timezone manually? And can the offset be
> formatted in the "standard" timezone-offset way automatically with this
> module?

Yes, you can use the naming convention provided with datetime or
you can specify an offset. I ran into a similar issue when writting the
tests
for the Sunrise module. I could not use the standard naming provided with
DateTime I had to use the offset, something like this

use strict;
use warnings;
use diagnostics;
use DateTime;
use DateTime::TimeZone;
use POSIX qw(floor ceil);

use vars qw(\$long \$lat \$offset \$dt);

\$dt = DateTime->now;

while (<DATA>) {
/(\w+),\s+(\w+)\s+(\d+)\s+(\d+)\s+(\w)\s+(\d+)\s+(\d+)\s+(\w)\s+sunrise:\s+(
\d+:\d+)\s+sunset:\s+(\d+:\d+)/;

\$lat = sprintf( "%.3f", ( \$3 + ( \$4 / 60 ) ) );
\$long = sprintf( "%.3f", -( \$6 + ( \$7 / 60 ) ) );
if ( \$long < 0 ) {
\$offset =
DateTime::TimeZone::offset_as_string( ceil( ( \$long / 15 ) ) * 60
*
60 );
}
elsif ( \$long > 0 ) {
\$offset =
DateTime::TimeZone::offset_as_string( floor( ( \$long / 15 ) ) * 60
*
60 );
}

}

\$dt->set_time_zone(\$offset);

print \$dt->offset;
__DATA__
Darwin, Australia 12 28 S 130 51 E sunrise: 05:36 sunset: 17:00

I hope this helps