time zone offset calc with localtime and gmtime

  • Thread starter Leendert Bottelberghs
  • Start date
L

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
 
G

Gunnar Hjalmarsson

Leendert said:
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.
 
L

Leendert Bottelberghs


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;

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...?
AFAIK, that's never happening.

I thought so. Thanx for your response,

-leendert bottelberghs
 
G

Geoff

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)
 
M

Mothra

Leendert Bottelberghs said:
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
(e-mail address removed).

Mothra
 
J

Joe Smith

Leendert said:
- 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
 
J

Joe Smith

Leendert said:
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
 
L

Leendert Bottelberghs

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
 
L

Leendert Bottelberghs

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
 
M

Mothra

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
 
L

Leendert Bottelberghs

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
make had returned bad status, install seems impossible
</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
 
M

Mothra

Leendert Bottelberghs said:
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:

Please report your failures to the DateTime Mailing list
(e-mail address removed) 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)
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::eek:ffset_as_string( ceil( ( $long / 15 ) ) * 60
*
60 );
}
elsif ( $long > 0 ) {
$offset =
DateTime::TimeZone::eek:ffset_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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,483
Members
44,902
Latest member
Elena68X5

Latest Threads

Top