I'm new in Perl. I want to calculate days (e.g. 5 days) after input.
Steps I need to cover:
1. start_date: 08.12.2015
2. add 5 days
3. end date: ?
My idea is to convert the start date into a timestamp. Then I add 5*84.400 seconds. After that, I want to re-convert the end timestamp.
I read the Time::Local module docs, but I did not understand the logic yet.
Is this the right way to handle date calculations?
You can do it using DateTime and DateTime::Format::Strptime. Like this:
use strict;
use DateTime;
use DateTime::Format::Strptime;
my $strp = DateTime::Format::Strptime->new(
pattern => '%d.%m.%Y'
);
my $date = '08.12.2015';
my $dt = $strp->parse_datetime($date);
printf "%s -> %s\n", $date, $dt->add(days => 5)->strftime("%d.%m.%Y");
Using Time::Piece
#!/usr/bin/env perl
use v5.10;
use Time::Piece;
use Time::Seconds;
my $date_string = '08.12.2015';
my $date_format = '%m.%d.%Y';
my $tp = Time::Piece->strptime( $date_string, $date_format );
$tp += 5 * ONE_DAY;
say $tp->strftime($date_format);
Outputs:
08.17.2015
Or another way, in vanilla perl (no use of packages needed), with help from Unix date:
$ date -d 08/12/2015
Wed, Aug 12, 2015 12:00:00 AM
$ date -d 08/12/2015 +%s
1439352000
$ date -d 08/12/2015 +%s|perl -ne 'print scalar localtime $_ + 5*24*60*60'
Mon Aug 17 00:00:00 2015
Related
I wanna calculate the date a week ago from today with a specific format and put it in to a variable. For example, today is Nov 21st. 2014, and I wanna print out: Last week is 2014-11-14.
I know we can use Date::Calc module, but I don't know how.
Check Time::Piece and Time::Seconds core modules,
use Time::Piece;
use Time::Seconds;
my $t = localtime() - ONE_WEEK;
print $t->ymd;
output
2014-11-14
DateTime version
use DateTime;
my $now = DateTime->now(time_zone => 'local')->subtract(weeks => 1);
print $now->ymd, ' ',$now->hms;
Date::Calc version
Instead of one week you can subtract 7 days using Date::Calc module
use Date::Calc qw(Add_Delta_Days);
my #date = Add_Delta_Days( 2014, 11, 21, -7 );
print join('-', #date);
OUTPUT
2014-11-14
This is very simple using Date::Manip
use Date::Manip;
my $today = ParseDate("today");
my $weeksago = DateCalc($today,"-7d");
Why not just subtract X days from the "mday" field of localtime? This example shows subtracting 60 days from the end of august. I'm not sure who corrects the month but I think I'm getting the right answer...
$ date
Wed Aug 30 14:34:14 DFT 2017
$ perl -MPOSIX -e '#t=localtime time; $t[3] -= 60; print strftime( "%Y/%m/%d", #t), "\n";'
2017/07/01
I wanna calculate the date a week ago from today with a specific format and put it in to a variable. For example, today is Nov 21st. 2014, and I wanna print out: Last week is 2014-11-14.
I know we can use Date::Calc module, but I don't know how.
Check Time::Piece and Time::Seconds core modules,
use Time::Piece;
use Time::Seconds;
my $t = localtime() - ONE_WEEK;
print $t->ymd;
output
2014-11-14
DateTime version
use DateTime;
my $now = DateTime->now(time_zone => 'local')->subtract(weeks => 1);
print $now->ymd, ' ',$now->hms;
Date::Calc version
Instead of one week you can subtract 7 days using Date::Calc module
use Date::Calc qw(Add_Delta_Days);
my #date = Add_Delta_Days( 2014, 11, 21, -7 );
print join('-', #date);
OUTPUT
2014-11-14
This is very simple using Date::Manip
use Date::Manip;
my $today = ParseDate("today");
my $weeksago = DateCalc($today,"-7d");
Why not just subtract X days from the "mday" field of localtime? This example shows subtracting 60 days from the end of august. I'm not sure who corrects the month but I think I'm getting the right answer...
$ date
Wed Aug 30 14:34:14 DFT 2017
$ perl -MPOSIX -e '#t=localtime time; $t[3] -= 60; print strftime( "%Y/%m/%d", #t), "\n";'
2017/07/01
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.
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))'
How to convert date in text format:
23.10.2011 11:35:00
to timestamp ?
Using Time::Local , you can do:
use Time::Local;
my $date = '23.10.2011 11:35:00';
my ($mday,$mon,$year,$hour,$min,$sec) = split(/[\s.:]+/, $date);
my $time = timelocal($sec,$min,$hour,$mday,$mon-1,$year);
print $time,"\n",scalar localtime $time;
Output:
1319362500
Sun Oct 23 11:35:00 2011
I'd look into DateTime and the parsing modules.
perl -MDateTime::Format::Strptime -le'$strp = DateTime::Format::Strptime->new( pattern => "%d.%m.%Y %T", time_zone => "local"); $dt = $strp->parse_datetime("23.10.2011 11:35:00"); print $dt->epoch'
1319384100 at -e line 1.
Same as above, but not a one-liner:
use DateTime::Format::Strptime;
my $strp = DateTime::Format::Strptime->new(
pattern => '%d.%m.%Y %T',
time_zone => 'local',
);
my $dt = $strp->parse_datetime('23.10.2011 11:35:00');
print $dt->epoch;
Using Date::Parse in Perl is very elegante option too.
Maybe someone will found this useful:
$gmtdate = 'Jul 12 00:12:26 2021 GMT';
my $timestamp = str2time($gmtdate);
Not sure why the Time::Piece answer was deleted. Maybe because it (Time::Piece) has its quirks. But it's more powerful than Date::Parse (although less powerful than DateTime, but some say it covers most of the needs), it's a core module, and you don't have to parse the string as with Time::Local. But datetime math is apparently not DST-safe.
Long story short:
use Time::Piece;
my $tp = Time::Piece->strptime("23.10.2011 11:35:00",
"%d.%m.%Y %H:%M:%S");
# or this way (if the timestamp is in the local time zone):
# $tp = localtime->strptime("23.10.2011 11:35:00",
# "%d.%m.%Y %H:%M:%S");
print $tp;
More on creating Time::Piece objects here.