Skip to content

Perl Date & Time

Perl provides built-in functions for basic date and time operations. For more complex tasks, powerful modules like Time::Piece (core module since Perl 5.10) and DateTime (from CPAN) are highly recommended.

The localtime() function is the primary way to get the current local date and time. Without arguments, it uses the current system time.

In list context, localtime() returns a 9-element list:

# Element Description Range
# -------------------------------------------------------
# $sec seconds 0-60 (60 for leap second)
# $min minutes 0-59
# $hour hours 0-23
# $mday day of the month 1-31
# $mon month 0-11 (January is 0)
# $year year since 1900 (e.g., 123 for 2023)
# $wday day of the week 0-6 (Sunday is 0)
# $yday day of the year 0-365 (365 for leap year)
# $isdst daylight saving time flag (true if DST is in effect)

Example of using localtime() in list context:

#!/usr/bin/env perl
use strict;
use warnings;
my @months = qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec);
my @days = qw(Sun Mon Tue Wed Thu Fri Sat);
my ($sec, $min, $hour, $mday, $mon, $year_offset, $wday, $yday, $isdst) =
localtime();
my $year = 1900 + $year_offset;
print "Date: $days[$wday], $months[$mon] $mday, $year\n";
print "Time: $hour:$min:$sec\n";
print "Day of year: $yday\n";
print "DST in effect: ", ($isdst ? "Yes" : "No"), "\n";

When executed, this might produce (depending on the current date/time):

Date: Sat, Feb 16, 2024
Time: 14:30:55
Day of year: 46
DST in effect: No

In scalar context, localtime() returns a human-readable string:

#!/usr/bin/env perl
use strict;
use warnings;
my $datestring = localtime();
print "Current local date and time: $datestring\n";

Output:

Current local date and time: Sat Feb 16 14:30:55 2024

The gmtime() function works identically to localtime(), but it returns the time components localized for the Greenwich Mean Time (GMT) or Coordinated Universal Time (UTC) zone. The $isdst element from gmtime() in list context is always 0, as GMT/UTC does not observe daylight saving time.

#!/usr/bin/env perl
use strict;
use warnings;
my $gmt_datestring = gmtime();
print "Current GMT/UTC date and time: $gmt_datestring\n";
my (undef, undef, undef, $mday, $mon, $year_offset) = gmtime();
my $year = 1900 + $year_offset;
printf "GMT Date: %04d-%02d-%02d\n", $year, $mon + 1, $mday;

Output (assuming local time was US Central, 6 hours behind UTC):

Current GMT/UTC date and time: Sat Feb 16 20:30:55 2024
GMT Date: 2024-02-16

You can use the elements from localtime() or gmtime() with printf or sprintf for custom formatting:

#!/usr/bin/env perl
use strict;
use warnings;
my ($sec, $min, $hour, $mday, $mon, $year_offset) = localtime();
my $year = 1900 + $year_offset;
$mon += 1; # Adjust month to be 1-12
printf("Formatted Time (HH:MM:SS): %02d:%02d:%02d\n", $hour, $min, $sec);
printf("Formatted Date (YYYY-MM-DD): %04d-%02d-%02d\n", $year, $mon, $mday);

Output:

Formatted Time (HH:MM:SS): 14:30:55
Formatted Date (YYYY-MM-DD): 2024-02-16

The time() function returns the number of seconds that have elapsed since the Unix epoch (00:00:00 UTC, January 1, 1970). This is often called a Unix timestamp.

#!/usr/bin/env perl
use strict;
use warnings;
my $epoch_seconds = time();
print "Seconds since Jan 1, 1970 UTC: $epoch_seconds\n";
# You can pass an epoch timestamp to localtime() or gmtime()
my $one_day_ago_epoch = $epoch_seconds - (24 * 60 * 60);
my $datestring_one_day_ago = localtime($one_day_ago_epoch);
print "One day ago: $datestring_one_day_ago\n";

Output:

Seconds since Jan 1, 1970 UTC: 1708093855
One day ago: Fri Feb 15 14:30:55 2024

For more flexible formatting, the POSIX module provides the strftime() function. It formats a date and time according to a format string, similar to the C library function of the same name.

strftime(format, sec, min, hour, mday, mon, year, wday (optional), yday (optional), isdst (optional))

Common strftime() format specifiers (locale-dependent ones marked with *):

