• Yo mamma! (unregistered)

    Great ending, the best thing to do with code of this quality.

  • Anonymous (unregistered)

    Good thing that I am good enough to use Java, Spring and Joda-Time.

  • akozakie (unregistered)

    To hell with Feb 27 - at least it works every 4 years and the date at least looks correct, even if there's no such day. Simple omission.

    But it also fails, even more spectacularly, on Dec 30. Every single year. Producing month 13. And it's not an omission - there is a special case for this day, but it's never reached.

    Wow. It's not even wrong (and not even used)... Beautiful WTF.

  • Zappes (unregistered)

    TRWTF is that "ubermorgen" was used instead of "uebermorgen" or "übermorgen".

  • Miriam (unregistered)

    That's ... unique. And the December issue is the icing on the cake!

  • foo AKA fooo (unregistered) in reply to Zappes
    Zappes:
    TRWTF is that "ubermorgen" was used instead of "uebermorgen" or "übermorgen".
    No, TRWTF is the name. Seriously, Stephaan? Not Hanzo? Oh, I understand Eriek's method of anonymization, just add a random vowel to any name ...
  • RFox (unregistered)

    Ho hum... wrong code that's not being used... maybe that's why it's not being used?

  • Miriam (unregistered) in reply to foo AKA fooo
    foo AKA fooo:
    Zappes:
    TRWTF is that "ubermorgen" was used instead of "uebermorgen" or "übermorgen".
    No, TRWTF is the name. Seriously, Stephaan? Not Hanzo? Oh, I understand Eriek's method of anonymization, just add a random vowel to any name ...
    Yeah, it should be Schtepfahn, not Stephaan.
  • I actually liked this. (unregistered)

    So, hooray.

  • Pista (unregistered)

    +1 for thinking about writing ubermorgen(date) as morgen(morgen(date)). I wonder how many programmers would come up with this idea if presented with the task of writing such functions.

    Captcha: ideo. This thing is reading my mind :)

  • Mr Tomato Bread (unregistered)

    I hate to think about what happens at midnight. Worst case it skips a complete month.

  • Smug Unix User (unregistered)

    The true WTF is php amirite? Ruthless refactoring is next to godliness.

  • HandsomeStan (unregistered) in reply to Smug Unix User
    Smug Unix User:
    The true WTF is php amirite?

    Nope

  • (cs)
    OP:
    Something about the code struck him as ... wrong.
    Code that touches dates or times always needs to be scrutinized with an extreme scrute. It will usually be buggy. If it doesn't use library functions it will almost always be buggy.

    Dates and times are hard, even for competent coders.

  • (cs)

    if the only thing to complain about in an erik story is the name, i think he did well

  • BA (unregistered)

    Coincidentally, Übermorgen is the ETA for the next date calculation WTF

  • Stephaan (unregistered) in reply to akozakie
    akozakie:

    But it also fails, even more spectacularly, on Dec 30. Every single year. Producing month 13. And it's not an omission - there is a special case for this day, but it's never reached.

    Oooh, I missed that! When I saw the code I knew there must be something wrong with it, only to stop perusing at the hilarious handling of february.

    As opposed to what was written in the article, I'm certain that this code was never tested. Not by me, and not by the perpetrator either.

    legi, ridi, aboli (I came, laughed and effaced)

  • Andy Canfield (unregistered)

    One of the rarecases where the best procedure is to use a library function to turn the date into a count (days,hours, seconds, whatever), add 24 hours, and then another library function to convert back. YYYY/MM/DD are wonderful for reading and sorting and selecting, but terrible for arithmetic.

  • Caffeine (unregistered)

    Does it not also fall on the 29th of February, returning the first of February for morgan?

  • Chaarmann (unregistered) in reply to Andy Canfield

    add 24 hours??? But sometimes you must add 25 hours (daylight saving) or 24 hours plus 1 second (leap second) to the current time to get to the next day instead of still being in the current day. Sometimes if you add 24 hours instead of 23 hours (daylight saving), you do not get to tomorrow, but the day after tomorrow (Übermorgen)

    conclusion: never add 24 hours, let the library do that for you!

  • jum (unregistered)

    Überfail. That is all.

  • Chaarmann (unregistered)

    "It worked for any date given on a leap year, but ..."

    That's not true, the day after tomorrow (übermorgen) is calculated wrong!

    29 november:manydays=30, currentday=29

    no elseif matches therefore going into the else-case --> morgen=30 ubermorgen=31 (!!!)

  • The Fury (unregistered) in reply to Andy Canfield
    Andy Canfield:
    One of the rarecases where the best procedure is to use a library function to turn the date into a count (days,hours, seconds, whatever), add 24 hours, and then another library function to convert back. YYYY/MM/DD are wonderful for reading and sorting and selecting, but terrible for arithmetic.

    That's not going to work. There aren't always 24 hours in a day.

  • (cs)

    I know that PHP gets bashed all the time (especially over Java, which we know has no known vulnerabilities to date).

    It's not the language that's the problem, but the coder. PHP has so many bad coders because it's easy to learn. It's a good entry-level language, and you will find quite a bit of bad code in entry-level languages.

    Taking this post as an example, the right way of doing it (Yes, I google'd it because I didn't want to throw this together):

    $datetime = new DateTime('tomorrow');
    echo $datetime->format('Y-m-d H:i:s');

    Well-written code in PHP can function as well as well written code in other languages. Am I a PHP fan? Yes. I can throw together a full-fledged ready-for-production site with a back-end for handling the workload in about a day or so. A simple SOAP/REST call in a few minutes. Is it better than Java/Perl/Python? Nope. Does it use more resources? Maybe. Depends on if it's CLI or running on a web head.

    Sorry. Had to vent.

  • Doctor_of_Ineptitude (unregistered) in reply to flabdablet
    flabdablet:
    OP:
    Something about the code struck him as ... wrong.
    Code that touches dates or times always needs to be scrutinized with an extreme scrute. It will usually be buggy. If it doesn't use library functions it will almost always be buggy.

    Dates and times are hard, even for competent coders.

    I know. In my first year of college, I thought of myself as a competent coder (I was already fluent in C, C++, actually knew pointers and a decent number of algorithms, etc). For our third assignment, the prof gave a simple task: write a program to to get number of days between two given dates (no libraries allowed). After three days of finding bugs in my flawless program, I understood arithmetic with dates is hard. It also made me appreciate the various libraries that provide methods for accepting dates as input, and SQL prepared statements (binding data). Also I learned a very important thing with that: some things are best as objects rather than a collection of associated data. A date is a lot more than just three numbers joined together.

  • Tux "Tuxedo" Penguin (unregistered) in reply to The Fury
    The Fury:
    Andy Canfield:
    One of the rarecases where the best procedure is to use a library function to turn the date into a count (days,hours, seconds, whatever), add 24 hours, and then another library function to convert back. YYYY/MM/DD are wonderful for reading and sorting and selecting, but terrible for arithmetic.

    That's not going to work. There aren't always 24 hours in a day.

    Then how comes every clock in existence has only 24 spots for hours (12 in analog and this weird american hor system)?

    Even on DST there are still 24 hours, they're just a bit shifted. (by 1h).

  • Matt (unregistered) in reply to Tux "Tuxedo" Penguin

    No, on the first and last day of DST, there are 23 and 25 hour days. If you try adding 24 hours at the wrong point of the day, it's very possible for you to skip a day or completely fail to go to the next day.

  • (cs)

    All developers think they are smarter than most people, so they think of smart ways to solve problems that do not really exist.

  • Zapp Brannigan (unregistered)

    It's ok to distort time and play with the number of hours in the day, but do NOT change the quantum mass of the electron!

  • (cs)

    Novice programmers write X lines of code a day. Good programmers write X * 4 lines of code a day. Excellent programmers remove X lines of code a day.

    The best programmers take garbage like this, and either remove it completely, or rewrite it using elegant code that takes fewer lines, is less error prone, is easier to understand ...

  • ¯\(°_o)/¯ I DUNNO LOL (unregistered)

    Back in '99 I once "fixed" a leap year calculation for the special case (in my lifetime at least) of 2000 being a leap year. I think the old code had the "century rule" but not the "400 year rule", and thus was wrong for 2000. Never mind that the code didn't exist in 1900 and would likely be long gone by 2100, so neither rule was needed.

    It was in assembly language, and I got a branch condition backward. This broke the calculation for every leap year, or maybe just for 2004 and later. Fortunately it was discovered before an actual leap year happened. あさっては難しいですね。

  • rob (unregistered)

    looks like php has a function for getting the number of days in a supplied month and year. Might have been useful.

    I am not a php programmer, so the following syntax is off.

    $numdays = cal_days_in_month(CAL_GREGORIAN, $today_month, $today_year)

    -- -- logic for tomorrow then becomes something like -- when the current day plus one goes over the number of days in -- the given month, set the day to 1, increment the month, when the -- month > 12, set the month to 1, and increment the year -- otherwise just add 1 to the current day, and set the return -- values for month and year to match the supplied values

    if ( ($today + 1) <= (cal_days_in_month, CAL_GREGORIAN, ...) { $tomorrow_day := $today + 1; $tomorrow_month := $today_month; } elsif { $tomorrow_day := 1; if (($today_month + 1) <= 12) { $tomorrow_month := $today_month; $tomorrow_year := $today_year; } elsif { {$tomorrow_month = 1; $tomorrow_year = $today_year + 1 } }

  • (cs)

    The .net date object is great -- set the date object to the desired date; then you add one day to it. Presto, the date object represents "tomorrow" without any of the complicated leap year calculations, etc.

  • akozakie (unregistered) in reply to RFox
    RFox:
    Ho hum... wrong code that's not being used... maybe that's why it's not being used?

    Maybe that's why it's wrong.

    Sure, getting it right would be quite difficult and the original author might spend days on this and still not realize, that there must be a better way to do it.

    But this level of bugginess is reserved for unused code. A bit of testing or a year (at worst) of untested production use and at least some of these bugs would be spotted.

    Unused code is an endless mine of WTFery.

  • KBKarma (unregistered) in reply to DrPepper

    I just was going to say that. A great language. Python's unfortunately not as neat, though, according to this:

    datetime.date.today() + datetime.timedelta(days=1)
  • Foonar (unregistered) in reply to Stephaan

    I read, I laughed, I effaced!

  • jugis (unregistered) in reply to Doctor_of_Ineptitude
    Doctor_of_Ineptitude:
    For our third assignment, the prof gave a simple task: write a program to to get number of days between two given dates (no libraries allowed). After three days of finding bugs in my flawless program, I understood arithmetic with dates is hard.
    Not especially:
    static int
    to_jdn(int year, int month, int day)
    {
        // http://www.tondering.dk/claus/cal/julperiod.php#formula
        if (year < 0)
            ++year;
        int a = (14 - month) / 12;
        int y = year + 4800 - a;
        int m = month + 12 * a - 3;
        return day + (153 * m + 2) / 5 + 365 * y + y / 4 - y / 100 + y / 400 - 32045;
    }
    
    int
    date_diff(int year1, int month1, int day1, int year2, int month2, int day2)
    {
        return to_jdn(year1, month1, day1) - to_jdn(year2, month2, day2);
    }
    

    (Please ignore any silly transcription errors.)

  • (cs) in reply to Pista
    Pista:
    +1 for thinking about writing ubermorgen(date) as morgen(morgen(date)). I wonder how many programmers would come up with this idea if presented with the task of writing such functions.

    Captcha: ideo. This thing is reading my mind :)

    Don't forget next week.

    morgen(morgen(morgen(morgen(morgen(morgen(morgen(date)))))));
    
  • (cs) in reply to KBKarma
    KBKarma:
    I just was going to say that. A great language. Python's unfortunately not as neat, though, according to this:
    datetime.date.today() + datetime.timedelta(days=1)

    One of the few things that I do not like about Python.

  • C (unregistered)

    And yet, there are more! :D

    Here's my take on the complete list of dates of failure:

    • 30 december : $ubermorgenmonth = 13. . both 27 and 28 february on non-leap years : $ubermorgenmonth = 2. . not just November, but all months with 30 days: 29 April, 29 June, 29 September, 29 November : $ubermorgen = 31.
    • 29 february on leap years : $morgenmonth = 2 (so next day gets to be February 1st!) -- therefore it's not perfect for leap years either. :p
  • (cs) in reply to flabdablet
    flabdablet:
    OP:
    Something about the code struck him as ... wrong.
    Code that touches dates or times always needs to be scrutinized with an extreme scrute. It will usually be buggy. If it doesn't use library functions it will almost always be buggy.
    Not "almost" always -- It's *always* buggy, inherently. For stuff like this, the failure to use the appropriate library functions should be considered a bug in its own right, even if they somehow manage to get all the logic right.

    To paraphrase Harvey's Second Universal Answer To Computer Science Questions: "If a question begins 'Why not just...', the answer is almost always 'Because that would violate the abstraction.'"

  • (cs)

    Of course, strtotime() is so much simpler...

    ...but if you had to do it the hard way, why not just loop twice with a simple 1-day increment?

    ``` // FORMAT DATE // detect this day and this month (without 0) $today = date("j") ; $thismonth = date("n") ; $manyday = date("t") ;
    $ubermorgenmonth = $thismonth;
    $ubermorgen      = $today;
    for ($i = 0; $i < 2; $i++)
    {
       $morgenmonth = $ubermorgenmonth;
       $morgen      = $ubermorgen;
    
       if (++$ubermorgen > $manyday)
       {
           $ubermorgen  = 1;
           if (++$ubermorgenmonth > 12) $ubermorgenmonth = 1;
       }
    }
    

    I guess it's just a WTF...all the way around.

  • Guestimate (unregistered) in reply to KBKarma
    KBKarma:
    datetime.date.today() + datetime.timedelta(days=1)
    As I assume that that "timedelta" has no awareness of the current day, I guess that it will return an unexpected result for any day just before a dayligh-savings switching -- where the next day will be either one hour long or short.

    Granted, in the current case it will probably only cause a problem when summertime starts (next day has less than 24 hours), and its near to midnight. But still.

  • QJo (unregistered) in reply to Javelin
    Javelin:
    flabdablet:
    OP:
    Something about the code struck him as ... wrong.
    Code that touches dates or times always needs to be scrutinized with an extreme scrute. It will usually be buggy. If it doesn't use library functions it will almost always be buggy.
    Not "almost" always -- It's *always* buggy, inherently. For stuff like this, the failure to use the appropriate library functions should be considered a bug in its own right, even if they somehow manage to get all the logic right.

    To paraphrase Harvey's Second Universal Answer To Computer Science Questions: "If a question begins 'Why not just...', the answer is almost always 'Because that would violate the abstraction.'"

    Do you have a link to a resource to this (and his first, and any other such) Universal Answers?

  • gnasher729 (unregistered) in reply to Guestimate
    Guestimate:
    KBKarma:
    datetime.date.today() + datetime.timedelta(days=1)
    As I assume that that "timedelta" has no awareness of the current day, I guess that it will return an unexpected result for any day just before a dayligh-savings switching -- where the next day will be either one hour long or short.

    Granted, in the current case it will probably only cause a problem when summertime starts (next day has less than 24 hours), and its near to midnight. But still.

    That kind of method works perfectly fine, if timedelta returns the right kind of object. Obviously it shouldn't convert "1 day" into "86400 seconds" - a timedelta of one day should represent just that, one day, and the operator+ should do its best to add a delta to a date, with all the needed cleverness built into that operator.

    So date + timedelta (seconds=86400) should always be 86,400 seconds later which might result in a different hour on two days in the year. date + timedelta (days =1) should return the next day, at the same hour, with well-documented and reasonable rules in the few cases where this is not possible, for example if the same hour doesn't exist on the next day.

    What's a bit more difficult is what today () should be. now () makes sense. But today ()? There are usually 86400 seconds in a day, so should today () be something that only can represent days, or should it be an interval of usually 24 hours, or noon or midnight on the current day?

  • gnasher729 (unregistered)

    Date calculations are not trivial, but this is just a case of a muddled brain.

    To calculate tomorrow: Copy today. Increase day be 1. If day > number of days in month, set day = 1, increase month by 1, and if month > 12 set month = 1 and increase year by 1.

    To calculate the day after tomorrow: Use the same method, but starting with tomorrow's date.

    No need for distinguishing between nine! different cases as this code does. When you encounter that kind of code, where someone clearly didn't have a clue how to attack a simple problem, you don't even need to look for bugs. You just know that somewhere within these nine different cases, some will be handled wrong.

  • v (unregistered)

    if in the end the calculated day/month are passed to mktime, all is good with 27th of february, as it handles overflows correctly. and all of those other hoops are unneeded. if it is instead concatenated to a string, that's another matter.

    on the other hand, the cases for december really worry me, because there is no year variables incremented anywhere.

  • (cs) in reply to QJo
    QJo:
    Javelin:
    flabdablet:
    OP:
    Something about the code struck him as ... wrong.
    Code that touches dates or times always needs to be scrutinized with an extreme scrute. It will usually be buggy. If it doesn't use library functions it will almost always be buggy.
    Not "almost" always -- It's *always* buggy, inherently. For stuff like this, the failure to use the appropriate library functions should be considered a bug in its own right, even if they somehow manage to get all the logic right.

    To paraphrase Harvey's Second Universal Answer To Computer Science Questions: "If a question begins 'Why not just...', the answer is almost always 'Because that would violate the abstraction.'"

    Do you have a link to a resource to this (and his first, and any other such) Universal Answers?

    No link. He find it easy to make up answers than supply link and have my answer questioned.

  • O RLY? (unregistered) in reply to The Fury
    The Fury:
    That's not going to work. There aren't always 24 hours in a day.
    There are always 24 hours in a UTC day. The solution is to convert from local time (rounded off to the nearest day) to UTC, add the 24h, then convert back. If you're worried about leap seconds (which almost no one cares about), add 24h+1s.
  • quibus (unregistered) in reply to O RLY?
    O RLY?:
    There are always 24 hours in a UTC day. The solution is to convert from local time (rounded off to the nearest day) to UTC, add the 24h, then convert back. If you're worried about leap seconds (which almost no one cares about), add 24h+1s.
    It's the 25th of October, and I want to find tomorrow's date. I convert midnight on the 25th from BST to UTC, getting 23:00 on the 24th. I add 24 hours, getting 23:00 on the 25th. I convert that back to local time, and since BST has now ended, I still get 23:00 on the 25th. Therefore, the day after the 25th of October is the 25th of October. QED?

Leave a comment on “Day After Übermorgen”

Log In or post as a guest

Replying to comment #:

« Return to Article