Comment On Perly Dates

Jeff D works on a team that develops applications on just about any platform under the sun. One day, a perl-based application they developed for a client just stopped working. This was actually a pretty common occurrence; the perl programmer who built the app would just jump in, do his magic, and voilà, it'd be fixed. But this time, the perl guy was unavailable, leaving Jeff (who had no perl experience whatsoever) to fix the problem. [expand full text]
« PrevPage 1 | Page 2 | Page 3Next »

Re: Perly Dates

2005-07-20 14:28 • by Fregas

damnit!  I'm the first poster for once, but I don't read Perl!  I have nothing to say!  arrrg!

Re: Perly Dates

2005-07-20 14:34 • by Owen
38788 in reply to 38787
leap years?  what leap years?

Re: Perly Dates

2005-07-20 14:34 • by JThelen
38789 in reply to 38787
Anonymous:

damnit!  I'm the first poster for once, but I don't read Perl!  I have nothing to say!  arrrg!





It's another reinventing the wheel.  The so called 'Perl Guy' uses
/bin/date to reproduce a handful of Perl date functions, which Alex
linked to.



It's a pretty big WTF, but it doesn't burn like some of them do.

Re: Perly Dates

2005-07-20 14:35 • by Munk Yee
How about those scalar names too?  eek!



it_is_the_first_of_the_year
it_is_the_first_of_the_month

Re: Perly Dates

2005-07-20 14:39 • by David

haha...so if it is the first of the year it returns the first day of last year as yesterday's date?


I also love how he has a separate if block after the first chunk of code to assign a value to $ftpdate when he could have done that in the first block of code.  He was smart enough to do one elsif if it was not the first of the year, but couldn't do another if it was also not the first of the month.


 


Of course I'm not a perl programmer, so I have no idea how much worse this general method is than the built in module.

Re: Perly Dates

2005-07-20 14:40 • by Rick
I only caught 2 failures. Did Jeff have to step in on the day after February 29th or on January 1st???



I really like subtracting 1 from $datestring. Does he append "0" when he wants to multiply by 10??

Re: Perly Dates

2005-07-20 14:47 • by th0mas
38793 in reply to 38791
Of course I'm not a perl programmer, so I have no idea how much worse this general method is than the built in module.



(not going to try to quoteblock it, forum will just spit it out)



anyways, we could use localtime(time()) to convert to a nice array of
day/month/etc then do the "are we first of month", etc, but it's easier
just to:



$sec_in_day = 60*60*24;

$yesterday = time() - $sec_in_day;

my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($yesterday);

print "yesterday was $mday/" . ($mon+1) . "/" . ($year+1900) . "\n";



Re: Perly Dates

2005-07-20 14:49 • by Hermann Klinke
38794 in reply to 38787
Exactly, that is the WTF: they used Perl!

 

P.S.: Don't flame me, I don't know anything about Perl, but the language looks so fucked up, that I just had to make that comment ;-).

Re: Perly Dates

2005-07-20 14:51 • by mizhi
Hey now, this is the Perl Way: TIMTOWTDI!



To be honest, 'Perl Guy' looks like a guy who enjoys his unix. 
It's not uncommon to find code that captures the output of a command to
be used in a program/script.



That said, doing it for /bin/date is pretty silly.  Not to mention
the fact that he does it incorrectly; ignoring leap years, and saying
that the previous day of the first of the year is December 1st. 
But those have already been mentioned.



The more serious wtfery is the fact that this code is totally non-portable.  Try running it on Windows.

Re: Perly Dates

2005-07-20 14:54 • by mizhi
38796 in reply to 38792
Rick:


I really like subtracting 1 from $datestring. Does he append "0" when he wants to multiply by 10??




It works.  Perl will automatically treat $datestring as a number
since the string itself is composed of contiguous digits and the
literal 1 is being subtracted from it.

Re: Perly Dates

