Beefy Boxes and Bandwidth Generously Provided by pair Networks
P is for Practical
 
PerlMonks  

How do I find the difference in days between two dates, in a cool perl way?

by frankus (Priest)
on Jun 08, 2000 at 15:53 UTC ( [id://17057]=perlquestion: print w/replies, xml ) Need Help??

frankus has asked for the wisdom of the Perl Monks concerning the following question: (dates and times)

How do I find the difference in days between two dates, in a cool perl way?

Originally posted as a Categorized Question.

  • Comment on How do I find the difference in days between two dates, in a cool perl way?

Replies are listed 'Best First'.
Re: How do I find the difference in days between two dates, in a cool perl way?
by reptile (Monk) on Jun 08, 2000 at 22:44 UTC
    If the dates are in epoch seconds, take the difference and divide it by the number of seconds in a day (which is 86400). Like so:
    my $days_difference = int(($time1 - $time2) / 86400);
    The int() there, by the way, chops off the decimal so you don't end up with something like 4.3231235. If you're curious, the remainder of that division is the number of seconds left after finding the number of days, so if you want "x days, x hours", you can do this next:
    my $hours_left = int((($time1 - $time2) % 86400) / 3600);
    That should give you an idea. If your dates aren't in epoch seconds, you'll either have to get them there somehow, or check out one of the Date::* modules.
Re: How do I find the difference in days between two dates, in a cool perl way?
by mojotoad (Monsignor) on Feb 05, 2003 at 06:25 UTC
    Check out Time::Piece. This overides localtime(), gmtime(), arithmetic operations, and stringification so that date calculations are remarkably simple. For example:

    use Time::Piece; $before = Time::Piece->strptime("2001/01/01", "%Y/%m/%d"); $now = localtime; $diff = $now - $before; print int($diff->days), " days since $before\n";
Re: How do I find the difference in days between two dates, in a cool perl way?
by autarch (Hermit) on May 10, 2004 at 19:39 UTC
    Using DateTime (assuming $dt1 and $dt2 are DateTime objects):
    my $duration = $dt1->delta_days($dt2); print $duration->days;
      I believe this is incorrect. print $duration->days; Should be print $duration->delta_days; if your delta is greater than or equal to a calendar week.

        Anonymous Monk is correct.

        #!/usr/bin/env perl use strict; use warnings; use Test::More tests => 4; use DateTime; my $dt1 = DateTime->new ( year => 2015, month => 6, day => 1 ); my $dt2 = DateTime->new ( year => 2015, month => 6, day => 30 ); my $duration = $dt1->delta_days ($dt2); is $duration->days, 29, 'Without delta, more than a week'; is $duration->delta_days, 29, 'With delta, more than a week'; $dt2 = DateTime->new ( year => 2015, month => 6, day => 3 ); $duration = $dt1->delta_days ($dt2); is $duration->days, 2, 'Without delta, less than a week'; is $duration->delta_days, 2, 'With delta, less than a week';

        Test 1 fails for me (with DateTime 1.20) but the others all pass. This fits with the description of the days() method on a duration which says:

        These methods return numbers indicating how many of the given unit the object represents, after having done a conversion to any larger units. For example, days are first converted to weeks, and then the remainder is returned.
Re: How do I find the difference in days between two dates, in a cool perl way?
by phenom (Chaplain) on May 10, 2004 at 23:04 UTC
    Using Date::Calc:
    #!/usr/bin/perl use strict; use warnings; use Date::Calc qw/Delta_Days/; my @first = (2001, 9, 12); my @second = (2004, 3, 11); my $dd = Delta_Days( @first, @second ); print "Difference in days: $dd\n";
Re: How do I find the difference in days between two dates, in a cool perl way?
by le (Friar) on Jun 08, 2000 at 15:59 UTC
    There's a module called Date::Calc that offers various ways to manipulate and calculate dates.

    Originally posted as a Categorized Answer.

Re: How do I find the difference in days between two dates, in a cool perl way?
by talexb (Chancellor) on Apr 21, 2016 at 14:07 UTC
    Use the utc_rd_values method in DateTime to get the day number of the date you're looking at:
    my @start = $dt1->utc_rd_values; my @finish = $dt2->utc_rd_values; my $delta = $finish[0] - $start[0];
    Now $delta contains the number of days between the two dates.
Re: How do I find the difference in days between two dates, in a cool perl way?
by swngnmonk (Pilgrim) on May 10, 2004 at 19:55 UTC
    [QandAEditor's note: the answer that had used ONE_MONTH has been fixed. Thanks to swngnmonk for pointing this out]

    A note on Time::Piece - While I love it, and I use it heavily, the ONE_MONTH constant is fundamentally broken, because there's no such thing as a constant value for a month.

    For example:

    #!/usr/bin/perl use Time::Piece; use Time::Seconds; my $now = localtime; print sprintf("Now = %s\n", $now->cdate); for (1..12) { $now += ONE_MONTH; print sprintf("Now + %02i months = %s\n", $_, $now->cdate); }

    Outputs something like this:

    bash-2.05b$ ./broken.pl Now = Mon May 10 15:56:13 2004 Now + 01 months = Thu Jun 10 02:25:17 2004 Now + 02 months = Sat Jul 10 12:54:21 2004 Now + 03 months = Mon Aug 9 23:23:25 2004 Now + 04 months = Thu Sep 9 09:52:29 2004 Now + 05 months = Sat Oct 9 20:21:33 2004 Now + 06 months = Tue Nov 9 05:50:37 2004 Now + 07 months = Thu Dec 9 16:19:41 2004 Now + 08 months = Sun Jan 9 02:48:45 2005 Now + 09 months = Tue Feb 8 13:17:49 2005 Now + 10 months = Thu Mar 10 23:46:53 2005 Now + 11 months = Sun Apr 10 11:15:57 2005 Now + 12 months = Tue May 10 21:45:01 2005

    Originally posted as a Categorized Answer.

Re: How do I find the difference in days between two dates, in a cool perl way?
by shmem (Chancellor) on Apr 21, 2016 at 22:28 UTC
    perl -MDate::Parse -le 'print+(str2time(pop) - str2time(pop)) / 86400' + 2016-02-28 2016-03-01 2
    Note, however, that it seems not to work for dates before January 1st 1967. At least, not with Date::Parse version 2.30, which is the version I have.

    Update: this seems to be a long-known bug: rt://105031; rt://84075 gives a little more info as well.

Re: How do I find the difference in days between two dates, in a cool perl way?
by parv (Parson) on May 10, 2004 at 20:17 UTC

    Below is the code to convert, among other things, Unix epoch seconds to year, month ... minute, second. What i have not tested is if it is any better in terms of accuracy than using built-in localtime(), or various epoch based date/time modules.

    #!/usr/local/bin/perl -w use strict; # About: # ----- # Author: Parv, parv underscore at yahoo dot com # Modified: dec 20 2000 # # Currently this program does the below stated conversion, but can be # (easily) extended to do other conversions. # # Unix date/time in seconds is converted to year, month, day, hour, # minute, second. # # Credits: # ------- # This program's date conversion algorithm is based on an # article about inter-date conversions (shown via JavaScript); # author of the article is John Walker, founder of AutoCad. # Article copies are available at many places, two of which 're... # # http://www.fourmilab.ch/documents/calendar/ # http://www.michaelmccafferty.com/mmmdate.htm # # ...The article recommends/referrers to... # # 1. Astronomical algorithms, # Mjean Meeus; 1991; ISBN: 0-943396-35-2 # # 2. Explanatory supplement to the astronomical almanac, # p. Kenneth Seidelmann (ed.); 1992; ISBN: 0-935702-68-7 # # adjust unix epoch in julian day by 0.5 so that day starts on # midnight instead of noon # use constant Unix_Epoc_Julian => 2440587.5 +0.5; # other constants use constant Avg_JulianCal_Yr => 365.25; use constant Avg_GregorianCal_Yr => 365.2425; convert_show_datetime(@ARGV); sub convert_show_datetime { for (@ARGV) { # check if an argument is a digit(s) # unless (m#\d+#) { print "\n# $_ is not a number, skipping...\n"; next; } # convert given seconds into (fractional) julian days # my $t = unixSec2julianDay($_); my $t_2 = int($t); my $diff = $t - $t_2; # get date & time... my ($year, $month, $day) = julianDay2date($t_2, $diff); my ($hour, $min, $sec) = julianDay2time($diff); print <<DATETIME; for $_ ... ...date (year month day) is: $year $month $day ...time (hour minute sec) is: $hour $min $sec DATETIME } } sub unixSec2julianDay { # convert unix seconds time to fractional julian day my ($sec) = @_; return 0 if not_digit($sec); return Unix_Epoc_Julian + ($sec /60 /60 /24); } sub julianDay2time { # return fractional julian day as list of hour, minute, second # my ($diff) = @_; return ('00', '00', '00') if not_digit($diff); # convert difference of julian days to seconds # my $sec = $diff *60 *60 *24; # zero-pad upto 2 characters before giving hour, minute, # second (in that order) # return ( sprintf("%02s", int($sec /60 /60)), sprintf("%02s", int(($sec /60) %60)), sprintf("%02s", int($sec %60)) ); } sub julianDay2date { # return fractional julian day as list of year, month, day # my ($days, $diff) = @_; if (not_digit($days) || not_digit($diff)) { return ('0000', '00', '00'); } my ($x, $y, $m, $d); # calculate year, month, day # if ($days < 2299161) { $x = $days; } else { $y = int( ($days -1867216.25) / Avg_GregorianCal_Yr /100 ); $x = $days + $y - int($y /4) +1; } $y = int( ($x +1524 -122.1) / Avg_JulianCal_Yr ); $m = int( ($x +1524 - int($y * Avg_JulianCal_Yr)) /30.6001 ); $d = int( $x +1524 + $diff - int($y * Avg_JulianCal_Yr) - int($m *30. +6001) ); $m = ($m < 14) ? ($m -1) : ($m -13); $y = ($m > 2) ? ($y -4716) : ($y -4715); # zero-pad year, month, day before returning # return ( sprintf("%04s", $y), sprintf("%02s", $m), sprintf("%02s", $d) ); } sub not_digit { my ($d) = @_; return 1 if !((defined $d) || ($d =~ m/\d+/)); return 0; }

    Originally posted as a Categorized Answer.

A reply falls below the community's threshold of quality. You may see it by logging in.
A reply falls below the community's threshold of quality. You may see it by logging in.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://17057]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others exploiting the Monastery: (7)
As of 2024-04-23 07:07 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found