This part of the Perl Tutorial series is explaining time in perl.

Perl has a built in function called time() that will return a nice, 10 digit long number representing the seconds elapsed since the "epoch" which is 1 January 1970 on most operating systems.

$t = time();         # returns a number like this: 1021924103

You can use this as a timestamp, for example to check elapsed time. You can save the seconds at one point in your code by calling time() and then calling time() again. Finally comparing the result of the two calls:

my $t = time();
# lots of code
say 'Elapsed time: ', (time() - $t);

localtime

There is another function called localtime() that can take the above, 10 digit representation of time, and turn it into some human readable format:

my $then = localtime($t);  # returns a string such as       Thu Feb 30 14:15:53 1998

It actually does not even need an argument. If called without any argument it will call time() by itself and

my $now = localtime();    # returns the string for the current time

You can save several timestamps in a program generated by time(), and later you can use them to compute elapsed times, or to turn them into such user friendly form as we saw above.

The other localtime

What happens if we call the same localtime($t) as above but this time we assign it to an array? Would you expect to get the same string as above in the first element of the array?

my @then = localtime($t);

The array will be filled with the following values:

53 15 14 30 1 98 4 61 0

What are these strange numbers? You might ask. If you look more closely, you'll notice that the first value holds the seconds, followed by the minutes, then hours and a few other numbers representing the same point in time. The full list is here:

my ($sec ,$min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime(time);
$sec   - seconds (0-59)
$min   - minutes (0-59)
$hour  - hours  (0-23)
$mday  - 'month day' or day of the month (1-31)
$mon   - month (0-11) - 0 is January, 11 is December.
$year  - YEAR-1900
$wday  - 'week day' or day of the week (0-6), 0 is Sunday, 1 is Monday
$yday  - 'year day' or day of the year (0-364 or 0-365 in leap years)
$isdst - 'is daylight saving time' true if daylight saving time is on in your computer. Otherwise false.

Note that, in the field representing the month 0 means January, and 11 means December. In the field representing the week day 0 means Sunday and 6 means Saturday.

On the other hand the field representing the day of the month ranges from 1-28,30 or 31 depending on the month.

The most problematic of all might be the field representing the year. It can easily lead to a Y2K bug:

Year 2000 bug

When in 1998 people saw the $year being 98 and wanted to print 1998 they wrote "19$year". That worked for them. It even worked in 1999, but then the year 2000 came, and $year became 2000-1900 = 100. Their nicely formatted string became 19100.

That's where the year 19100 came from. That's exactly how people created code with the infamous Year 2000 bug.

If they had read the documentation, they would have written:

1900 + $year

which is the correct way to get back the real number of our date used in the Gregorian calendar. The most commonly used calendar around the world.

gmtime

Perl also has function called gmtime() that does the same as localtime(), but it provides the time in Greenwich, a neighborhood in London. (The $isdst is alway 0 in this case.)

How does time really work?

Normally your computer's hardware clock should be set to GMT (Greenwich Mean Time) (or rather UTC which is more or less the same).

Your operating system (Windows, Linux, Mac OSX, Unix etc.) should know about the time zone you configured, and whether Daylight Saving Time is in effect. localtime() takes into account these values while gmtime() just uses the raw value from the hardware clock.

High precision time

The built-in time() function returns the current time in seconds. That means it cannot measure shorter time periods than a second. If you need higher precision in time measuring, there is a module called Time::HiRes that can provide a replacement for the time() function.

use strict;
use warnings;
use 5.010;

use Time::HiRes qw(time);

say time;

And the output is:

1021924103.58673

DateTime

While the above functions can provide you with basic time and date manipulations, probably anything beyond the most simple need is better served by the DateTime module from CPAN.

We will learn about it later.

Context awareness

All the above is important, but there is one very important aspect of all this talk. We slightly skipped over this major issue of Perl for which the localtime() function is just one example.

If you look back in the example, you might notice that the localtime() function somehow knows if its return value is going to be assigned to a scalar variable, or an array, and returns either a human readable representation of time, or this other, 9-number representation of the same time.

This is a general feature of Perl 5. A very important feature, and we are going to learn about it a lot more. The important thing here is to understand that in many situations Perl is context sensitive.