'Time calculation in perl
I am very new to perl script and I wanted to do some time calculations. I am using localtime() to get the current time.
my ($sec,$min,$hour,$day,$mon,$year) = localtime(time());
my ($ysec,$ymin,$yhour,$yday,$ymon) = localtime(time() - 60*60*24);
my ($wsec,$wmin,$whour,$wday,$wmon,$wyr) = localtime(time() - 8*60*60*24);
This is how I had calculated the time for current day, yesterday and a week back timings. But I also want to calculate a month back and a year's time. and I followed the similar pattern:
#my ($msec,$mmin,$mhour,$mday,$mmon,$myr) = localtime(time()-30*60*60*24);
#my ($ysec,$ymin,$yhour,$yday,$ymon,$yyr) = localtime(time()-365*60*60*24);
But I am wondering if there is a better way of doing this time calculations. Can some one help me with this month and year calculations? Can you suggest if there is a better way of doing this stuff?
Solution 1:[1]
A easy access module to use is Time::Piece, which is core since Perl version 5.9.5. Constants for time math can be access via Time::Seconds
use strict;
use warnings;
use Time::Piece;
use Time::Seconds; # used for constants ONE_WEEK etc
my $time_now = localtime();
my $time_hour = $time_now - ONE_HOUR;
my $time_month = $time_now - ONE_MONTH;
print "$_\n" for $time_now, $time_hour, $time_month;
Outputs:
Thu Jan 29 17:20:55 2015
Thu Jan 29 16:20:55 2015
Tue Dec 30 06:51:51 2014
Solution 2:[2]
Date and time calculations can be very complicated in any language. There are a lot of details to consider, and a lot of weird special cases (such as daylight saving time, or leap seconds). Best to find a well-tested off-the-shelf package to do the dirty work.
Two of the best for Perl are DateTime and Time::Piece. Another useful one to know is Date::Manip; it is less suited for general programming use, but is handy for parsing all kinds of sloppy user input, from "1/29/2015" to "last saturday".
Solution 3:[3]
Perl tracks time as the number of seconds from the start of the epoch which is usually January 1, 1970. Perl uses the built in C API to fetch information about month, day, date, time, day of the week, etc.
Built into Perl's basic command set is localtime and gmtime. These will return an array of time elements. Ironically, the reverse functions were not part of the standard Perl package. However, the Time::Local module included the reversing functions timelocal and timegm. These take an array and return the time in seconds since the epoch.
For years, this was the standard toolkit in using these time functions. As you see, they're not particularly easy to use. Dozens of time modules were written to help fill in the gap. In Perl 5.10, Time::Piece was included as a standard Perl module which means that any Perl install of version 5.10 or later will include this module. Combine this with the constants in Time::Seconds, and you have an nice easy way to calculate dates and times in Perl.
The big issue with this module is that it's object oriented which may make it difficult to use if you're not familiar with Object Oriented Perl. Another criticism is that Time::Seconds makes lousy assumptions such as a day is 24 hours long. This might sound nice and logical until you realize that certain days have 25 or 23 hours in them due to Daylight Savings Time.
However, they do provide a nice easy to use interface. First, you need to create a Time::Piece object, then you use various methods on that object to get what you want. Think of methods as functions, and the object as something that holds information (such as the date you're using), and it's not so bad.
To create a Time::Piece object, you use strptime:
use Time::Piece;
my $datestring = "Jan 31, 2015 - 12:20pm";
my $timeformat = "%b %e, %Y - %I:%M%p";
my $time_object = Time::Piece->strptime( $datestring, $format );
The $timeformat uses percent signs followed by a letter to represent certain aspects of the date. You can usually find these looking at the manpage of either date or strftime. Once you create your object, you can do all sorts of nifty tricks:
use Time::Piece;
say "The day of the week is " . $time_object->day;
say "The year is " . $time_object->year;
say "The time in MM/DD/YY is " . $time_object->mdy("/");
You can easily use calculations with these too.
use Time::Piece;
use Time::Seconds;
$time_object + ( 2 * ONE_DAY );
say "The date two days later is " . $time_object->mdy("/");
Or take the difference between two days:
my $time_diff = $time_object - $time_object2;
say "The difference is " . $time_diff->days;
As I said, this is an object oriented module, so the syntax is a bit weird for beginning Perl programmers (What's with that ->?), and if you're not familiar with object oriented programming, the concept can be difficult to understand. Other modules such as Date::Manip are popular because they're functional interfaces, and a lot of people like DateTime which can deal with fractional seconds and contain a lot more methods. However, Time::Piece is included in Perl, so you know you always have access to it.
Solution 4:[4]
Have you considered using the DateTime package? It contains a lot of date manipulation and computation routines, including the ability to add dates.
There is an FAQ, with examples, here (in particular, see the section on sample calculations and DateTime formats).
Here is a snippet:
use strict;
use warnings;
use DateTime;
my $dt = DateTime->now();
print "Now: " . $dt->datetime() . "\n";
print "Now (epoch): " . $dt->epoch() . "\n";
my $two_days_from_now = $dt->add(days => 2);
print "Two days from now: " . $two_days_from_now->datetime() . "\n";
print "Two days from now (epoch): " . $two_days_from_now->epoch() . "\n";
Which produces the following output:
Now: 2013-02-23T18:30:58
Now (epoch): 1361644258
Two days from now: 2013-02-25T18:30:58
Two days from now (epoch): 1361817058
Solution 5:[5]
Use Time::Moment for all your timely needs
Time::Moment is a SUPERIOR alternative to DateTime and Time::Piece with a smaller foot print and better performance (FASTER).
Considering these articles:
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | TLP |
| Solution 2 | Sue D. Nymme |
| Solution 3 | David W. |
| Solution 4 | user 12321 |
| Solution 5 |
