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)
Related
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);
I am reading a log file which contains time stamps which I want to convert to human readable.
In this command, $1 contains a time stamp (like this 1403457192.663): $temp = localtime->mon($1) but instead of storing the month, $temp contains the same timestamp that was input. What am I doing wrong?
You're close. The time should be passed to the localtime function, not the mon method.:
$temp = localtime($1)->mon; # 6
You can use strftime with this to turn it into any arbitrary format
localtime($1)->strftime("%b %d %a"); # Jun 22 Sun
Or if you're not picky about the format you can just stringify it:
$temp = localtime($1);
print "$temp\n"; # Sun Jun 22 13:13:12 2014
This assumes that Time::Piece is loaded.
I'd simply go with
$ perl -E'
use POSIX qw( strftime );
say strftime("%Y/%m/%d %H:%M:%S", localtime(1403457192.663));
'
2014/06/22 13:13:12
But you're using Time::localtime. That module overrides the localtime builtin, so you need a slight modification if you use that.
Either avoid using Time::localtime's localtime
$ perl -E'
use POSIX qw( strftime );
use Time::localtime qw( localtime );
say strftime("%Y/%m/%d %H:%M:%S", CORE::localtime(1403457192.663));
'
2014/06/22 13:13:12
or flatten an existing Time::localtime object.
$ perl -E'
use POSIX qw( strftime );
use Time::localtime qw( localtime );
my $tm = localtime(1403457192.663);
say strftime("%Y/%m/%d %H:%M:%S", #$tm);
'
2014/06/22 13:13:12
All of these solutions lose the millisecond precision. If it's relevant, you'll have to extract it from the original input and reinsert it in the output.
For formatting dates most system strftime manual pages will list a few "shortcuts" to get you certain "standard" formats.
e.g. %F is equivalent to ā%Y-%m-%dā.
~/% perl -MPOSIX -E'say strftime"%D",localtime'
06/25/14
~/% perl -MPOSIX -E'say strftime"%F",localtime'
2014-06-25
These can make using "ye olde" strftime easier ;-)
Perl since 5.10 now contains Time::Piece. This makes it the official way to handle time in Perl. Or, about as official as something gets in Perl. Since it's always available, you might as well learn to use that:
use strict;
use warnings;
use Time::Piece;
use Time::Seconds; # More time fun!
my $time = Time::Piece->new; # Gets the current timestamp
my $month = $time->mon(); # Month from 1 to 12
my $month = $time->month(); # Abbreviation of the name of month
my $month = $time->fullmonth(); # Full name of the month
my $time = $time + (ONE_DAY * 30) # Add thirty days to the time
my $date = $time->mdy # The date 30 days from now.
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] );
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);
I would like a simple way to get yesterday's date (local time) as a string in a Perl script. Preferably, I would like to do this with no module dependencies, since we have a bare bones Perl 5.12 installation.
So, something like:
my $yesterdays_date=...; # Puts for example '301011' into $yesterdays_date,
# if today is October 31st, 2011
Time::Piece is core:
use Time::Piece;
use Time::Seconds qw(ONE_DAY);
my $yesterday = localtime() - ONE_DAY();
print $yesterday->strftime('%d%m%y'), "\n";
If you're concerned about daylight savings, you can normalize the current time to near noon:
use Time::Piece;
use Time::Seconds qw(ONE_DAY ONE_HOUR);
my $today = localtime;
my $yesterday = $today + ONE_HOUR * ( 12 - $today->hour ) - ONE_DAY;
print $yesterday->strftime("%d%m%y"), "\n";
If you can live with dependencies, then use DateTime:
use DateTime;
print DateTime->now->subtract(days => 1)->strftime('%d%m%y'), "\n";
If you're willing to go with dependencies, DateTime will generally do anything you need.
use strict;
use warnings;
use 5.012;
use DateTime;
say DateTime->now->subtract(days => 1)->strftime('%d%m%y');
Just subtract 24 hours (24 hours * 60 minutes * 60 seconds) from current time and get localtime:
say scalar localtime(time - 60*60*24);
# Sun Oct 30 21:04:30 2011
Note, that localtime returns time in string format only in scalar context.
If you need to generate 'DDMMYY' you can just use data structure returned by list context:
my #tm = localtime(time - 60*60*24);
my $date = sprintf("%02d%02d%2d", $tm[3], $tm[4]+1, $tm[5] + 1900);
# 30102011
You can use the POSIX module thusly:
perl -MPOSIX=strftime -le 'print strftime "%m%d%y",localtime(time-(60*60*24))'