SpecifierDescriptionExample (for Sat Feb 16 14:30:55 2024 CST)
%aAbbreviated weekday name *Sat
%AFull weekday name *Saturday
%bAbbreviated month name *Feb
%BFull month name *February
%cLocale’s appropriate date and time representation *Sat Feb 16 14:30:55 2024
%CCentury (year divided by 100 and truncated to an integer)20
%dDay of the month, zero-padded (01-31)16
%DShort MM/DD/YY date, equivalent to %m/%d/%y02/16/24
%eDay of the month, space-padded ( 1-31)16
%FISO 8601 date format (YYYY-MM-DD), equivalent to %Y-%m-%d2024-02-16
%gWeek-based year, last two digits (00-99)07
%GWeek-based year (e.g., 2024)2024
%hAbbreviated month name * (same as %b)Feb
%HHour in 24h format (00-23)14
%IHour in 12h format (01-12)02
%jDay of the year, zero-padded (001-366)047
%mMonth as a decimal number, zero-padded (01-12)02
%MMinute, zero-padded (00-59)30
%nNewline character\n
%pAM or PM designation for 12-hour clock *PM
%r12-hour clock time * (e.g., hh:mm:ss AM/PM)02:30:55 PM
%R24-hour HH:MM time, equivalent to %H:%M14:30
%SSecond, zero-padded (00-60)55
%tHorizontal tab character\t
%TISO 8601 time format (HH:MM:SS), equivalent to %H:%M:%S14:30:55
%uISO 8601 weekday as number (Monday=1, Sunday=7)6
%UWeek number of the year (Sunday as first day of week) (00-53)07
%VISO 8601 week number of year (Monday as first day of week) (01-53)07
%wWeekday as a decimal number (Sunday=0, Saturday=6)6
%WWeek number of the year (Monday as first day of week) (00-53)07
%xLocale’s appropriate date representation *02/16/24
%XLocale’s appropriate time representation *14:30:55
%yYear, last two digits (00-99)24
%YYear (e.g., 2024)2024
%zISO 8601 offset from UTC in timezone (e.g., +hhmm or -hhmm)-0600
%ZTimezone name or abbreviation *CST
%%A literal % character%

Example using POSIX::strftime():

#!/usr/bin/env perl
use strict;
use warnings;
use POSIX qw(strftime);
my @time_parts = localtime(); # Get current local time parts
# Note: strftime expects year as (current year - 1900)
# and month as 0-11, which localtime() provides directly.
my $formatted_string = strftime "%Y-%m-%d %H:%M:%S %Z (%A)", @time_parts;
print "Formatted local time: $formatted_string\n";
my @gmt_time_parts = gmtime();
my $gmt_formatted_string = strftime "%Y-%m-%dT%H:%M:%SZ (%A)", @gmt_time_parts;
print "Formatted GMT/UTC time: $gmt_formatted_string\n";

Output:

Formatted local time: 2024-02-16 14:30:55 CST (Saturday)
Formatted GMT/UTC time: 2024-02-16T20:30:55Z (Saturday)

Since Perl 5.10, Time::Piece has been a core module, offering an object-oriented approach to date and time manipulation that is often easier to use than raw localtime/gmtime and strftime.

#!/usr/bin/env perl
use strict;
use warnings;
use Time::Piece;
use Time::Seconds; # For constants like ONE_DAY
my $t = localtime(); # Creates a Time::Piece object for current local time
print "Current time: ", $t->datetime, "\n"; # YYYY-MM-DDTHH:MM:SS
print "Formatted: ", $t->strftime("%A, %B %d, %Y, %I:%M %p"), "\n";
print "Epoch seconds: ", $t->epoch, "\n";
my $tomorrow = $t + ONE_DAY;
print "Tomorrow: ", $tomorrow->date, "\n"; # YYYY-MM-DD
my $custom_time = Time::Piece->strptime("2023-07-15 10:00:00", "%Y-%m-%d %H:%M:%S");
print "Custom time: ", $custom_time->strftime("%c"), "\n";

For more advanced date/time operations, including complex timezone handling, date arithmetic, parsing various formats, and internationalization, the DateTime suite of modules from CPAN is the de facto standard in the Perl community. It’s very powerful and comprehensive.

#!/usr/bin/env perl
use strict;
use warnings;
use DateTime;
my $dt = DateTime->now(time_zone => 'local'); # Current local time
print "DateTime now: ", $dt->iso8601, " (", $dt->time_zone_long_name, ")\n";
my $dt_ny = DateTime->now(time_zone => 'America/New_York');
print "New York time: ", $dt_ny->strftime('%Y-%m-%d %H:%M:%S %Z'), "\n";
$dt->add(days => 5, hours => 3);
print "After adding 5 days, 3 hours: ", $dt->datetime, "\n";
# Requires 'cpanm DateTime' or similar to install.

Recommendation: For new projects, prefer Time::Piece for simpler tasks and DateTime for more complex requirements over the older, procedural functions, due to their improved clarity, robustness, and feature sets.