3

What's the best way to get a file's modification date in DDMMYY format in Perl?

(Originally the question was "How to do it without the DateTime module". I removed this restriction in order to make the question more general.)

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Igor
  • 26,650
  • 27
  • 89
  • 114

5 Answers5

18

If this is the only date formatting I need to do and don't need any date features for anything else, I just use POSIX (which comes with Perl):

use POSIX;

my $file = "/etc/passwd";

my $date = POSIX::strftime( 
             "%d%m%y", 
             localtime( 
                 ( stat $file )[9]
                 )
             );

Forget about -M if you aren't using relative time. Go directly to stat to get the epoch time.

brian d foy
  • 129,424
  • 31
  • 207
  • 592
  • Stat() doesn't seem to work on Activestate Perl 5.24 on Windows Server 2012. How would I get a file date for a file on Windows Server? – Bulrush Mar 28 '18 at 15:16
  • Look through the Win32:: modules for those that know about the Windows filesystems. – brian d foy Mar 28 '18 at 16:13
  • Thanks. I've already did a search on DuckDuckGo, the Activestate community forum, and looked at CPAN at Win32::File. Some of the modules have not been updated in 10 years. But I have not found what I needed yet. – Bulrush Mar 28 '18 at 16:23
12

See Time::Piece for object oriented syntax. It also comes with Perl by default in versions 5.10 and next. Usually at some later point you need more functionality. Using Time::Piece does not import anything beside localtime and gmtime. And you can ask it not to import anything too by just saying use Time::Piece ();.

use Time::Piece;
localtime((stat $filename)[9])->ymd;                # 2000-02-29
localtime((stat $filename)[9])->ymd('');                 # 20000229
localtime((stat $filename)[9])->dmy("");#is what you wanted



$perl -MTime::Piece -e 'print localtime(time)->dmy("")'
Беров
  • 1,383
  • 10
  • 22
4

UPDATE: Note that this answer was to the original question, which specifically excluded use of DateTime modules.

To get modified time

my $mtime = (stat $filename)[9];

This returns the last modify time in seconds since the epoch.

Then, to translate to date components, use localtime -

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

Note that localtime returns 0 for Jan, 1 for Feb, etc, and $year is the number of years since 1900, so 109 -> 2009.

Then to output in the format DDMMYY -

print substr('0'.$mday,-2), substr('0'.($mon+1),-2), substr($year+1900,-2);

So it's easier - and less error-prone - to simply use Date::Format if you can.

ysth
  • 96,171
  • 6
  • 121
  • 214
Ed Guiness
  • 34,602
  • 16
  • 110
  • 145
4

Here's a reasonably straightforward method using POSIX (which is a core module) and localtime to avoid twiddling with the details of what stat returns (see Edg's answer for why that's a pain):

use POSIX qw/strftime/;

my @records;

opendir my $dh, '.' or die "Can't open current directory for reading: $!";

while (my $item = readdir $dh) {
    next unless -f $item && $item !~ m/^\./;
    push @records, [$item, (stat $item)[9]];
}

for my $record (@records) {
    print "File: $record->[0]\n";
    print "Mtime: " . strftime("%d%m%Y", localtime $record->[1]), "\n";
}
Community
  • 1
  • 1
Telemachus
  • 19,459
  • 7
  • 57
  • 79
1
use Date::Format;
print time2str("%d%m%y", (stat $filename)[9]);
Igor
  • 26,650
  • 27
  • 89
  • 114