[perl] How do I convert a date/time to epoch time (unix time/seconds since 1970) in Perl?

Given a date/time as an array of (year, month, day, hour, minute, second), how would you convert it to epoch time, i.e., the number of seconds since 1970-01-01 00:00:00 GMT?

Bonus question: If given the date/time as a string, how would you first parse it into the (y,m,d,h,m,s) array?

This question is related to perl datetime parsing date time

The answer is


To parse a date, look at Date::Parse in CPAN.


Possibly one of the better examples of 'There's More Than One Way To Do It", with or without the help of CPAN.

If you have control over what you get passed as a 'date/time', I'd suggest going the DateTime route, either by using a specific Date::Time::Format subclass, or using DateTime::Format::Strptime if there isn't one supporting your wacky date format (see the datetime FAQ for more details). In general, Date::Time is the way to go if you want to do anything serious with the result: few classes on CPAN are quite as anal-retentive and obsessively accurate.

If you're expecting weird freeform stuff, throw it at Date::Parse's str2time() method, which'll get you a seconds-since-epoch value you can then have your wicked way with, without the overhead of Date::Manip.


For further reference, a one liner that can be applied in, for example, !#/bin/sh scripts.

EPOCH="`perl -e 'use Time::Local; print timelocal('${SEC}','${MIN}','${HOUR}','${DAY}','${MONTH}','${YEAR}'),\"\n\";'`"

Just remember to avoid octal values!


There are many Date manipulation modules on CPAN. My particular favourite is DateTime and you can use the strptime modules to parse dates in arbitrary formats. There are also many DateTime::Format modules on CPAN for handling specialised date formats, but strptime is the most generic.


