[perl] Quickly getting to YYYY-mm-dd HH:MM:SS in Perl

When writing Perl scripts I frequently find the need to obtain the current time represented as a string formatted as YYYY-mm-dd HH:MM:SS (say 2009-11-29 14:28:29).

In doing this I find myself taking this quite cumbersome path:

  • man perlfunc
  • /localtime to search for localtime - repeat five times (/ + \n) to reach the relevant section of the manpage
  • Copy the string ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time); from the manpage to my script.
  • Try with my $now = sprintf("%04d-%02d-%02d %02d:%02d:%02d", $year, $mon, $mday, $hour, $min, $sec);
  • Remember gotcha #1: Must add 1900 to $year to get current year.
  • Try with my $now = sprintf("%04d-%02d-%02d %02d:%02d:%02d", $year+1900, $mon, $mday, $hour, $min, $sec);
  • Remember gotcha #2: Must add 1 to $mon to get current month.
  • Try with my $now = sprintf("%04d-%02d-%02d %02d:%02d:%02d", $year+1900, $mon+1, $mday, $hour, $min, $sec);
  • Seems ok. Done!

While the process outlined above works it is far from optimal. I'm sure there is a smarter way, so my question is simply:

What is the easiest way to obtain a YYYY-mm-dd HH:MM:SS of the current date/time in Perl?

Where "easy" encompasses both "easy-to-write" and "easy-to-remember".

This question is related to perl datetime formatting timestamp

The answer is


Why not use the DateTime module to do the dirty work for you? It's easy to write and remember!

use strict;
use warnings;
use DateTime;

my $dt   = DateTime->now;   # Stores current date and time as datetime object
my $date = $dt->ymd;   # Retrieves date as a string in 'yyyy-mm-dd' format
my $time = $dt->hms;   # Retrieves time as a string in 'hh:mm:ss' format

my $wanted = "$date $time";   # creates 'yyyy-mm-dd hh:mm:ss' string
print $wanted;

Once you know what's going on, you can get rid of the temps and save a few lines of code:

use strict;
use warnings;
use DateTime;

my $dt = DateTime->now;
print join ' ', $dt->ymd, $dt->hms;

Short and sweet, no additional modules needed:

my $toDate = `date +%m/%d/%Y" "%l:%M:%S" "%p`;

Output for example would be: 04/25/2017 9:30:33 AM


Time::Piece (in core since Perl 5.10) also has a strftime function and by default overloads localtime and gmtime to return Time::Piece objects:

use Time::Piece;
print localtime->strftime('%Y-%m-%d');

or without the overridden localtime:

use Time::Piece (); 
print Time::Piece::localtime->strftime('%F %T');

Time::Piece::datetime() can eliminate T.

use Time::Piece;
print localtime->datetime(T => q{ });

Try this:

use POSIX qw/strftime/;
print strftime('%Y-%m-%d',localtime);

the strftime method does the job effectively for me. Very simple and efficient.



In many cases, the needed 'current time' is rather $^T, which is the time at which the script started running, in whole seconds (assuming only 60 second minutes) since the UNIX epoch.

This to prevent that an early part of a script uses a different date (or daylight-saving status) than a later part of a script, for example in query-conditions and other derived values.

For that variant of 'current time', one can use a constant, also to document that it was frozen at compile time:

use constant YMD_HMS_AT_START => POSIX::strftime( "%F %T", localtime $^T );

Alternative higher resolution startup time:

0+ [ Time::HiRes::stat("/proc/$$") ]->[10]

I made a little test (Perl v5.20.1 under FreeBSD in VM) calling the following blocks 1.000.000 times each:

A

my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
my $now = sprintf("%04d-%02d-%02d %02d:%02d:%02d", $year+1900, $mon+1, $mday, $hour, $min, $sec);

B

my $now = strftime('%Y%m%d%H%M%S',localtime);

C

my $now = Time::Piece::localtime->strftime('%Y%m%d%H%M%S');

with the following results:

A: 2 seconds

B: 11 seconds

C: 19 seconds

This is of course not a thorough test or benchmark, but at least it is reproducable for me, so even though it is more complicated, I'd prefer the first method if generating a datetimestamp is required very often.

Calling (eg. under FreeBSD 10.1)

my $now = `date "+%Y%m%d%H%M%S" | tr -d "\n"`;

might not be such a good idea because it is not OS-independent and takes quite some time.

Best regards, Holger


if you just want a human readable time string and not that exact format:

$t = localtime;
print "$t\n";

prints

Mon Apr 27 10:16:19 2015

or whatever is configured for your locale.


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 formatting

How to add empty spaces into MD markdown readme on GitHub? VBA: Convert Text to Number How to change indentation in Visual Studio Code? How do you change the formatting options in Visual Studio Code? (Excel) Conditional Formatting based on Adjacent Cell Value 80-characters / right margin line in Sublime Text 3 Format certain floating dataframe columns into percentage in pandas Format JavaScript date as yyyy-mm-dd AngularJS format JSON string output converting multiple columns from character to numeric format in r

Examples related to timestamp

concat yesterdays date with a specific time How do I format {{$timestamp}} as MM/DD/YYYY in Postman? iOS Swift - Get the Current Local Time and Date Timestamp Pandas: Convert Timestamp to datetime.date Spark DataFrame TimestampType - how to get Year, Month, Day values from field? What exactly does the T and Z mean in timestamp? What does this format means T00:00:00.000Z? Swift - iOS - Dates and times in different format Convert timestamp to string Timestamp with a millisecond precision: How to save them in MySQL