so I am currently using
my $date = DateTime->now->mdy;
which gives me the format in "09-10-2013"
then i used
my $modTime = localtime((stat($some_file))[9]);
which gives me the date in format "Tue Sep 10 15:29:29 2013"
is there a way built in perl to format the $modTime to the format like $date?
or do i have to do it manually?
thanks!
Well, depending on what you mean by "manually", you can do it in a couple of short steps:
# demo.
# Put the whole local time/stat/etc in parentheses where I put localtime.
#
($m,$d,$y) = (localtime)[4,3,5]; # extract date fields using a list slice
$modtime = sprintf('%02d-%02d-%4d', $m+1, $d, $y+1900); # format the string
There's probably a way to do it in a single line, incorporating both the extraction and a more complex format string, but that would lead to unnecessary obfuscation.
-Tom Williams
Create a DateTime object using the from_epoch constructor.
#!/usr/bin/perl
use strict;
use warnings;
use 5.010;
use DateTime;
# Using $0 (the current file) in these examples.
my $epoch = (stat $0)[9];
my $dt = DateTime->from_epoch(epoch => $epoch);
say $dt->dmy;
Of course, that can be rewritten as a single line:
#!/usr/bin/perl
use strict;
use warnings;
use 5.010;
use DateTime;
say DateTime->from_epoch(epoch => (stat $0)[9])->dmy;
But for something this easy, I'd probably use Time::Piece (which is part of the Perl standard distribution) rather than DateTime.
#!/usr/bin/perl
use strict;
use warnings;
use 5.010;
use Time::Piece;
say localtime((stat $0)[9])->dmy;
Late to answer, already seen the good answer to use from_epoch (DateTime->from_epoch(epoch => $epoch);). You could also use POSIX's function strftime like: print strftime "%m-%d-%Y", localtime( ( stat $some_file )[9] );
Related
How can I get the file modification time formatted in local time?
By doing this:
use File::stat;
use Time::Piece;
my $format = '%Y%m%d%H%M';
print Time::Piece->strptime(stat($ARGV[0])->mtime, '%s')->strftime($format);
I get 202011301257 for a file that was saved at Nov 30 13:57 in my local time (GMT+01:00).
Since I can do
print localtime $file->stat->mtime;
and
print localtime->strftime($format)
I'd like to do something like
print (localtime stat($file)->mtime)->strftime($format);
Which throws
Can't locate object method "mtime" via package "1" (perhaps you forgot to load "1"?)
Any advice?
I'd like to do something like
print (localtime stat($file)->mtime)->strftime($format);
Very close! Your first parenthesis is in the wrong spot:
#!/usr/bin/env perl
use warnings; # Pardon the boilerplate
use strict;
use feature 'say';
use File::stat;
use Time::Piece;
my $format = '%Y%m%d%H%M';
say localtime(stat($ARGV[0])->mtime)->strftime($format);
Always use use strict; use warnings;. It would have caught the problem:
print (...) interpreted as function at a.pl line 6.
You have the following
print ( localtime ... )->strftime($format);
Because the space between print and ( is meaningless, the above is equivalent to the following:
( print( localtime ... ) )->strftime($format);
The problem is that you are using ->strftime on the result of print. The problem goes away if you don't omit the parens around print's operands.
print( ( localtime ... )->strftime($format) );
Alternatively, not omitting the parens localtime's args would allow you to remove the parens causing the problem.
print localtime( ... )->strftime($format);
I want to accept a user date on the command line in format
dd/mm/yyyy
then print the date out to the user in
yyyy/mm/dd
I am trying to use the Date::Parse module to parse into a date to be reprinted.
The Date:Parse docs show that I should be able to get $day, $month and $year from user input.
use Date::Parse;
$time = str2time($date);
($ss,$mm,$hh,$day,$month,$year,$zone) = strptime($date);
This is my current code:
use strict;
use Date::Parse;
print "Enter a date in dd/mm/yyy format: ";
my $user_date = <STDIN>;
my #date = strptime($user_date);
# ( $day, $month, $year ) = strptime($user_date);
# my $user_day = ( ($day) = strptime($user_date) );
print "%Y/%m/%d", #date;
However the print fails and it appears from output that entered 10 of 10 is 9 in output.
Output
Enter a date in dd/mm/yyy format: 16/10/1952
%Y/%m/%d1952916s
What should I do?
The documentation for Date::Parse isn't clear, but it looks like you get the values back in the format that localtime() would expect. The year, for example, seems to be the year minus 1900. This means that the month number will be 0 to 11 rather than 1 to 12.
Date::Parse hasn't been updated for over five years. I'd suggest that it should best be avoided these days. There are much better options to choose from. These include Time::Piece that has been included as a standard part of the Perl distribution since version 5.10.0. You can use its strptime() (string parse time) method to parse your string and its strftime() (string format time) method to format the date object as you like.
#!/usr/bin/perl
use strict;
use warnings;
use feature 'say';
use Time::Piece;
print "Enter a date in dd/mm/yyy format: ";
chomp(my $user_date = <STDIN>);
my $tp = Time::Piece->strptime($user_date, '%d/%m/%Y');
say $tp->strftime('%Y/%m/%d');
Update:
Also, it's really not clear what this line is supposed to do:
print "%Y/%m/%d", #date;
I think you were thinking of using the strftime() method from POSIX.pm.
print strftime "%Y/%m/%d", #date;
But with use warnings this generates warnings because of all the undefined values in #data (that's a rather bizarre design decision in that module and, in my opinion, another reason to avoid it). You can fix that by replacing:
my #date = strptime($user_date);
With:
my #date = map { $_ // 0 } strptime($user_date);
This question already has answers here:
How can I parse dates and convert time zones in Perl?
(5 answers)
Closed 7 years ago.
I have a date/time like this: 2015-07-31T13:30:00.000+01:00
And I want to convert it to normal date and time using Perl and Time::Piece->strptime
Here is my code:
sub changeDateFormat {
my ($date, $fromFormat, $toFormat) = (#_);
return Time::Piece->strptime($date, $fromFormat)->strftime($toFormat);
}
The call:
print changeDateFormat($that_date, '%Y-%m-%dT%H:%M:%S.%N+%z', '%Y:%m:%d');
I think that .000 are nano seconds and +01.00 stands for time zone.
But the given code gives this:
Error parsing time at /usr/lib64/perl5/Time/Piece.pm line 470
Any help is appreciated.
There's a couple of problems I think.
%N isn't in my strftime manpage. So that might well not work.
And %z - I'm pretty sure +01:00 isn't valid.
%z The +hhmm or -hhmm numeric timezone (that is, the hour and
minute offset from UTC). (SU)
This works though:
my $date = '2015-07-31T13:30:00+0100';
my $fromFormat = '%Y-%m-%dT%H:%M:%S%z';
print Time::Piece->strptime($date, $fromFormat);
So I'd suggest - unless your milliseconds are important - you could just strip those via a regex, and likewise the timezone. (And it they are important, I don't think Time::Piece does ms resolution anyway)
You can probably use a regular expression to 'correct' your input date if you were so inclined. I'm unsure if fits your use case but:
$date =~ s/\+(\d{2}):(\d{2})$/+$1$2/;
$date =~ s/\.\d{3}+/+/;
You can use strptime in Time::Piece and adding the time zone manually as shown in this answer, or you could try using DateTime::Format::Strptime instead:
use feature qw(say);
use strict;
use warnings;
use DateTime::Format::Strptime;
my $timestamp = '2015-07-31T13:30:00.000+0100';
my $strp = DateTime::Format::Strptime->new(
pattern => '%Y-%m-%dT%H:%M:%S.%N%z'
);
my $dt = $strp->parse_datetime( $timestamp );
say $dt->strftime('%Y:%m:%d');
Output:
2015:07:31
use DateTime;
use DateTime::Format::ISO8601;
use DateTime::Format::Strptime;
my $string = '2015-07-31T13:30:00.000+01:00';
my $date = DateTime::Format::ISO8601->parse_datetime( $string );
die "Error" unless $date;
my $formatter = new DateTime::Format::Strptime(pattern => '%Y-%m-%d %T');
$date->set_formatter($formatter);
print "$date\n";
i'm using Time::Piece to parse date.
#!/usr/bin/perl -w
use warnings;
use Time::Piece;
my $date = '20-11-2038';
my $frmt = '%d-%m-%Y';
my $t = Time::Piece->strptime($date, $frmt);
$t = $t + ONE_DAY;
print $t->ymd('/'), "\n";
i can use only dates ranging from 1970 - 2038. if i use any other date, i'm getting error as
Day too big - 25160 > 24853
Cannot handle date (0, 0, 0, 20, 11, 2038) at C:/perl/lib/Time/Piece.pm line 315
is there any other way ?
I can't reproduce your error, I get:
Argument "ONE_DAY" isn't numeric in addition (+) at ...lib/5.10.1/x86_64-linux-thread-multi/Time/Piece.pm line 571.
But, if I add use Time::Seconds it works fine (I changed the code to show dates outside the 1970-2038 range):
use 5.010;
use strict;
use warnings;
use Time::Piece;
use Time::Seconds;
my $tmin = Time::Piece->strptime('20-11-1970', '%d-%m-%Y');
my $tmax = Time::Piece->strptime('20-11-2038', '%d-%m-%Y');
say $tmin->ymd('-');
say $tmax->ymd('-');
say '---';
my $tmin2 = $tmin - ONE_YEAR;
my $tmax2 = $tmax + ONE_YEAR;
say $tmin2->ymd('-');
say $tmax2->ymd('-');
and the result is:
1970-11-20
2038-11-20
---
1969-11-19
2039-11-20
Update:
This is perl, v5.10.1 (*) built for x86_64-linux-thread-multi
Time::Piece is up to date. (1.29)
I'm looking for a way to convert a date in format YYDDD to YY/MM/DD.
i.e. 12212 becomes 12/07/30.
An example in php can be found at http://www.longpelaexpertise.com.au/toolsJulian.php and you can find a DDD calendar at http://landweb.nascom.nasa.gov/browse/calendar.html
I'd appreciate any guidance both with and without perl modules.
Thanks!
edit: I'm not looking for a way to convert php2perl or anything like that. I'm simply looking for a way to convert YYDDD to YY/MM/DD using perl. I would prefer a way without using any additional perl modules however if that is the only way to do it, then I'll welcome examples using perl modules.
The nicest way would be to use Time::Piece to parse the date and reformat it, like this
Time::Piece->strptime('12212', '%y%j')->strftime('%y/%m/%d')
unfortunately however, the module doesn't accept %j (day of year) in its strptime format (although it is fine in strftime).
The second best option is strftime from the POSIX module. The string has to be split into year and day first, and the day of year is zero-based so one must be subtracted, but then the conversion is straightforward. It is probably best packaged as a subroutine, like this
use strict;
use warnings;
use POSIX 'strftime';
sub yj2ymd {
my ($year, $yday) = $_[0] =~ /(\d\d)(\d\d\d)/;
strftime('%y/%m/%d', 0, 0, 0, 0, 0, 2000+$year, 0, $yday-1);
}
print yj2ymd('12212');
output
12/07/30
You will have to do something fancier with the year if you expect any dates from last century.
I like Time::Piece simply because it comes with Perl since, I believe revision 5.10. You'll find dozens of date/time modules and everyone has their favorites, but with Time::Piece becoming part of the official distribution, it's time to switch to that.
To use Time::Piece, you need to know about strptime (STRing Parse TIME) and strftime (STRing Format TIME) both which uses %x letter formats to represent certain aspects of your time string. The reason is that Time::Piece uses the same %x format characters to both convert your time string to a time object and sometimes to format that time object into your string.
From strftime's manpage:
%j
The day of the year as a decimal number (range 001 to 366).
And:
%y
The year as a decimal number without a century (range 00 to 99).
Now to convert your date:
use Time::Piece;
my $old_time = "12212"; #YYddd
my $time = Time::Piece->strptime( $old_time, "%y%j" );
my $new_time = $time->ymd("/"); Now in YY/MM/DD format
Whoops
Hang on — strptime does not grok %j. This will give the wrong answer.
I didn't test this because I have used Time::Piece so often that I can do it in my sleep. I never used %j before in Time::Piece. The perldoc mentions nothing about %j not working, and I don't get any sort of error. That's not nice.
New strategy. I can parse the YYddd string into year and days. Then, I can get the beginning of the year as 01/01/$year. After that, I can take the days, and add it to the year. However, to do this correctly, I need a constant from Time::Seconds:
use strict;
use warnings;
use feature qw(say);
use Time::Piece;
use Time::Seconds;
my $old_date = "12212";
$old_date =~ /(..)(.*)/;
my $year = $1;
my $days = $2;
my $time = Time::Piece->strptime("01/01/$year", "%m/%d/%y");
$time += ( ( $days - 1 ) * ONE_DAY); #01/01/$year is day 1 and not 0
say $time->strftime("%y/%m/%d");
That gives 12/07/30 as the answer.
Announcement
The owner of the Time::Piece module fixed the error in the module. Version 1.23 now works:
use warnings;
use strict;
use autodie;
use feature qw(say);
use Data::Dumper;
use Time::Piece;
my $old_time = "12212"; #YYddd
my $time = Time::Piece->strptime( $old_time, "%y%j" );
my $new_time = $time->ymd("/"); #Now in YY/MM/DD format
say "Version: $Time::Piece::VERSION";
say $new_time;
This prints out:
Version: 1.23
2012/07/30
Here's a short and sweet way to do what you want:
#!/usr/bin/perl
use strict;
use Date::Calc qw(Add_Delta_Days);
my $dt = '12212';
my $startYr = 2000 + substr($dt, 0, 2);
my $daysToAdd = substr($dt, 2) - 1;
my ($newYr, $newMo, $newDay) = Add_Delta_Days($startYr, 1, 1, $daysToAdd);
printf("%02d/%02d/%02d\n", $newYr % 100, $newMo, $newDay);