FutureQuest, Inc. FutureQuest, Inc. FutureQuest, Inc.
Knowledgebase: CGI/Perl
Programmatic Time Usage With Perl
Posted on 24 October 2003 05:54 PM

This information is intended for anyone using time functions in their scripts or if you just want a better understanding of how Perl's time functions are used.

The bottom line is that IF you have used the right time function for the right purpose and IF your server is properly configured (and the FutureQuest servers are properly configured) then the whole world can change around you without you having to miss a minute of sleep.

Programmatic Time Usage With Perl

Brief summary of tips for using time functions in Perl:

  • GMT = Grenwich Mean Time = UTC = Universal Coordinated Time. UTC is now the preferred usage.

  • If your programs are returning correct time results and continue to return correct time results through time zone changes, then you are using the functions correctly.

  • If you constantly have to modify your programs (adding an hour, subtracting an hour) whenever time zones change, then you are not using the functions correctly. (Keep reading.)

  • Time functions and what they take as arguments and what they return:

But first a definition:

Some functions take a seconds argument and return the various date/time elements of seconds, hours, month, etc. I refer to this as the broken-down time list.

A broken-down time list example:

my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst);

Functions returning a list of broken-down time elements will return them in the order listed above.

0 <= sec <= 60

0 <= min <= 59

0 <= hour <= 23

1 <= mday <= 31, the day of the month

0 <= mon <= 11 , 0=Jan, 1=Feb, 2=Mar, etc.

year has 1900 subtracted from it, i.e. years since 1900. The year 1999 is 99 and the year 2000 is 100.

0 <= wday <= 6 , the day of the week , 0=Sunday, 1=Monday, 2=Tuesday, etc.

1 <= yday <= 366 , the day of the year

isdst = {0,1} , 0=DST (Daylight Saving Time) not in effect, 1= DST in effect

The isdst argument will rarely be used and is not needed to accurately display the time, so we will ignore it in the rest of our discussion.

Now, the functions:

(times)[0] - returns CPU seconds and fractions of a second that the current process has been executing.

time() - returns the number of non-leap seconds since the epoch (January 1, 1970 UTC, on Unix systems)

gmtime(seconds) - returns list of broken-down time representing seconds in UTC

ex: ($sec,$min,$hour,etc...) = gmtime(time)
returns the current time in UTC. (isdst is always equal to 0 for UTC.)

timegm(broken-down time) - returns seconds

ex: $gmTimeInSeconds = timegm($sec,$min,$hour, etc...)

localtime(seconds) - returns list of broken-down times

ex: ($sec,$min,$hour,etc...) = localtime(time)
returns the current local time based on the current time zone setting (see #9, below)

timelocal(broken-down time) - returns seconds

ex: $localTimeInSeconds = timelocal($sec,$min,$hour,etc...)
  • The timegm() and timelocal() functions will need a use statement:
    use Time::Local;

  • If you only care about timing something within the current process (script), use (times)[0] called at the
    appropriate places. However, if you need to attach date/time significance to things, use the other functions.

  • If you are timing how long something takes then you can just perform all calculations using gmtime() and timegm(), assuming you need the time/date functionality and the Perl times() is not sufficient.

  • If you need to display a date/time in anything other than UTC, then convert the time at the point that you need to display it using localime(time in seconds).

  • Time Zones: localtime() and timelocal() will always represent the time based on the value of the time zone environment variable if it has been set, or the value of the server's "time zone symbolic link" if the time zone environment variable has not been set.

The FutureQuest server's time zone symbolic link is stored at /etc/localtime. This symbolic link currently points to /usr/share/zoneinfo/US/Eastern, the time zone in which the server is located.

The time zone environment variable is TZ. You set it like this:
$ENV{TZ} = ':/usr/share/zoneinfo/US/Eastern';

This sets the TZ environment variable to the US/Eastern time zone. Note the use of the leading ":" which is required. You can use 'ls' at the command line (i.e., via SSH) to get a listing of all the time zones contained in the /usr/share/zoneinfo directory and its subdirectories. Or, you can visit www.timezoneconverter.com/cgi-bin/tzref.tzc which lists all the timezones that can be used. Simply tack on whatever time zone you want to use to the string ':/usr/share/zoneinfo/'. Note that all time zone usage is case sensitive.

Example #1:

You have performed all your time/date operations using gmtime() and timegm() and now have your date/time represented as SECONDS stored in $TimeInSeconds and you want to display this time in the Europe/Paris time zone.

use Time::Local;
my @dayofweek = (qw(Sunday Monday Tuesday Wednesday Thursday Friday Saturday));
my @monthnames = (qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec));
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday);
$ENV{TZ} = ':/usr/share/zoneinfo/Europe/Paris';
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday) = localtime($TimeInSeconds);
$year += 1900;
print "This date is $dayofweek[$wday], $monthnames[$mon] $mday, $yearn";
print "This time is $hour:$min:$secn";

Example #2:

You have performed all your time/date operations using gmtime() and timegm() and now have your date/time represented as a UTC broken-down time stored in the variables $sec, $min, etc., and you want to display this time in the Europe/Paris time zone.

use Time::Local;
my $TimeInSeconds;
#convert from UTC to Europe/Paris
$ENV{TZ} = ':/usr/share/zoneinfo/Europe/Paris';
#convert broken-down time to seconds in UTC
$TimeInSeconds = timegm($sec,$min,$hour,$mday,$mon,$year,$wday,$yday);
#convert the UTC seconds to broken-down time in time zone
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday) = localtime($TimeInSeconds);
  • When you display a time, ALWAYS, ALWAYS, ALWAYS display the time zone that the time represents so your reader can give the time some context.

  • When you store a date/time variable (such as in a file), ALWAYS, ALWAYS, ALWAYS store the variable in UTC.

The above was submitted by Rich from TimeZoneConverter.com.