Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Perl: Calculate number of days by converting to seconds

Tags:

perl

I am trying to calculate the number of calendar days between two dates extracted from a database. I thought that converting the dates to seconds would be a simple and correct solution.

#!/usr/bin/perl
use warnings;
use strict;
use POSIX qw(strftime);
use Date::Parse;

my $minDate = "2016-03-27";
my $maxDate = "2016-06-15";

print "Format as extracted from db: mindate: $minDate and maxdate: $maxDate\n"; 

my ($dbYear,$dbMonth,$dbDay) = split ('-', $minDate);
my $datum = "$dbYear$dbMonth$dbDay";
my $minDateSec = str2time($datum);

($dbYear,$dbMonth,$dbDay) = split ('-', $maxDate);
$datum = "$dbYear$dbMonth$dbDay";
my $maxDateSec = str2time($datum);

my $numCalDaysSec = ($maxDateSec-$minDateSec)/86400;

print "Min date in Seconds: $minDateSec\n";
print "Max date in Seconds: $maxDateSec\n";
print "Num days: $numCalDaysSec\n";

Initially, I thought that this method provided me with reliable results:

bash-3.2$ ./testNumDays.pl
As extracted from db: mindate: 2016-06-14 and maxdate: 2016-06-15
Min date in Seconds: 1465855200
Max date in Seconds: 1465941600
Num days: 1
bash-3.2$ ./testNumDays.pl
As extracted from db: mindate: 2016-05-31 and maxdate: 2016-06-15
Min date in Seconds: 1464645600
Max date in Seconds: 1465941600
Num days: 15
bash-3.2$ ./testNumDays.pl
As extracted from db: mindate: 2016-03-28 and maxdate: 2016-06-15
Min date in Seconds: 1459116000
Max date in Seconds: 1465941600
Num days: 79
bash-3.2$ ./testNumDays.pl
As extracted from db: mindate: 2016-03-27 and maxdate: 2016-06-15
Min date in Seconds: 1459033200
Max date in Seconds: 1465941600
Num days: 79.9583333333333
bash-3.2$

Obviously, the number of calendar dates between dates should be an integer. Mmmm, what I am doing wrong? Why is converting to seconds not reliable?

Since I am a Perl newbie, I am probably overlooking the obvious. Any help is therefore more than welcome.

like image 293
Ga Mmeeu Avatar asked Jun 16 '16 15:06

Ga Mmeeu


3 Answers

One way is to use the Time::Piece Core module:

use warnings;
use strict;
use Time::Piece qw();

my $t1 = Time::Piece->strptime('2016-03-27', '%Y-%m-%d');
my $t2 = Time::Piece->strptime('2016-06-15', '%Y-%m-%d');
my $seconds = $t2 - $t1;
print $seconds->days(), "\n";

__END__

80
like image 136
toolic Avatar answered Nov 15 '22 08:11

toolic


An alternative is DateTime. It's not in Core, but it's often very handy. Because it doesn't parse dates, we quickly made our own parsing function.

use strict;
use warnings;
use DateTime;
my $minDate = "2016-03-27";
my $maxDate = "2016-06-15";

sub parse {
    my $date = shift;

    my ( $y, $m, $d ) = split /-/, $date;

    return DateTime->new( year => $y, month => $m, day => $d );
}

my $days = parse($minDate)->delta_days(parse($maxDate))->in_units('days');
print $days;

__END__

80
like image 22
simbabque Avatar answered Nov 15 '22 07:11

simbabque


You are making the invalid assumption that every day is 86,400 seconds long.

Please go to http://www.timeanddate.com/time/dst/2016.html and look at all of the places where Daylight Saving Time (aka Summer Time) starts on 27 Mar 2016. That day is not 86,400 seconds long.

like image 45
hymie Avatar answered Nov 15 '22 07:11

hymie