Beefy Boxes and Bandwidth Generously Provided by pair Networks DiBona
Welcome to the Monastery
 
PerlMonks  

Subtracting and Comparing Two Dates

by mindful07 (Initiate)
on Jan 08, 2007 at 17:06 UTC ( [id://593632]=perlquestion: print w/replies, xml ) Need Help??

This is an archived low-energy page for bots and other anonmyous visitors. Please sign up if you are a human and want to interact.

mindful07 has asked for the wisdom of the Perl Monks concerning the following question:

I need your help with two issues I am having:

How do you subtract two dates (both in the format of YYYYMMDD) to obtain the value in days? One date will always be local date and I'm using strftime("%Y%m%d", localtime(time) to obtain it. I do not have nor can I use the Time:Piece or Date:Calc modules at this time. The problem I am having is as long as its the same year (for example 20070108 - 20070101) my code will work fine giving me 7 days. But if I have 20070108 - 20061228 it will return an incorrect amount of days.

My second issue is once I get the amount of days it doesnt appear that I'm able to compare it. I have a variable called $diff_days that returns 7. I then want to compare $diff_days > 15 or $diff_days = 15. Is that possible? What is the best way to handle that because I get a syntax error.

Could you please provide examples since I am very new to Perl.

Replies are listed 'Best First'.
Re: Subtracting and Comparing Two Dates
by jettero (Monsignor) on Jan 08, 2007 at 17:14 UTC

    I think you probably want to look at POSIX (for strftime) and Time::Local qw(timelocal) as I discovered a year or so ago in Fast date parsing — although, for totally different reasons.

    Without being able to use Date::Manip or Date::Calc (why again?) — I would personally probalby convert the dates to epoch seconds (strftime's %s) and subtract those. It'd be a bit more reliable than subtracting ... er, the mess you're subtracting.

    -Paul

      I don't have Time::Piece or Date::Calc modules loaded for the version of Perl I am working with and as of right now its not recommended that I load them.
Re: Subtracting and Comparing Two Dates
by kyle (Abbot) on Jan 08, 2007 at 17:50 UTC

    Crude and slow, but it doesn't require anything but what you already have (strftime), and it should work (I haven't tried it)...

    my $date_in_past = '20070101'; # YYYYMMDD my $ONE_DAY = 24 * 60 * 60; my $days_ago = 0; my $now = time(); while ( $date_in_past < strftime('%Y%m%d', localtime( $now - $days_ago*$ONE_DAY ) ) ) { $days_ago++; }

    I'm not proud. I guess without Date::Calc, I really am lost.

Re: Subtracting and Comparing Two Dates
by BaldPenguin (Friar) on Jan 08, 2007 at 17:54 UTC
    Try this, you have to use POSIX, but ...
    use POSIX qw/difftime mktime/; my $now = time(); my @then = ($ARGV[0] =~ /^(\d{4})(\d{2})(\d{2})/); my $then = mktime(0,0,0,$then[2],$then[1]-1,$then[0]-1900); my $diff = difftime($now,$then); printf("%d days", int($diff/86400) ); printf(", %d hours", int( $diff%86400)/3600 ); printf(", %d minutes ", int( ($diff%86400)%3600 )/60 ); printf(", %d seconds \n", ( ($diff%86400)%3600 )%60 );
    It may not be elegant, and could defintely benefit from some cleaner formatting like use of constants, but it gets the point across

    Don
    WHITEPAGES.COM | INC
    Everything I've learned in life can be summed up in a small perl script!

      Your solution doesn't always give the right answer.

      Then Now Date::Calc BaldPenguin ---------- ------------------- ----------- ----------- 2005/08/01 2006/10/29 00:59:00 454 453.9993056 <- XXX 2005/08/01 2006/10/29 02:01:00 454 454.0840278 <- ok
      use strict; use warnings; use POSIX qw( difftime mktime strftime ); use Time::Local qw( timegm timelocal ); use Date::Calc qw( Delta_Days ); use constant ONE_DAY_IN_SECS => 24 * 60 * 60; sub baseline { my ($then_date_str, $now) = @_; my ($y1, $m1, $d1) = $then_date_str =~ /^(\d{4})(\d{2})(\d{2})\z/; my ($y2, $m2, $d2) = (localtime($now))[5,4,3]; $y2 += 1900; $m2 += 1; return Delta_Days($y1, $m1, $d1, $y2, $m2, $d2); } sub bald_penguin { my ($then_date_str, $now) = @_; my @then = $then_date_str =~ /^(\d{4})(\d{2})(\d{2})/; my $then = mktime(0,0,0,$then[2],$then[1]-1,$then[0]-1900); return difftime($now, $then) / ONE_DAY_IN_SECS; } { print("Then Now Date::Calc BaldPenguin\n" +); print("---------- ------------------- ----------- -----------\n" +); for ( [ '20050801', timelocal(0, 59, 0, 29, 10-1, 2006) ], [ '20050801', timelocal(0, 1, 2, 29, 10-1, 2006) ], ) { printf("%s %s %3d %3d %11.7f\n", do { my ($y, $m, $d) = $_->[0] =~ /^(\d{4})(\d{2})(\d{2})\z/; + sprintf("%04d/%02d/%02d", $y, $m, $d) }, strftime('%Y/%m/%d %H:%M:%S', localtime($_->[1])), baseline(@$_), bald_penguin(@$_), ); } }
Re: Subtracting and Comparing Two Dates
by ikegami (Patriarch) on Jan 08, 2007 at 17:58 UTC
    # Always use gmtime and timegm when # dealing with dates without times. use Time::Local qw( timegm ); # Replace with your input. my $then_date_str = 'YYYYMMDD'; my $then_date = do { my ($y, $m, $d) = $then_date_str =~ /^(.{4})(.{2})(.{2})\z/; $m--; timegm(0, 0, 0, $d, $m, $y) }; my $now_date = do { my ($y, $m, $d) = (localtime())[5,4,3]; timegm(0, 0, 0, $d, $m, $y) }; my $diff = $now_date - $then_date; my $diff_days = int($diff / (24*60*60)); if ($diff_days < -1) { printf("%d days ago\n", -$diff_days); } elsif ($diff_days == -1) { print("yesterday\n"); } elsif ($diff_days == 1) { print("tomorrow\n"); } elsif ($diff_days > 1) { printf("%d days from now\n", $diff_days); } else { print("today\n"); }

    Notes:

    • Time::Local is a core module.
    • I advise against this method. Use Date::Calc.
    • It only supports dates time can return.

    Update: Oops, I was subtracting from $m twice. Fixed.

      For my own clarification, what benefits are there to using Time::Local instead of POSIX. The functionality seems to be the same. Is implemetation different? Or is it just a preference thing?

      Don
      WHITEPAGES.COM | INC
      Everything I've learned in life can be summed up in a small perl script!
        I don't see anything in POSIX similar to Time::Local's timegm. To which POSIX function were you refering?
      Right now I do not have Date::Calc installed and I'm trying to figure out how I can get the value in days of two dates. Here is my code to give you an idea of what I'm trying to accomplish.

      If I somehow can get date::calc installed could I just then do $diff_in_days = Delta_days($sysdate, $installed_date)? Also in the event I can't install date::Calc can you please give a suggestion of how else to accomplish this?

      use POSIX qw(strftime); use Time::Local; #use Date::Calc qw(:all); #use time::Piece; #use Date::Calc qw(Delta_Days); sub give_warning { my($carrier) = @_; my($installed_date); my($max_days) = 15; $installed_date = get_value($carrier ."_DAYS", $trn_info, '') ; printf("Value of Carrier Days is $installed_date \n"); if ($installed_date ne "" ) { my $sysdate = decode_date ('SYSDATE','CCYYMMDD'); printf("Todays date is $sysdate \n"); my $diff_in_days = $sysdate - $installed_date ; print "Difference in days: $diff_in_days\n"; if $result > $max_days # give error and return { &print_error ("New Installation is required."); return 1; } elsif $result <= $max_days # give warning and return { &print_warning ("New Installation is required."); return 0; } } else { return 0; } }
        Why do you want me to look at this? The code in the post to which you replied does exactly what you want.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://593632]
Approved by jettero
help
Sections?
Information?
Find Nodes?
Leftovers?
    Notices?
    hippoepoptai's answer Re: how do I set a cookie and redirect was blessed by hippo!
    erzuuliAnonymous Monks are no longer allowed to use Super Search, due to an excessive use of this resource by robots.