Beefy Boxes and Bandwidth Generously Provided by pair Networks
go ahead... be a heretic

Date function

by Anonymous Monk
on Aug 02, 2013 at 15:50 UTC ( #1047614=perlquestion: print w/replies, xml ) Need Help??

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

Hi, I am new at perl so any help is appreciated. I am trying to write something along the lines of a date function. Essentially I want to return yesterdays date but I am having problems with my if statements.
use strict; use warnings; ### Date my ($sec,$min,$hour,$mday,$month,$year,$wday,$yday,$isdst) = localtime +(); $year += 1900; $mday -= 1; if ($mday == 0) { $month -= 1; } if ($month == 1||3||5||7||8||10||12) { $mday = 31; } elsif ($month == 4||6||9||11) { $mday = 30; } elsif ($month == 2) { print "is this a leap year"; } if ($month == 0) { $year -= 1; $month = 12; } print ($sec."\n",$min."\n",$hour."\n",$mday."\n",$month."\n",$year."\n +",$wday."\n",$yday."\n",$isdst."\n");
I'm pretty sure the problem will be with my style. I simply cant find whats wrong with it? The output is below
56 45 11 31 7 2013 5 213 1
It should read as:
56 45 11 1 7 2013 5 213 1

Replies are listed 'Best First'.
Re: Date function
by toolic (Bishop) on Aug 02, 2013 at 15:59 UTC
    if ($month == 1||3||5||7||8||10||12)
    That probably doesn't do what you think it does. I believe you meant:
    if ($month == 1 || $month == 3 || $month == 5 etc...
      Yes, that would help. Is there any way to compact the code so that it has fewer characters? Also, I am still getting the output for  $mday to be 31. This means that it is interpreting  if ($mday == 0) as true. However since today is the 2nd and the previous day was the 1st; this should be false.
        Is there any way to compact the code so that it has fewer characters?
        Use a hash. Or one of the date modules, like Date::Simple
        use warnings; use strict; use Date::Simple qw(today); print 'today = ', today(), "\n"; print 'yesterday = ', today() - 1, "\n"; __END__ today = 2013-08-02 yesterday = 2013-08-01
        if (grep { $month == $_ } (1,3,5,7,8,10,12)) {
Re: Date function
by CountZero (Bishop) on Aug 02, 2013 at 16:47 UTC
    Date calculations are tricky. There are many edge cases that can trip you up.
    use Modern::Perl; use Date::Calc qw/Add_Delta_Days/; my ($year,$month,$day) = Add_Delta_Days(2013,8,1, -1); say "$day-$month-$year";


    A program should be light and agile, its subroutines connected like a string of pearls. The spirit and intent of the program should be retained throughout. There should be neither too little or too much, neither needless loops nor useless variables, neither lack of structure nor overwhelming rigidity." - The Tao of Programming, 4.1 - Geoffrey James

    My blog: Imperial Deltronics
      The documentation of Date::Calc describes a few of these that I would never have dreamed of!
Re: Date function
by Cristoforo (Curate) on Aug 02, 2013 at 16:55 UTC
    A solution for this simple task could be
    #!/usr/bin/perl use strict; use warnings; use POSIX 'strftime'; my @date = (localtime)[0 .. 5]; $date[3]--; print strftime "%Y-%m-%d", @date;
    This will give you the previous day (and roll back the month if today is the 1st).
      This is what I need... How can I define and print the day, month and year from this code? Does  $date[3] mean that its picking up the 4 element in the "list?" Thank you for this piece of code!
        Yes, $date[3] is the day, (the 4th element in the array), and I'm subtracting 1 from it. @date has (secs mins hour day month year) from localtime. I'm taking a slice of the list returned by localtime, elements 0 to 5.
        How can I define and print the day, month and year from this code?
        See POSIX and find there 'strftime'. The date format uses the specifiers found here. (i.e, %Y-%m-%d)

        That is what my print statement does.

        Update: After thinking it over, I would not recommend using my suggestion and use one of the Date modules like toolic or CountZero suggested. For an example why mine could be in error, suppose you were 1 day past the daylight savings time beginning. You might go back a day to a nonexistent hour, (when Daylight savings went into effect) by simply subtracting a day and not accounting for the hour.

        Date/times are tricky.

Re: Date function
by Laurent_R (Canon) on Aug 02, 2013 at 17:58 UTC

    You should probably use one of the existing date modules, but if you want to do it yourself, take a look at a possible simple solution in this session under the perl debugger:

    DB<8> $c = time DB<9> p $c 1375466025 DB<10> $c -= 3600*24 DB<11> $d = localtime $c DB<12> p $d Thu Aug 1 19:53:45 2013

    which is exactly one day ago in my local time zone.

Re: Date function
by cursion (Pilgrim) on Aug 02, 2013 at 20:52 UTC
    It looks like you can display the current date and time. You just need to subtract 24 hours from now to get to yesterday.
    localtime( time() - (24 * 60 * 60) );
    Combine that with strftime() and youre done.

    EDIT (after comment below): Make sure your timezone is set correctly too.

      A reasonable approach, though if you live somewhere that observes daylight savings, it will produce incorrect results for one hour, twice each year.

      package Cow { use Moo; has name => (is => 'lazy', default => sub { 'Mooington' }) } say Cow->new->name
Re: Date function
by ww (Archbishop) on Aug 02, 2013 at 19:24 UTC

    Alternately, a regex will work:

    perl -E "my $month=3;if ($month =~ / 1|3|5|7|8|10|12/ ) {say $month; }else{say 'goofed.';}"

    Prints: 3

    If you didn't program your executable by toggling in binary, it wasn't really programming!

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1047614]
Approved by toolic
Front-paged by toolic
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others chilling in the Monastery: (3)
As of 2021-01-23 13:20 GMT
Find Nodes?
    Voting Booth?