2005-07-20 14:56 • by mizhi
38797 in reply to 38794
Anonymous:
P.S.: Don't flame me, I don't know
anything about Perl, but the language looks so fucked up, that I just
had to make that comment ;-).




You, my friend, have never seen brainfuck.



http://www.muppetlabs.com/~breadbox/bf/

Re: Perly Dates

2005-07-20 15:02 • by loneprogrammer
Those DateTime modules are not builtin.  They have to be
downloaded separately, so Perl beginners don't know about them. 
That's still not a reason to resort to /bin/date!



# Print the time/date 24 hours ago

perl -e 'print scalar localtime(time()-60*60*24)'



Re: Perly Dates

2005-07-20 15:07 • by James Sneeringer
38799 in reply to 38795
Even if the guy is a Unix guy who writes Perl code like shell scripts (not uncommon), it's still a WTF because he doesn't bother to use the built-in facilities of /bin/date to automatically figure out what "yesterday" was:


$yesterday = `/bin/date -d yesterday +%Y%m%d`;

Re: Perly Dates

2005-07-20 15:09 • by mizhi
38800 in reply to 38799
Anonymous:
Even if the guy is a Unix guy who writes Perl
code like shell scripts (not uncommon), it's still a WTF because he
doesn't bother to use the built-in facilities of /bin/date to
automatically figure out what "yesterday" was:


$yesterday = `/bin/date -d yesterday +%Y%m%d`;




Yeah, I actually just remembered that the date utility can do all
that work for you.  I've used it before in shell scripts (not perl
though), php also has functions that work similar to date.


Re: Perly Dates

2005-07-20 15:12 • by loneprogrammer
38801 in reply to 38799
Anonymous:
$yesterday = `/bin/date -d yesterday +%Y%m%d`;


That will only work in the GNU version of /bin/date, so it won't run on many systems.

Stick to Perl, it is more portable.



Re: Perly Dates

2005-07-20 15:13 • by Ross Day
I've found that there is a pretty big difference between a Perl
"programmer" and a Perl "scripter".  This Perl Guy definitely
seems to fall in the latter category.



Perl, although its syntax is awkward at times, does have good
modularization, layering, and object-oriented capabilities.  Real
Perl programs are written this way.



Then you have the Perl scripter...who rights quick one file
scripts.  These are the crontab and other quick-fix kings. 
It's more about getting the little script to do exactly what it's
supposed to do on this exact system at this time than it is about
writing good portable modular reusable code.



I'm not saying this isn't a WTF (with how the logic is just wrong), but
that it's non-portable and haphazard doesn't really surprise me.

Re: Perly Dates

2005-07-20 15:14 • by Andrew Medico
There's an additional WTF of calling /bin/date multiple times and
expecting the date to be the same every time. Better not run this
function at 23:59:59!

Re: Perly Dates

2005-07-20 15:24 • by Maurits
38804 in reply to 38803
As previously noted...

The code will break on January 1 every year (will return a year ago
rather than a day ago), and on March 1 in leap years (will return
invalid date February 31.)  Otherwise it looks OK

Re: Perly Dates

2005-07-20 15:32 • by Rick
38805 in reply to 38796
Multiplying by 10 by appending a "0" also works...

my $x = 1234;

$x .= "0";

Its still stupid.



mizhi:
Rick:


I really like subtracting 1 from $datestring. Does he append "0" when he wants to multiply by 10??




It works.  Perl will automatically treat $datestring as a number
since the string itself is composed of contiguous digits and the
literal 1 is being subtracted from it.

Re: Perly Dates

2005-07-20 15:34 • by mizhi
38806 in reply to 38805
Rick:
Multiplying by 10 by appending a "0" also works...

my $x = 1234;

$x .= "0";

Its still stupid.




Sorry, I misread your original comment.  I thought you said "multiply by 0"



In anycase, you're talking about two different types of operations:
mathematic and string.  Not sure if it necessarily qualifies as
stupid.

Re: Perly Dates

2005-07-20 15:38 • by dubwai