A filter converting any dates in various ISO-related formats (and who'd use anything else after reading the writings of the Mighty Kuhn?) on standard input to seconds-since-the-epoch time on standard output might serve to illustrate both parts:

martind@whitewater:~$ cat `which isoToEpoch`
#!/usr/bin/perl -w
use strict;
use Time::Piece;
# sudo apt-get install libtime-piece-perl
while (<>) {
  # date --iso=s:
  # 2007-02-15T18:25:42-0800
  # Other matched formats:
  # 2007-02-15 13:50:29 (UTC-0800)
  # 2007-02-15 13:50:29 (UTC-08:00)
  s/(\d{4}-\d{2}-\d{2}([T ])\d{2}:\d{2}:\d{2})(?:\.\d+)? ?(?:\(UTC)?([+\-]\d{2})?:?00\)?/Time::Piece->strptime ($1, "%Y-%m-%d$2%H:%M:%S")->epoch - (defined ($3) ? $3 * 3600 : 0)/eg;
  print;
}
martind@whitewater:~$ 

Get Date::Manip from CPAN, then:

use Date::Manip;
$string = '18-Sep-2008 20:09'; # or a wide range of other date formats
$unix_time = UnixDate( ParseDate($string), "%s" );

edit:

Date::Manip is big and slow, but very flexible in parsing, and it's pure perl. Use it if you're in a hurry when you're writing code, and you know you won't be in a hurry when you're running it.

e.g. Use it to parse command line options once on start-up, but don't use it parsing large amounts of data on a busy web server.

See the authors comments.

(Thanks to the author of the first comment below)


My favorite datetime parser is DateTime::Format::ISO8601 Once you've got that working, you'll have a DateTime object, easily convertable to epoch seconds with epoch()


I'm using a very old O/S that I don't dare install libraries onto, so here's what I use;

%MonthMatrix=("Jan",0,"Feb",31,"Mar",59,"Apr",90,"May",120,"Jun",151,"Jul",181,"Aug",212,"Sep",243,"Oct",273,"Nov",304,"Dec",334);
$LeapYearCount=int($YearFourDigits/4);
$EpochDayNumber=$MonthMatrix{$MonthThreeLetters};
if ($LeapYearCount==($YearFourDigits/4)) { if ($EpochDayNumber<32) { $EpochDayNumber--; }}
$EpochDayNumber=($YearFourDigits-1970)*365+$LeapYearCount+$EpochDayNumber+$DayAsNumber-493;
$TimeOfDaySeconds=($HourAsNumber*3600)+($MinutesAsNumber*60)+$SecondsAsNumber;
$ActualEpochTime=($EpochDayNumber*86400)+$TimeOfDaySeconds;

The input variables are;

$MonthThreeLetters
$DayAsNumber
$YearFourDigits
$HourAsNumber
$MinutesAsNumber
$SecondsAsNumber

...which should be self-explanatory.

The input variables, of course, assume GMT (UTC). The output variable is "$ActualEpochTime". (Often, I only need $EpochDayNumber, so that's why that otherwise superfluous variable sits on its own.)

I've used this formula for years with nary an error.


Possibly one of the better examples of 'There's More Than One Way To Do It", with or without the help of CPAN.

If you have control over what you get passed as a 'date/time', I'd suggest going the DateTime route, either by using a specific Date::Time::Format subclass, or using DateTime::Format::Strptime if there isn't one supporting your wacky date format (see the datetime FAQ for more details). In general, Date::Time is the way to go if you want to do anything serious with the result: few classes on CPAN are quite as anal-retentive and obsessively accurate.

If you're expecting weird freeform stuff, throw it at Date::Parse's str2time() method, which'll get you a seconds-since-epoch value you can then have your wicked way with, without the overhead of Date::Manip.


There are many Date manipulation modules on CPAN. My particular favourite is DateTime and you can use the strptime modules to parse dates in arbitrary formats. There are also many DateTime::Format modules on CPAN for handling specialised date formats, but strptime is the most generic.


If you're using the DateTime module, you can call the epoch() method on a DateTime object, since that's what you think of as unix time.

Using DateTimes allows you to convert fairly easily from epoch, to date objects.

Alternativly, localtime and gmtime will convert an epoch into an array containing day month and year, and timelocal and timegm from the Time::Local module will do the opposite, converting an array of time elements (seconds, minutes, ..., days, months etc.) into an epoch.


I'm using a very old O/S that I don't dare install libraries onto, so here's what I use;

%MonthMatrix=("Jan",0,"Feb",31,"Mar",59,"Apr",90,"May",120,"Jun",151,"Jul",181,"Aug",212,"Sep",243,"Oct",273,"Nov",304,"Dec",334);
$LeapYearCount=int($YearFourDigits/4);
$EpochDayNumber=$MonthMatrix{$MonthThreeLetters};
if ($LeapYearCount==($YearFourDigits/4)) { if ($EpochDayNumber<32) { $EpochDayNumber--; }}
$EpochDayNumber=($YearFourDigits-1970)*365+$LeapYearCount+$EpochDayNumber+$DayAsNumber-493;
$TimeOfDaySeconds=($HourAsNumber*3600)+($MinutesAsNumber*60)+$SecondsAsNumber;
$ActualEpochTime=($EpochDayNumber*86400)+$TimeOfDaySeconds;

The input variables are;

$MonthThreeLetters
$DayAsNumber
$YearFourDigits
$HourAsNumber
$MinutesAsNumber
$SecondsAsNumber

...which should be self-explanatory.

The input variables, of course, assume GMT (UTC). The output variable is "$ActualEpochTime". (Often, I only need $EpochDayNumber, so that's why that otherwise superfluous variable sits on its own.)

I've used this formula for years with nary an error.


If you're using the DateTime module, you can call the epoch() method on a DateTime object, since that's what you think of as unix time.

Using DateTimes allows you to convert fairly easily from epoch, to date objects.

Alternativly, localtime and gmtime will convert an epoch into an array containing day month and year, and timelocal and timegm from the Time::Local module will do the opposite, converting an array of time elements (seconds, minutes, ..., days, months etc.) into an epoch.


If you're just looking for a command-line utility (i.e., not something that will get called from other functions), try out this script. It assumes the existence of GNU date (present on pretty much any Linux system):

#! /usr/bin/perl -w

use strict;

$_ = (join ' ', @ARGV);
$_ ||= <STDIN>;

chomp;

if (/^[\d.]+$/) {
    print scalar localtime $_;
    print "\n";
}
else {
    exec "date -d '$_' +%s";
}

Here's how it works:

$ Time now
1221763842

$ Time yesterday
1221677444

$ Time 1221677444
Wed Sep 17 11:50:44 2008

$ Time '12:30pm jan 4 1987'
536790600

$ Time '9am 8 weeks ago'
1216915200

A filter converting any dates in various ISO-related formats (and who'd use anything else after reading the writings of the Mighty Kuhn?) on standard input to seconds-since-the-epoch time on standard output might serve to illustrate both parts:

martind@whitewater:~$ cat `which isoToEpoch`
#!/usr/bin/perl -w
use strict;
use Time::Piece;
# sudo apt-get install libtime-piece-perl
while (<>) {
  # date --iso=s:
  # 2007-02-15T18:25:42-0800
  # Other matched formats:
  # 2007-02-15 13:50:29 (UTC-0800)
  # 2007-02-15 13:50:29 (UTC-08:00)
  s/(\d{4}-\d{2}-\d{2}([T ])\d{2}:\d{2}:\d{2})(?:\.\d+)? ?(?:\(UTC)?([+\-]\d{2})?:?00\)?/Time::Piece->strptime ($1, "%Y-%m-%d$2%H:%M:%S")->epoch - (defined ($3) ? $3 * 3600 : 0)/eg;
  print;
}
martind@whitewater:~$ 

If you're using the DateTime module, you can call the epoch() method on a DateTime object, since that's what you think of as unix time.

Using DateTimes allows you to convert fairly easily from epoch, to date objects.

Alternativly, localtime and gmtime will convert an epoch into an array containing day month and year, and timelocal and timegm from the Time::Local module will do the opposite, converting an array of time elements (seconds, minutes, ..., days, months etc.) into an epoch.


There are many Date manipulation modules on CPAN. My particular favourite is DateTime and you can use the strptime modules to parse dates in arbitrary formats. There are also many DateTime::Format modules on CPAN for handling specialised date formats, but strptime is the most generic.


If you're just looking for a command-line utility (i.e., not something that will get called from other functions), try out this script. It assumes the existence of GNU date (present on pretty much any Linux system):

#! /usr/bin/perl -w

use strict;

$_ = (join ' ', @ARGV);
$_ ||= <STDIN>;

chomp;

if (/^[\d.]+$/) {
    print scalar localtime $_;
    print "\n";
}
else {
    exec "date -d '$_' +%s";
}

Here's how it works:

$ Time now
1221763842

$ Time yesterday
1221677444

$ Time 1221677444
Wed Sep 17 11:50:44 2008

$ Time '12:30pm jan 4 1987'
536790600

$ Time '9am 8 weeks ago'
1216915200

I know this is an old question, but thought I would offer another answer.

Time::Piece is core as of Perl 5.9.5

This allows parsing of time in arbitrary formats via the strptime method.

e.g.:

my $t = Time::Piece->strptime("Sunday 3rd Nov, 1943",
                              "%A %drd %b, %Y");

The useful part is - because it's an overloaded object, you can use it for numeric comparisons.

e.g.

if ( $t < time() ) { #do something }

Or if you access it in a string context:

print $t,"\n"; 

You get:

Wed Nov  3 00:00:00 1943

There's a bunch of accessor methods that allow for some assorted other useful time based transforms. https://metacpan.org/pod/Time::Piece


$ENV{TZ}="GMT";
POSIX::tzset();
$time = POSIX::mktime($s,$m,$h,$d,$mo-1,$y-1900);

To parse a date, look at Date::Parse in CPAN.


Possibly one of the better examples of 'There's More Than One Way To Do It", with or without the help of CPAN.

If you have control over what you get passed as a 'date/time', I'd suggest going the DateTime route, either by using a specific Date::Time::Format subclass, or using DateTime::Format::Strptime if there isn't one supporting your wacky date format (see the datetime FAQ for more details). In general, Date::Time is the way to go if you want to do anything serious with the result: few classes on CPAN are quite as anal-retentive and obsessively accurate.

If you're expecting weird freeform stuff, throw it at Date::Parse's str2time() method, which'll get you a seconds-since-epoch value you can then have your wicked way with, without the overhead of Date::Manip.


Get Date::Manip from CPAN, then:

use Date::Manip;
$string = '18-Sep-2008 20:09'; # or a wide range of other date formats
$unix_time = UnixDate( ParseDate($string), "%s" );

edit:

Date::Manip is big and slow, but very flexible in parsing, and it's pure perl. Use it if you're in a hurry when you're writing code, and you know you won't be in a hurry when you're running it.

e.g. Use it to parse command line options once on start-up, but don't use it parsing large amounts of data on a busy web server.

See the authors comments.

(Thanks to the author of the first comment below)


Possibly one of the better examples of 'There's More Than One Way To Do It", with or without the help of CPAN.

If you have control over what you get passed as a 'date/time', I'd suggest going the DateTime route, either by using a specific Date::Time::Format subclass, or using DateTime::Format::Strptime if there isn't one supporting your wacky date format (see the datetime FAQ for more details). In general, Date::Time is the way to go if you want to do anything serious with the result: few classes on CPAN are quite as anal-retentive and obsessively accurate.

If you're expecting weird freeform stuff, throw it at Date::Parse's str2time() method, which'll get you a seconds-since-epoch value you can then have your wicked way with, without the overhead of Date::Manip.


My favorite datetime parser is DateTime::Format::ISO8601 Once you've got that working, you'll have a DateTime object, easily convertable to epoch seconds with epoch()


A filter converting any dates in various ISO-related formats (and who'd use anything else after reading the writings of the Mighty Kuhn?) on standard input to seconds-since-the-epoch time on standard output might serve to illustrate both parts:

martind@whitewater:~$ cat `which isoToEpoch`
#!/usr/bin/perl -w
use strict;
use Time::Piece;
# sudo apt-get install libtime-piece-perl
while (<>) {
  # date --iso=s:
  # 2007-02-15T18:25:42-0800
  # Other matched formats:
  # 2007-02-15 13:50:29 (UTC-0800)
  # 2007-02-15 13:50:29 (UTC-08:00)
  s/(\d{4}-\d{2}-\d{2}([T ])\d{2}:\d{2}:\d{2})(?:\.\d+)? ?(?:\(UTC)?([+\-]\d{2})?:?00\)?/Time::Piece->strptime ($1, "%Y-%m-%d$2%H:%M:%S")->epoch - (defined ($3) ? $3 * 3600 : 0)/eg;
  print;
}
martind@whitewater:~$ 

If you're just looking for a command-line utility (i.e., not something that will get called from other functions), try out this script. It assumes the existence of GNU date (present on pretty much any Linux system):

#! /usr/bin/perl -w

use strict;

$_ = (join ' ', @ARGV);
$_ ||= <STDIN>;

chomp;

if (/^[\d.]+$/) {
    print scalar localtime $_;
    print "\n";
}
else {
    exec "date -d '$_' +%s";
}

Here's how it works:

$ Time now
1221763842

$ Time yesterday
1221677444

$ Time 1221677444
Wed Sep 17 11:50:44 2008

$ Time '12:30pm jan 4 1987'
536790600

$ Time '9am 8 weeks ago'
1216915200

Get Date::Manip from CPAN, then:

use Date::Manip;
$string = '18-Sep-2008 20:09'; # or a wide range of other date formats
$unix_time = UnixDate( ParseDate($string), "%s" );

edit:

Date::Manip is big and slow, but very flexible in parsing, and it's pure perl. Use it if you're in a hurry when you're writing code, and you know you won't be in a hurry when you're running it.

e.g. Use it to parse command line options once on start-up, but don't use it parsing large amounts of data on a busy web server.

See the authors comments.

(Thanks to the author of the first comment below)


$ENV{TZ}="GMT";
POSIX::tzset();
$time = POSIX::mktime($s,$m,$h,$d,$mo-1,$y-1900);

If you're using the DateTime module, you can call the epoch() method on a DateTime object, since that's what you think of as unix time.

Using DateTimes allows you to convert fairly easily from epoch, to date objects.

Alternativly, localtime and gmtime will convert an epoch into an array containing day month and year, and timelocal and timegm from the Time::Local module will do the opposite, converting an array of time elements (seconds, minutes, ..., days, months etc.) into an epoch.


My favorite datetime parser is DateTime::Format::ISO8601 Once you've got that working, you'll have a DateTime object, easily convertable to epoch seconds with epoch()


A filter converting any dates in various ISO-related formats (and who'd use anything else after reading the writings of the Mighty Kuhn?) on standard input to seconds-since-the-epoch time on standard output might serve to illustrate both parts:

martind@whitewater:~$ cat `which isoToEpoch`
#!/usr/bin/perl -w
use strict;
use Time::Piece;
# sudo apt-get install libtime-piece-perl
while (<>) {
  # date --iso=s:
  # 2007-02-15T18:25:42-0800
  # Other matched formats:
  # 2007-02-15 13:50:29 (UTC-0800)
  # 2007-02-15 13:50:29 (UTC-08:00)
  s/(\d{4}-\d{2}-\d{2}([T ])\d{2}:\d{2}:\d{2})(?:\.\d+)? ?(?:\(UTC)?([+\-]\d{2})?:?00\)?/Time::Piece->strptime ($1, "%Y-%m-%d$2%H:%M:%S")->epoch - (defined ($3) ? $3 * 3600 : 0)/eg;
  print;
}
martind@whitewater:~$ 

To parse a date, look at Date::Parse in CPAN.


There are many Date manipulation modules on CPAN. My particular favourite is DateTime and you can use the strptime modules to parse dates in arbitrary formats. There are also many DateTime::Format modules on CPAN for handling specialised date formats, but strptime is the most generic.


My favorite datetime parser is DateTime::Format::ISO8601 Once you've got that working, you'll have a DateTime object, easily convertable to epoch seconds with epoch()


To parse a date, look at Date::Parse in CPAN.


For further reference, a one liner that can be applied in, for example, !#/bin/sh scripts.

EPOCH="`perl -e 'use Time::Local; print timelocal('${SEC}','${MIN}','${HOUR}','${DAY}','${MONTH}','${YEAR}'),\"\n\";'`"

Just remember to avoid octal values!


I know this is an old question, but thought I would offer another answer.

Time::Piece is core as of Perl 5.9.5

This allows parsing of time in arbitrary formats via the strptime method.

e.g.:

my $t = Time::Piece->strptime("Sunday 3rd Nov, 1943",
                              "%A %drd %b, %Y");

The useful part is - because it's an overloaded object, you can use it for numeric comparisons.

e.g.

if ( $t < time() ) { #do something }

Or if you access it in a string context:

print $t,"\n"; 

You get:

Wed Nov  3 00:00:00 1943

There's a bunch of accessor methods that allow for some assorted other useful time based transforms. https://metacpan.org/pod/Time::Piece


Get Date::Manip from CPAN, then:

use Date::Manip;
$string = '18-Sep-2008 20:09'; # or a wide range of other date formats
$unix_time = UnixDate( ParseDate($string), "%s" );

edit:

Date::Manip is big and slow, but very flexible in parsing, and it's pure perl. Use it if you're in a hurry when you're writing code, and you know you won't be in a hurry when you're running it.

e.g. Use it to parse command line options once on start-up, but don't use it parsing large amounts of data on a busy web server.

See the authors comments.

(Thanks to the author of the first comment below)


If you're just looking for a command-line utility (i.e., not something that will get called from other functions), try out this script. It assumes the existence of GNU date (present on pretty much any Linux system):

#! /usr/bin/perl -w

use strict;

$_ = (join ' ', @ARGV);
$_ ||= <STDIN>;

chomp;

if (/^[\d.]+$/) {
    print scalar localtime $_;
    print "\n";
}
else {
    exec "date -d '$_' +%s";
}

Here's how it works:

$ Time now
1221763842

$ Time yesterday
1221677444

$ Time 1221677444
Wed Sep 17 11:50:44 2008

$ Time '12:30pm jan 4 1987'
536790600

$ Time '9am 8 weeks ago'
1216915200

Examples related to perl

The program can't start because api-ms-win-crt-runtime-l1-1-0.dll is missing while starting Apache server on my computer "End of script output before headers" error in Apache Perl - Multiple condition if statement without duplicating code? How to decrypt hash stored by bcrypt Split a string into array in Perl Turning multiple lines into one comma separated line String compare in Perl with "eq" vs "==" how to remove the first two columns in a file using shell (awk, sed, whatever) Find everything between two XML tags with RegEx Difference between \w and \b regular expression meta characters

Examples related to datetime

Comparing two joda DateTime instances How to format DateTime in Flutter , How to get current time in flutter? How do I convert 2018-04-10T04:00:00.000Z string to DateTime? How to get current local date and time in Kotlin Converting unix time into date-time via excel Convert python datetime to timestamp in milliseconds SQL Server date format yyyymmdd Laravel Carbon subtract days from current date Check if date is a valid one Why is ZoneOffset.UTC != ZoneId.of("UTC")?

Examples related to parsing

Got a NumberFormatException while trying to parse a text file for objects Uncaught SyntaxError: Unexpected end of JSON input at JSON.parse (<anonymous>) Python/Json:Expecting property name enclosed in double quotes Correctly Parsing JSON in Swift 3 How to get response as String using retrofit without using GSON or any other library in android UIButton action in table view cell "Expected BEGIN_OBJECT but was STRING at line 1 column 1" How to convert an XML file to nice pandas dataframe? How to extract multiple JSON objects from one file? How to sum digits of an integer in java?

Examples related to date

How do I format {{$timestamp}} as MM/DD/YYYY in Postman? iOS Swift - Get the Current Local Time and Date Timestamp Typescript Date Type? how to convert current date to YYYY-MM-DD format with angular 2 SQL Server date format yyyymmdd Date to milliseconds and back to date in Swift Check if date is a valid one change the date format in laravel view page Moment js get first and last day of current month How can I convert a date into an integer?

Examples related to time

Date to milliseconds and back to date in Swift How to manage Angular2 "expression has changed after it was checked" exception when a component property depends on current datetime how to sort pandas dataframe from one column Convert time.Time to string How to get current time in python and break up into year, month, day, hour, minute? Xcode swift am/pm time to 24 hour format How to add/subtract time (hours, minutes, etc.) from a Pandas DataFrame.Index whos objects are of type datetime.time? What does this format means T00:00:00.000Z? How can I parse / create a date time stamp formatted with fractional seconds UTC timezone (ISO 8601, RFC 3339) in Swift? Extract time from moment js object