Beefy Boxes and Bandwidth Generously Provided by pair Networks
Come for the quick hacks, stay for the epiphanies.
 
PerlMonks  

Add A Number of Days to Today's Date

by rline (Initiate)
on Sep 28, 2001 at 12:09 UTC ( [id://115337]=perlquestion: print w/replies, xml ) Need Help??

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

Hello, I have a perl cgi that saves form data to a flatfile database. One of the form fields asks the user to say whether they need to move (rental property company) in 10 days, 20 days, etc. Anyway, next to that field in the database, I want to add another field which gives a date equal to the date the user submits the form plus the number of days the user selects. So if they submitted it on October 2nd, and selected to move in 20 days, I'd want the field to say "October 22". Can this be done? If so, how? Thankyou very much.

Replies are listed 'Best First'.
Re: Add A Number of Days to Today's Date
by davorg (Chancellor) on Sep 28, 2001 at 12:31 UTC

    Perl finds it all much easier if you deal with dates as the number of seconds since 00:00 Jan 1 1970 (this number, incidently, has just passed one billion). The function time gives this value for the current time and the timelocal function (from the Time::Local module) can convert any date or time into this format.

    You can then use the POSIX::strftime to convert that value into a human-readable string. Here's an example:

    use POSIX 'strftime'; my $now = time; my $then = $now + (20 * 86_400); # 86,400 seconds in a day my $then_str = strftime('%d %B %Y', localtime($then)); print "In 20 days time it will be $then_str\n";

    Of course, it's possible to write that more compactly :)

    use POSIX 'strftime'; print "In 20 days time it will be ", strftime('%d %B %Y', localtime(time + 20 * 86_400)), "\n";
    --
    <http://www.dave.org.uk>

    "The first rule of Perl club is you don't talk about Perl club."

      Hey, Thanks y'all for your time and effort in replying to my question! I really appreciate it. OK. So I understand how to get the date in x days time. How can I automatically insert the variable $then_str into my flatfile database? The database is appended every time a user fills out a form. So there are about 20 fields which are appended. How do I automatically insert the variable $then_str next to, say, the 15th field in the database? So the script needs to pull the 20 user-filled-in values, and then add my created $then_str value next to the 15th value, to make a total of 21 values in the database? Thanks in advance!
Re: Add A Number of Days to Today's Date
by clemburg (Curate) on Sep 28, 2001 at 13:14 UTC

    You should also have a look at Date::Manip and Date::Calc. Both offer a large range of features that will probably cover your needs. Especially Date::Manip's ParseDate() function is a real time saver for tasks like this.

    Example:

    > perl -MDate::Manip -e 'print UnixDate(ParseDate("October 2nd"), "%Y- +% m-%d"), "\n"' 2001-10-02 > perl -MDate::Manip -e 'print UnixDate(DateCalc("October 2nd", "+ 20 +days", \$err), "%Y-%m-%d"), "\n"' 2001-10-22 > perl -MDate::Manip -e 'print UnixDate(ParseDate("today"), "%Y-%m-%d" +) , "\n"' 2001-09-28 > perl -MDate::Manip -e 'print UnixDate(ParseDate("10 days"), "%Y-%m-% +d "), "\n"' 2001-10-08 > perl -MDate::Manip -e 'print UnixDate(ParseDate("10 days ago"), "%Y- +% m-%d"), "\n"' 2001-09-18 > perl -MDate::Manip -e 'print UnixDate(ParseDate("Monday 1 week ago") +, "%Y-%m-%d"), "\n"' 2001-09-17

    Christian Lemburg
    Brainbench MVP for Perl
    http://www.brainbench.com

      I really don't like Date::Manip. Sure it does a lot, but that's it's downfall. In tests I've seen it take fifteen times as long to do simple date manipulations than an equivalent script written using Perl's built-in functions.

      There are times when that's a worthwhile hit to take, but in cases like this where it's very simple to do with built-ins I really don't think it's worthwhile.

      --
      <http://www.dave.org.uk>

      "The first rule of Perl club is you don't talk about Perl club."

        Sure, Date::Manip is slow compared to hand-rolled stuff. It even says so in the POD (see below). So there is no reason to complain about this, you have been warned.

        OTOH, I really think re-solving all those common date calculating problems again and again is a big waste of time, and a big source of errors in programs, too.

        From the Date::Manip POD:

        Date::Manip is certainly the most powerful of the Date modules. To the best of my knowledge, it will do everything that any other date module will do (not just the ones I listed above), and there are a number of features that Date::Manip has that none of the other modules have. Date::Manip is the "Swiss Army Knife" of Date modules. I'm trying to build a library which can do _EVERY_ conceivable date/time manipulation that you'll run into in everyday life. Although I am working on making Date::Manip faster, it will never be as fast as other modules. And before anyone asks, Date::Manip will never be translated to C (at least by me). I write C because I have to. I write perl because I like to. Date::Manip is something I do because it interests me, not something I'm paid for. Date::Manip is also big. The last time I looked, it's one of the largest CPAN modules there is. If you ignore modules like Tk, LWP, etc. which are actually packages of modules, it may be the largest. It's true that Date::Manip will do almost every date operation you could imagine... but you rarely need all that power. I'm working on reducing the footprint of Date::Manip, but even at it's slimmest, it'll outweigh the other modules by a good bit. If you are going to be using the module in cases where performance is an important factor (started up in a CGI program being run by your web server 5,000 times a second), you should check out one of the other Date or Time modules in CPAN. If you're only doing fairly simple date operations (parsing common date formats, finding the difference between two dates, etc.), the other modules will almost certainly suffice. If you're doing one operation very repetitively (parsing 10,000 dates from a database), you are probably better off writing your own functions (perhaps bypassing all date modules entirely) designed specifically for your needs. On the other hand, if you want one solution for all your date needs, don't need peak speed, or are trying to do more exotic date operations, Date::Manip is for you. Operations on things like business dates, foreign language dates, holidays and other recurring events, etc. are available more-or-less exclusively in Date::Manip.

        Christian Lemburg
        Brainbench MVP for Perl
        http://www.brainbench.com

Re: Add A Number of Days to Today's Date
by tachyon (Chancellor) on Sep 28, 2001 at 14:47 UTC
    $days = 10; $then = localtime ( time() + $days * 24*60*60 ); print $then;

    cheers

    tachyon

    s&&rsenoyhcatreve&&&s&n.+t&"$'$`$\"$\&"&ee&&y&srve&&d&&print

      Except when the day is 23 or 25 hours long.
      Probably not noticable but it is slightly faster to do
      $days = 10; $then = localtime(time() + $days * 86400); print $then;
        * 24 * 60 *60

        slightly faster to do ... * 86400

        No, any good optimizer should optimize away those multiplications (in any language) anyway (so if its done in a loop it shouldn't matter, and if its only done once then it makes too little difference to matter), and its better self-documentation IMHO to leave it as '24*60*60' because those numbers mean something to me, whereas 86400 does not. Someone could inadvertently change it to 84600 and I wouldn't notice the difference until many wrong calculations had been done. In any case, this is a bad place for micro-optimizations...

        It makes it obvious what is meant and makes no significant difference to speed whatsoever:

        use Benchmark; $yours = ' $days = 10; $then = localtime(time() + $days * 86400);'; $mine = ' $days = 10; $then = localtime(time() + $days * 24*60*60 );'; timethese ( 100000, { 'yours' => $yours, 'mine' => $mine } ); __END__ Benchmark: timing 100000 iterations of mine, yours... mine: 30 wallclock secs (29.95 usr + 0.00 sys = 29.95 CPU) @ 33 +38.89/s (n=100000) yours: 30 wallclock secs (29.94 usr + 0.00 sys = 29.94 CPU) @ 33 +40.01/s (n=100000)

        sleep 28800 :-) cheers

        tachyon

        s&&rsenoyhcatreve&&&s&n.+t&"$'$`$\"$\&"&ee&&y&srve&&d&&print

Re: Add A Number of Days to Today's Date
by Zaxo (Archbishop) on Sep 28, 2001 at 13:16 UTC

    I like davorg's way, but you might also look at Date::Calc (adapted from perldoc):

    my $Dd = 10; ($year,$month,$day) = Add_Delta_Days($year,$month,$day,$Dd);
    There are lots more ways to choose from

    After Compline,
    Zaxo

(tye)Re: Add A Number of Days to Today's Date
by tye (Sage) on Sep 28, 2001 at 21:16 UTC

    Note that using time()+$nDays*24*60*60 can fail when done near midnight near transitions to or from daylight savings time. This is fairly easy to fix, tho:

    my $now= time(); my($y,$m,$d)= (localtime( $now + 60*60*(12-(localtime($now))[2]) + $nDays*24*60*60 ))[5,4,3]; print sprintf "%04d-%02d-%02d", 1900+$y, 1+$m, $d; print $/;

    Note that the use of $now is required to avoid one race condition but that it isn't enough since doing this calculation near midnight still has a race condition of whether "today" ends up being before mignight or after midnight. So you need to use $now to set all of the dates that get recorded. For this reason, I prefer {NULE}'s solution. But I wanted to point out the problem with two of the other solutions.

            - tye (but my friends call me "Tye")
Re: Add A Number of Days to Today's Date
by {NULE} (Hermit) on Sep 28, 2001 at 17:18 UTC
    Hi rline,

    My approach differs a bit from what other's have posted here, so I'll offer it. I like to avoid modules that others might have to download, because I know first hand that process doesn't always go smoothly. So here is an example that accomplishes two things - first allows your user to specify a date (which are fed to $mday,$mon,$year) and a number of days (fed to $daysFromNow) and using the built-in Time::Local module will return th date you desire. Second it avoids having to specify non-standard modules, or having to manually getting date manipulation right.

    The idea is the same as what the other monks are telling you, I just "like my way better(tm)". I also find it much safer than trusting my dumb brain to handle manipulating dates by hand.

    #! /usr/local/bin/perl -w use strict; use Time::Local; my ($sec,$min,$hour,$mday,$mon,$year) = (0,0,0,22,11,2001); my $daysFromNow = 99; $year-=1900; $mon-=1; $daysFromNow*=86400; my $givenTime = timelocal($sec,$min,$hour,$mday,$mon,$year); $givenTime+=$daysFromNow; ($sec,$min,$hour,$mday,$mon,$year) = localtime($givenTime); $year+=1900;$mon+=1; print "$year-$mon-$mday $hour:$min:$sec\n";
    Good luck!
    {NULE}

    P.S. Opera appears to add carriage returns by itself to these posts - so my apologies if this is mis-formatted.

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others sharing their wisdom with the Monastery: (5)
As of 2024-04-25 14:10 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found