Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Time::Local for a different time zone

Status
Not open for further replies.

Kirsle

Programmer
Jan 21, 2006
1,179
US
Something "strange" just happened with a site I'm developing that left me confused about time with Perl again.

Part of the web application I'm building includes a web blog, and there's a user-friendly way of specifying what time the blog should be posted with, where the hours/minutes/days/months etc are in individual text boxes, with JavaScript automatically keeping them up-to-date if the user wants it to.

So, when submitted, the site needs to turn the human-readable values they gave and turn it into an epoch time stamp when it saves the entry to the database.

The idea is that all blog entries are saved with Unix time stamps, so then the remote user (who might have their own time zone specified, or else they default to the server's time zone) can see the time stamps on the posts adjusted to match their own time zone. The user's time zone is saved as an offset of GMT time (e.g. -28800 for Pacific time), and the code to calculate the time stamp is as follows:

Code:
sub getTimestamp {
        my ($format,$epoch) = @_;

        # If no epoch time was given, use the current time.
        if (!defined $epoch || (defined $epoch && $epoch =~ /[^0-9]/)) {
                $epoch = time();
        }

        # Format the time.
        return Time::Format::time_format ($format,$epoch);
}

sub getLocalTimestamp {
        my ($format,$epoch,$tz) = @_;

        # If no epoch time, use the current time.
        if (!defined $epoch || (defined $epoch && $epoch =~ /[^0-9]/)) {
                $epoch = time();
        }

        # Get the current GMT time based on the server's localtime.
        my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = gmtime ($epoch);

        # Get the adjust epoch time back from this.
        my $gm = Time::Local::timelocal ($sec,$min,$hour,$mday,$mon,$year);
        $gm = $epoch unless defined $tz;

        # Offset the epoch time.
        if (defined $tz) {
                # Need to apply daylight saving time?
                if (isDST()) {
                        $tz += 3600;
                }
                $gm += $tz;
        }

        # Format the time.
        return getTimestamp ($format,$gm);
}

sub isDST {
        my ($isdst) = (localtime(time()))[8];
        return $isdst ? 1 : undef;
}

So the time stamp adjusted for the user would be called like:

Code:
my $ts = getLocalTimestamp ("Weekday, Month dd yyyy @ H:mm:ss AM", $epoch, $tz);

Anyway...

The issue I noticed was that, after transferring all the code to the other server, that if I posted a blog entry with the current time, it would actually start showing up with a time that was 3 hours in the past.

I found out that the problem was that my dev server had a Pacific time zone, and my production server was Eastern time. So, when the code did Time::Local::timelocal to turn my user-supplied time into unix time, it did so in the Eastern time zone, so that the resulting unix time is what `time()` would've been, on the east coast, when the date/time is what I gave it via the web front-end.

When I changed the server's time zone to Pacific, it worked; what also worked is getting it to show the correct time in different time zones. If I change the time zone back to Eastern after this point, it still shows the correct time. So it appears that all my code dealing with time zones is working fine, and the only weak link is turning the user-supplied time into unix time, and it seems like this is highly timezone-dependent.

So the question is: is there a way to make Time::Local give local time for a specific time zone? The idea is that if I can get the server to calculate unix time using the same time zone that the end user is probably using, that it would work correctly (i.e. so if server time is Eastern, and the end user is on Pacific, the time that the end user submits with the blog entry will be calculated into unix time in the Pacific time zone, instead of in Eastern).

Also if anyone sees any flaws in any of my other time-related code, feel free to point it out.

Cuvou.com | My personal homepage
Code:
perl -e '$|=$i=1;print" oo\n<|>\n_|_";x:sleep$|;print"\b",$i++%2?"/":"_";goto x;'
 
You could define $ENV{TZ} to be the value for the user's time zone before calling timelocal. Getting a list of all of the valid timezones with the various daylight savings variations could be the challenging part though, e.g. GMT, GMT0BST (UK with summer time), EST5EDT (US East coast), EST-10EDT (Australian East coast), etc.

Annihilannic.
 
how do you get a user's timezone?

"In complete darkness we are all the same, only our knowledge and wisdom separates us, don't let your eyes deceive you."

"If a shortcut was meant to be easy, it wouldn't be a shortcut, it would be the way!
 
The user provides their time zone when they create an account. If they're not logged in, it uses a default time zone from the site's configuration.

$ENV{TZ} looks like it'd work, but at this point I wouldn't be able to incorporate it into the project I'm using, since users provide their time zones as an offset in seconds from GMT.

I'll probably do something similar to my GMT-manipulating code from the getLocalTimestamp function, and turn their user-provided date and time into GMT and use their time zone offset on the unix time it gets back from it.

Kirsle.net | My personal homepage
Code:
perl -e '$|=$i=1;print" oo\n<|>\n_|_";x:sleep$|;print"\b",$i++%2?"/":"_";goto x;'
 
Is there no way of asking the browsers for the users current timestamp, timezone or other metric where you can then do the math?

"In complete darkness we are all the same, only our knowledge and wisdom separates us, don't let your eyes deceive you."

"If a shortcut was meant to be easy, it wouldn't be a shortcut, it would be the way!
 
JavaScript could probably calculate the user's time zone, but it would require that the user has JavaScript enabled, and I know enough people who have the NoScript plugin in their Firefox that it wouldn't be reasonable to expect all users to have JS enabled all the time.

But anyway, for the project I'm working on the user will have to be logged in to be able to post an entry where they can change the date/time so the site will have a reasonably good guess as to what time zone they're in since it's saved with their other user info on the server.

Kirsle.net | My personal homepage
Code:
perl -e '$|=$i=1;print" oo\n<|>\n_|_";x:sleep$|;print"\b",$i++%2?"/":"_";goto x;'
 
Dang, I was hoping for a way of getting this via perl, oh well.

"In complete darkness we are all the same, only our knowledge and wisdom separates us, don't let your eyes deceive you."

"If a shortcut was meant to be easy, it wouldn't be a shortcut, it would be the way!
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top