Dates, Times, and Timezones (in perl)
Deprecated: ord(): Providing a string that is not one byte long is deprecated. Use ord($str[0]) instead in /project/www/devpit.org/mediawiki-1.23.8/includes/cache/MessageCache.php on line 731
Deprecated: ord(): Providing a string that is not one byte long is deprecated. Use ord($str[0]) instead in /project/www/devpit.org/mediawiki-1.23.8/includes/cache/MessageCache.php on line 739
Deprecated: Creation of dynamic property PPDStack::$accum is deprecated in /project/www/devpit.org/mediawiki-1.23.8/includes/parser/Preprocessor_DOM.php on line 754
Deprecated: Constant E_STRICT is deprecated since 8.4, the error level was removed in /project/www/devpit.org/mediawiki-1.23.8/includes/GlobalFunctions.php on line 2409
From Devpit
Contents
Notes on terminology
- A timezone is a specific offset from UTC. So CST and CDT are timezones. CST6CDT is not.
- A tzspec is a specification for the timezone used in a particular part of the world, for example, CST6CDT or CST6.
- Epoch_seconds is a timestamp expressed in seconds since the Unix epoch.
- I use CST6CDT, CST, and CDT here as placeholders for any arbitrary timezone.
Printing a Non-Local Time
use Date::Format ();
use Time::Zone ();
my $epoch_seconds = time();
my $tzspec = "CST6CDT";
print Date::Format::time2str("%a %Y-%m-%d %H:%M:%S %Z", $epoch_seconds, Time::Zone::tz2zone($tzspec, $epoch_seconds)), "\n";
Time::Zone::tz2zone() calculates whether $epoch_seconds is during the time of year the timezone is CST or CDT.
Date::Format::time2str() formats $epoch_seconds with a specific timezone (not a tzspec).
Interpreting a Time Entered By A User
This is much harder than it sounds. You (not the user) are responsible for figuring out whether the time entered by the user should be interpreted as CST or CDT. This has nothing to do with the current time. If the user enters July 1 11pm, that should always be interpreted as CDT (unless the user specifically enters a timezone). Similarly, January 1 11pm should always be interpreted as CST. To complicate things, Date::Parse isn't very smart; you can't pass it a tzspec {grumble}. Obviously there is an hour a year where time timezone the user wants is only a guess, but Date::Parse::str2time() always lets the user override it to any timezone.
use Date::Parse (); use Time::Zone (); my $user_input = "June 23, 2005 4:43pm"; my $tzspec = "CST6CDT"; # Figure out the timezone. First, interpret what the user entered with a # guessed timezone so str2time() has something to work with that is at most # an hour off (not half-way around the world). Then use tz2zone() to figure # out what timezone that time of year should use. Finally, re-execute # str2time() to get the output in the correct timezone for that time of year. my $timezone = Time::Zone::tz2zone($tzspec, 1); # Guess at $timezone my $epoch_seconds = Date::Parse::str2time($user_input, $timezone); # May be an hour off $timezone = Time::Zone::tz2zone($tzspec, $epoch_seconds); # Now correct $epoch_seconds = Date::Parse::str2time($user_input, $timezone); # Now correct print $epoch_seconds, "\n";
As far as I know, this code should always "do the right thing". If the user types "EDT" after their input, it will always be interpreted as EDT, even if you set $tzspec to CST6CDT and even if it's winter. (See Date::Parse's docs.)