ZetCode

Perl date and time

last modified October 8, 2026

In this article we work with dates and times in Perl. We cover epoch seconds, the localtime and gmtime functions, formatting with POSIX::strftime, building epoch values with POSIX::mktime, and the Time::Piece module.

Perl stores a point in time as an integer number of seconds since the epoch, which is 00:00:00 UTC on January 1, 1970. The core functions localtime and gmtime convert such a number into calendar fields. The examples that print local times were run with the local time zone set to UTC (TZ=UTC); in another time zone the hours and epoch values differ.

Perl time function

The time function returns the current time as seconds since the epoch. Its value changes every second, so the example prints only facts that do not change between runs.

time.pl
#!/usr/bin/perl

use v5.34.0;
use warnings;

my $now = time;

say "time() returns an integer: ", ($now =~ /^\d+$/ ? "yes" : "no");
say "The value is after 2020-01-01: ", ($now > 1577836800 ? "yes" : "no");

The value 1577836800 is the epoch time of January 1, 2020 at midnight UTC.

$ ./time.pl
time() returns an integer: yes
The value is after 2020-01-01: yes

Perl localtime in scalar context

When localtime is called in scalar context, it returns a string with the date and time in the local time zone. We pass a fixed epoch value so the output is repeatable.

localtime_scalar.pl
#!/usr/bin/perl

use v5.34.0;
use warnings;

my $t = localtime(1700000000);
say "Scalar localtime: $t";

The string has the form Tue Nov 14 22:13:20 2023, that is, the weekday, month, day, time, and year.

$ TZ=UTC ./localtime_scalar.pl
Scalar localtime: Tue Nov 14 22:13:20 2023

Perl localtime in list context

In list context, localtime returns nine values: sec, min, hour, mday, mon, year, wday, yday, and isdst. Two offsets are easy to forget: year counts years since 1900, and mon is zero-based, so January is 0 and December is 11.

localtime_list.pl
#!/usr/bin/perl

use v5.34.0;
use warnings;

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

printf "Date: %04d-%02d-%02d\n", $year + 1900, $mon + 1, $mday;
printf "Time: %02d:%02d:%02d\n", $hour, $min, $sec;
say "wday: $wday (0 = Sunday)";
say "yday: $yday (0-based)";
say "isdst: $isdst";
printf "Date: %04d-%02d-%02d\n", $year + 1900, $mon + 1, $mday;

We add 1900 to $year and 1 to $mon to get the calendar year and month.

say "wday: $wday (0 = Sunday)";
say "yday: $yday (0-based)";

The weekday is 0 for Sunday through 6 for Saturday. The day of the year yday starts at 0 for January 1. The isdst flag is 1 when daylight saving time is in effect and 0 otherwise.

$ TZ=UTC ./localtime_list.pl
Date: 2023-11-14
Time: 22:13:20
wday: 2 (0 = Sunday)
yday: 317 (0-based)
isdst: 0

Perl gmtime

The gmtime function works like localtime, but it returns UTC values. It does not depend on the time zone, so it is useful for fixed reference points. gmtime(0) is the epoch itself.

gmtime.pl
#!/usr/bin/perl

use v5.34.0;
use warnings;

my $t = gmtime(0);
say "Scalar: $t";

my @parts = gmtime(0);
say "List: @parts";

The list form has the fields in the order sec, min, hour, mday, mon, year, wday, yday, isdst. For the epoch, the year field is 70 (1970), and the weekday field is 4 (Thursday).

$ ./gmtime.pl
Scalar: Thu Jan  1 00:00:00 1970
List: 0 0 0 1 0 70 4 0 0

Perl strftime

The strftime function from the core POSIX module formats a list of time fields using a format string, in the same way as the C library function. Here we use gmtime to get the fields.

strftime.pl
#!/usr/bin/perl

use v5.34.0;
use warnings;
use POSIX qw(strftime);

my @t = gmtime(1700000000);