This is nothing.  I was once conversing on a forum with someone who posted a date validation written entirely in regex.  Theoretically, it worked but it was uglier than sin.

Re: Perly Dates

2005-07-20 15:39 • by whojoedaddy
Is there good documentation on the api for perl? Closest thing I've tried to perl was cshell. I know those are probably extremely different. The problem I kept running into was lack of api documentation, everything was about bash.

Re: Perly Dates

2005-07-20 15:42 • by mizhi
38810 in reply to 38808
whojoedaddy:
Is there good documentation on the api for
perl? Closest thing I've tried to perl was cshell. I know those
are probably extremely different. The problem I kept running into was
lack of api documentation, everything was about bash.




man perl

man perldoc



http://perldoc.perl.org/perl.html

Re: Perly Dates

2005-07-20 15:50 • by -L
38811 in reply to 38797
mizhi:


You, my friend, have never seen brainfuck.



http://www.muppetlabs.com/~breadbox/bf/


Well, brainfuck doesn't use every single special character on the
keyboard as a special variable (I know for sure $| is legal in Perl,
wouldn't be surprised if it also had $/, $\, $-, and $*...)



TMTOWTDI is really a killer for maintainability. In a team of four
programmers I bet every single one has her own idioms for doing trivial
stuff. Perl has them all.



I am currently in the unfortunate position that I need to do a code
review for a 2 KSLOC Perl module I wrote three years ago as a summer
intern. Documentation? Nope. Using Perl in imaginative ways? Yup. I'll
see if I find anything worth a WTF entry in there...

Re: Perly Dates

2005-07-20 15:54 • by loneprogrammer
38813 in reply to 38807
dubwai:
This is nothing.  I was once conversing on a
forum with someone who posted a date validation written entirely in
regex.  Theoretically, it worked but it was uglier than
sin.


You sure it wasn't a email address validator?



That's the output from make_rfc822re(), a function that is hidden inside the module.



Re: Perly Dates

2005-07-20 16:10 • by Hank Miller
elsif ($it_is_the_first_of_the_year == 0) 
I find it "interesting" that the previous check was inconsistant:

if ($it_is_the_first_of_the_month)
Both
those checks should be eliminated though - the
$it_is_the_first_of_the_month case  is just a few more lines on
the month case above, and the ($it_is_the_first_of_the_year == 0) case
is an else to the first two ifs.  



Not to mention the bugs that everyone else has mentioned.









Re: Perly Dates

2005-07-20 16:11 • by rogthefrog

Even crap like the following is less retarded than that WTF


my ($sec,$min,$hour,$mday,$mon,$year, $wday,$yday,$isdst) = localtime time - 24 * 3600;
my $date = (1900 + $year) . "-" . $mon . "-" . $mday;
print $date;


(0-padding left as an exercise for the reader)

Re: Perly Dates

2005-07-20 16:23 • by UncleMidriff
38816 in reply to 38804
original code:


   .

   .

   .

   elsif ($datestring =~ /01$/) {




   $it_is_the_first_of_the_month = 1;




   $monthofyear = `/bin/date +%m`;




   chomp $monthofyear;




   $monthofyear = $monthofyear - 1;




   # Here are our thirty-day months




   if (($monthofyear == "04") || ($monthofyear == "06") ||




       ($monthofyear == "09") || ($monthofyear == "11")) {




      $day = 30;




   # Our single 28-day month




   } elsif ($monthofyear == "02") {




      $day = 28;




   # Fall through as a 31-day month




   } else {




      $day = 31;




   }

























Maurits:

As previously noted...

The code will break ... on March 1 in leap years (will return
invalid date February 31.)  Otherwise it looks OK




Perhaps I'm just missing something, but won't it return February 28 on
a leap year March 1, rather than February 29 like it's supposed to?

Re: Perly Dates

2005-07-20 16:51 • by foxyshadis
38818 in reply to 38811
Anonymous:
mizhi:


You, my friend, have never seen brainfuck.



http://www.muppetlabs.com/~breadbox/bf/


Well, brainfuck doesn't use every single special character on the
keyboard as a special variable (I know for sure $| is legal in Perl,
wouldn't be surprised if it also had $/, $\, $-, and $*...)



TMTOWTDI is really a killer for maintainability. In a team of four
programmers I bet every single one has her own idioms for doing trivial
stuff. Perl has them all.



I am currently in the unfortunate position that I need to do a code
review for a 2 KSLOC Perl module I wrote three years ago as a summer
intern. Documentation? Nope. Using Perl in imaginative ways? Yup. I'll
see if I find anything worth a WTF entry in there...


http://perldoc.perl.org/perlvar.html shows...

$|  $!  $_  $/  $`  $'  $+  $* 
$.  $,  $\  $"  $;  $#  $%  $= 
$-  $~  $^  $:  $?  $@  $$  $<

%!

@+  @-



And a lot more I'm not going to bother to list. Every one of them has a
more verbose version, but perl hackers prefer the meaningless line
noise version most of the time. (C hackers would probably use them if
available. Hmm... I wonder if #define would work here.)

Re: Perly Dates

2005-07-20 16:57 • by eown
38819 in reply to 38793
Anonymous:
but it's easier
just to:



$sec_in_day = 60*60*24;

$yesterday = time() - $sec_in_day;

my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($yesterday);

print "yesterday was $mday/" . ($mon+1) . "/" . ($year+1900) . "\n";






You are assuming that every day has 60*60*24 seconds. In a country with
daylight savings time this asumption will fail twice a year. See:



#!/usr/bin/perl

# On Sun Oct 30 23:23:20 CEST 2005:
$today = 1130711000;

$sec_in_day = 60*60*24;

$yesterday = $today - $sec_in_day;


($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($today);
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($yesterday);


print "today is $mday/" . ($mon+1) . "/" . ($year+1900) . "\n";


print "yesterday was $mday/" . ($mon+1) . "/" . ($year+1900) . "\n";



which in my time zone outputs:




today is 30/10/2005

yesterday was 30/10/2005



ymmv, but in every time zone with daylight savings time you'll find something like this.







Re: Perly Dates

2005-07-20 17:14 • by Maurits
38820 in reply to 38819


$datestring  = `/bin/date +%Y%m%d`;

($year, $month, $day) = $datestring =~ /(\d\d\d\d)(\d\d)(\d\d)/;





$daysinfebruary =

    $year % 400 == 0 ? 29 : # 1600, 2000, 2400 ...

    $year % 100 == 0 ? 28 : # 1800, 1900, 2100 ...

    $year % 4 == 0 ? 29 : # 2004, 2008, 2012 ...

    28; # 2005, 2006, 2007, ...



@daysinmonth = (undef, 31, $daysinfebruary, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);



if ($month eq "01" and $day eq "01")

{    $ftpdate = ($year - 1) . $month . $day;

} elsif ($day eq "01")

{    $ftpdate = $year . ($month - 1) . $daysinmonth[$month - 1];

} else

{    $ftpdate = $year . $month . ($day - 1);

}



Re: Perly Dates

2005-07-20 17:15 • by Maurits
38821 in reply to 38819
Oops should be

if ($month eq "01" and $day eq "01")

{    $ftpdate = ($year - 1) . "1231";

} ...

Re: Perly Dates

2005-07-20 17:30 • by Maurits
38824 in reply to 38821
Double oops forgot zero-padding



$datestring  = `/bin/date +%Y%m%d`;



($year, $month, $day) = $datestring =~ /(\d\d\d\d)(\d\d)(\d\d)/;



$daysinfebruary =

    $year % 400 == 0 ? 29 : # 1600, 2000, 2400 ...

    $year % 100 == 0 ? 28 : # 1800, 1900, 2100 ...

    $year % 4 == 0 ? 29 : # 2004, 2008, 2012 ...

    28; # 2005, 2006, 2007, ...



@daysinmonth = (undef, 31, $daysinfebruary, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);



if ($month eq "01" and $day eq "01")

{    $ftpdate = ($year - 1) . "1231";

} elsif ($day eq "01")

{    $ftpdate = $year . zeropad($month - 1) . $daysinmonth[$month - 1];

} else

{    $ftpdate = $year . $month . zeropad($day - 1);

}



sub zeropad($)

{       my $num = shift;

        return $num < 10 ? "0$num" : $num;

}



Re: Perly Dates

2005-07-20 17:33 • by loneprogrammer
38825 in reply to 38819
eown:
You are assuming that every day has 60*60*24 seconds. In a country with
daylight savings time this asumption will fail twice a year.



eown:


which in my time zone outputs:




today is 30/10/2005

yesterday was 30/10/2005



What does it output if you write it correctly?  The reason it
prints the same thing twice is that you clobbered all the variables
with the result of localtime($yesterday).



#  Here's my code:

$today = 1130711000;

$yesterday = $today - 60*60*24;



print scalar localtime($today), "\n";

print scalar localtime($yesterday), "\n";



# Results:

Sun Oct 30 17:23:20 2005

Sat Oct 29 18:23:20 2005



Re: Perly Dates

2005-07-20 17:46 • by loneprogrammer
38826 in reply to 38825
loneprogrammer:
What does it output if you write it correctly?


I see where you were going with that now . . .



# Sun Oct 30 23:23:00 EST 2005

$today = 1130732580;

$yesterday = $today - 60*60*24;



print scalar localtime($today), "\n";

print scalar localtime($yesterday), "\n";



# Result:

Sun Oct 30 23:23:00 2005

Sun Oct 30 00:23:00 2005



This happens to be a 25 hour day, because the clock says 1AM for two hours.



Re: Perly Dates

2005-07-20 17:50 • by terry
jesus.



i would eat someone if they put that code out. like a snake. face first.

Re: Perly Dates

2005-07-20 18:04 • by Richard
38829 in reply to 38787
Nobody *reads* perl, they only *write* it.

Re: Perly Dates

2005-07-20 18:07 • by Chris Brien
May I be the first to say...

$ftpdate = `/bin/date -d yesterday +%Y%m%d`

Thank you and goodnight.

Re: Perly Dates

2005-07-20 18:15 • by Aristotle
38831 in reply to 38794
Anonymous:
I don't know anything about Perl, but the language looks so fucked up, that I just had to make that comment ;-).

Real programmers can write FORTRAN in any language...



I know quite a lot about Perl and I can assure you Perl doesn't intrinsically look fucked up.



That said, the fact that this guy is shelling out to /bin/date
is not a serious WTF. The people writing replies and trying to
implement date math in 5 lines are much worse. The fact that he is
groping around with a regex is the primary WTF, that he is shelling out
multiple times is the secondary. His date math bugs are just cherry
topping.



Date math is hard. Really, really, really ridiculously hard. That's
why the dudes who set out to write the DateTime modules started that
project in the first place; so noone would have to implement the math
again and get it wrong again.



The funny thing is, this coder could have had /bin/date do all this for him:



my $ftpdate = `date -d yesterday +%Y%m%d`;

Re: Perly Dates

2005-07-20 18:18 • by Aristotle
38832 in reply to 38830
Damn you Chris, beat me to the punch by a few minutes.

Re: Perly Dates

2005-07-20 18:20 • by loneprogrammer
38833 in reply to 38832
Anonymous:
Damn you Chris, beat me to the punch by a few minutes.


First, Chris wasn't the first to mention it.



Second, it won't run on most versions of Unix.  Just because it works on Linux doesn't mean it's Unix.

Re: Perly Dates

2005-07-20 18:21 • by toffer
38834 in reply to 38820

Whatever happened to laziness?


use Date::Calc qw(Add_Delta_Days Today);

$ftpdate = sprintf("%04d-%02d-%02d",
           Add_Delta_Days(Today(), -1));
print $ftpdate, "\n";


You may have to install Date::Calc, of course. I generally find it's worth it. :)





Re: Perly Dates

2005-07-20 18:40 • by Maurits
38839 in reply to 38830
Anonymous:
May I be the first to say...

$ftpdate = `/bin/date -d yesterday +%Y%m%d`

Thank you and goodnight.




Actually that has a trailing newline.  You could do

$ftpdate = `/bin/date -d yesterday +%Y%m%d`

chomp($ftpdate);



or if you want to keep it a one-liner:

$ftpdate = (split /\n/, `/bin/date -d yesterday +%Y%m%d`)[0];

Re: Perly Dates

2005-07-20 18:42 • by Alan
38840 in reply to 38791
I am a perl guy and I can say that getting yesterday's date is not a
complicated matter and doesn't even need any "built-in" modules. A fair
method involves some hacking with the timelocal() and localtime()
built-ins, maybe slightly tricky but not very complex; an expert
doesn't think twice to pull in DateTime or Date::Calc and have it all
done in about 2 lines of code.

Re: Perly Dates

2005-07-20 18:50 • by foxyshadis
38841 in reply to 38839
Once you bring dst into the equation you might as well throw out
localtime() alltogether and go straight to gmt. Don't forget leap
seconds!

Re: Perly Dates

2005-07-20 18:55 • by Aristotle Pagaltzis
38842 in reply to 38833
loneprogrammer:
First, Chris wasn't the first to mention it.



Second, it won't run on most versions of Unix.  Just because it works on Linux doesn't mean it's Unix.

It's not Unix, but I am no fan of using the lowest common denominator either. That gets you things like AWT. Or database apps that use only the widely supported subset of SQL92. Portability has a price; this does not seem like a case where paying the price would have been worth it. Things would be different if this were supposed to go onto the CPAN or such.



Anonymous:
use Date::Calc qw(Add_Delta_Days Today);


$ftpdate = sprintf("%04d-%02d-%02d",
Add_Delta_Days(Today(), -1));
print $ftpdate, "\n";

use DateTime;


$ftpdate = DateTime->now->subtract( days => 1 )->ymd( '' );


;)



Alan:
A fair method involves some hacking with the timelocal() and localtime() built-ins, maybe slightly tricky but not very complex

Actually, it is. You can write code that works almost all of the time fairly easily, but there are way way more edge cases than you care to think about. Don't be fooled by the seeming simplicity, like so many others.

Re: Perly Dates

2005-07-20 19:01 • by Sean Connery
38843 in reply to 38830
Anonymous:
May I be the first to say...

$ftpdate = `/bin/date -d yesterday +%Y%m%d`

Thank you and goodnight.




Nope, second.

Re: Perly Dates

2005-07-20 19:21 • by loneprogrammer
38846 in reply to 38839
Maurits:
You could do

$ftpdate = `/bin/date -d yesterday +%Y%m%d`

chomp($ftpdate);



chomp works on assignments, too:



chomp($ftpdate = `/bin/date`);



Although I think it's more readable to use two lines for this.

Re: Perly Dates

2005-07-20 19:28 • by Rustam
38848 in reply to 38795
Well, I'm sure it would run in Cygwin on Windows. So it's portable to the extent of whether you're willing to install Cygwin, to "make" it portable.



And, I suppose you could argue it's not portable on a couple days a year no matter what.

Re: Perly Dates

2005-07-20 19:29 • by mizhi
38849 in reply to 38833
loneprogrammer:
Anonymous:
Damn you Chris, beat me to the punch by a few minutes.


First, Chris wasn't the first to mention it.



Second, it won't run on most versions of Unix.  Just because it works on Linux doesn't mean it's Unix.




Lest we not forget that supposedly, this came out of a shop that
develops on a number of different platforms... portability much?

« PrevPage 1 | Page 2 | Page 3Next »

Add Comment