say strftime("%Y-%m-%d %H:%M:%S", @t);
say strftime("%A, %B %d, %Y", @t);
say strftime("%a %b %e %I:%M %p", @t);

The format codes %Y, %m, and %d give the year, month, and day. %A and %B are the full weekday and month names, %e is the day padded with a space, and %I and %p give the 12-hour clock and AM/PM marker.

$ ./strftime.pl
2023-11-14 22:13:20
Tuesday, November 14, 2023
Tue Nov 14 10:13 PM

Perl mktime

The mktime function from POSIX does the reverse of localtime: it takes the calendar fields and returns an epoch value in the local time zone. The same offsets apply: the year is counted from 1900 and the month is zero-based.

mktime.pl
#!/usr/bin/perl

use v5.34.0;
use warnings;
use POSIX qw(mktime);

# year is years since 1900, month is 0-based: 123 = 2023, 11 = December
my $epoch = mktime(0, 0, 12, 25, 11, 123);

say "Epoch: $epoch";
say "Back: ", scalar localtime($epoch);

We build the epoch for December 25, 2023 at 12:00:00. We then convert the epoch back with localtime to check the result.

$ TZ=UTC ./mktime.pl
Epoch: 1703505600
Back: Mon Dec 25 12:00:00 2023

Perl Time::Piece

Time::Piece is a core module, included with Perl since version 5.10. It provides an object interface to dates and times. When it is loaded, localtime and gmtime return objects in scalar context, and the object has methods such as ymd, hms, and strftime.

timepiece.pl
#!/usr/bin/perl

use v5.34.0;
use warnings;
use Time::Piece;

my $t = gmtime(1700000000);

say "Date: ", $t->ymd;
say "Time: ", $t->hms;
say "Month: ", $t->monname;
say "Day: ", $t->fullday;
say "Custom: ", $t->strftime("%d.%m.%Y");

my $t2 = Time::Piece->strptime("2024-03-01", "%Y-%m-%d");
printf "Days until 2024-03-01: %.2f\n", ($t2 - $t)->days;

Subtracting two Time::Piece objects returns a Time::Seconds object, whose days method gives the difference in days. The strptime method parses a string into a Time::Piece object.

$ ./timepiece.pl
Date: 2023-11-14
Time: 22:13:20
Month: Nov
Day: Tuesday
Custom: 14.11.2023
Days until 2024-03-01: 107.07

Perl elapsed time

To measure elapsed time in a real program, store time in a variable before the work starts and subtract it afterwards. In this example we use two fixed epoch values, so the result is the same on every run.

elapsed.pl
#!/usr/bin/perl

use v5.34.0;
use warnings;

my $start = 1700000000;
my $end   = 1700093784;

my $elapsed = $end - $start;

my $days    = int($elapsed / 86400);
my $hours   = int(($elapsed % 86400) / 3600);
my $minutes = int(($elapsed % 3600) / 60);
my $seconds = $elapsed % 60;

say "Elapsed seconds: $elapsed";
printf "Elapsed: %d days, %02d:%02d:%02d\n", $days, $hours, $minutes, $seconds;
my $elapsed = $end - $start;

The difference between two epoch values is the number of seconds elapsed.

my $days    = int($elapsed / 86400);
my $hours   = int(($elapsed % 86400) / 3600);

There are 86400 seconds in a day and 3600 seconds in an hour. Integer division and the modulus operator split the total into days, hours, minutes, and seconds.

$ ./elapsed.pl
Elapsed seconds: 93784
Elapsed: 1 days, 02:03:04

In this article we have covered epoch seconds, localtime and gmtime, strftime, mktime, and Time::Piece in Perl.

Author

My name is Jan Bodnar, and I am a passionate programmer with extensive programming experience. I have been writing programming articles since 2007. To date, I have authored over 1,400 articles and 8 e-books. I possess more than ten years of experience in teaching programming.

List all Perl tutorials.