DateTime is hard



  • Nothing spectacular, but I need to get these off my chest.

    A former co-worker apparently did not trust .NET's implementation of ToString for DateTime:

    public static string ConvertDateToDayName( DateTime Date )
    {
                switch( Date.DayOfWeek )
                {
                            case DayOfWeek.Sunday: return "Sun";
                            case DayOfWeek.Monday: return "Mon";
                            case DayOfWeek.Tuesday: return "Tue";
                            case DayOfWeek.Wednesday: return "Wed";
                            case DayOfWeek.Thursday: return "Thu";
                            case DayOfWeek.Friday: return "Fri";
                            //Saturday
                            default: return "Sat";
                }
    }


    He also apparently favored casting DateTime to String and back again multiple times before using the string in a non-parameterized query. It was something like the following; I don't want to find the actual code or I will hit something:


    public void SomeFunction(string dateStr) {
         DateTime theDate = DateTime.Parse(dateStr);
         string queryDate = theDate.ToString("MM/dd/yyyy");
         string sQuery = "SELECT * FROM table WHERE theDate = '" + dateStr + "'";
         doQuery(sQuery);
    }



  • So is ADO.NET, apparently...



  • @Liquid Egg Product said:

    Nothing spectacular, but I need to get these off my chest.

    A former co-worker apparently did not trust .NET's implementation of ToString for DateTime:

    public static string ConvertDateToDayName( DateTime Date )
    {
                switch( Date.DayOfWeek )
                {
                            case DayOfWeek.Sunday: return "Sun";
                            case DayOfWeek.Monday: return "Mon";
                            case DayOfWeek.Tuesday: return "Tue";
                            case DayOfWeek.Wednesday: return "Wed";
                            case DayOfWeek.Thursday: return "Thu";
                            case DayOfWeek.Friday: return "Fri";
                            //Saturday
                            default: return "Sat";
                }
    }

    This is future-proof because this will handle any future DayOfWeek that scientists or accountants could create. Of course, if there is really a new DayOfWeek this will return the wrong value (unless the name of the new day starts with "Sat", in which case it won't be wrong but merely confusing). The most important thing is that the method will not fail and unless someone updates the test cases at the moment of the new DayOfWeek creation, this method will pass with flying colors. A lot can be accomplished with a clever usage of a switch.

    @Liquid Egg Product said:


    He also apparently favored casting DateTime to String and back again multiple times before using the string in a non-parameterized query. It was something like the following; I don't want to find the actual code or I will hit something:


    public void SomeFunction(string dateStr) {
         DateTime theDate = DateTime.Parse(dateStr);
         string queryDate = theDate.ToString("MM/dd/yyyy");
         string sQuery = "SELECT * FROM table WHERE theDate = '" + dateStr + "'";
         doQuery(sQuery);
    }

    Besides the obvious sql injection issue, this kind of code will cause endless (and seemingly random) nightmares in non-US locales. As an example, if this was to run on a server configured to use French locale, it would return the wrong value when the days is lower than 13th (because French format is DD/MM/YYYY), otherwise it would crash or return the right value, depending on how forgiving is the database engine date library.

     

     


  • Considered Harmful

    @thistooshallpass said:

    Besides the obvious sql injection issue, this kind of code will cause endless (and seemingly random) nightmares in non-US locales. As an example, if this was to run on a server configured to use French locale, it would return the wrong value when the days is lower than 13th (because French format is DD/MM/YYYY), otherwise it would crash or return the right value, depending on how forgiving is the database engine date library.

    I'm not seriously defending this (l2parameters n00b), but SQL injection isn't really possible because ParseDate will throw an exception on anything but a valid date string.

    I'd also like to note that queryDate is MM/dd/yyyy, but dateStr is passed raw into the query, so it remains in whatever format it came into the function; queryDate is a dead store, and since ToString has no side-effects it may be optimized away entirely.



  • This should be fun:

    [code]SomeFunction("2008-11-01T19:35:00.0000000-07:00");[/code]



  •  It may not have an SQL injection bug, but it's dodging every possible way of making the SQL compare dates. It's going to be a lot slower than it needs to be because all the dates in the table will have to be converted to strings for the comparison.



  • @Liquid Egg Product said:


    public void SomeFunction(string dateStr) {
         DateTime theDate = DateTime.Parse(dateStr);
         string queryDate = theDate.ToString("MM/dd/yyyy");
         string sQuery = "SELECT * FROM table WHERE theDate = '" + dateStr + "'";
         doQuery(sQuery);
    }

    I can almost defend this function. If the dateStr is a string, that means the date could come in as any formatted date (or garbage), and parsing that string into a specific format a) should throw an exception if the string is not a valid date, and 2) force the date string into the format that is recognized by the database column. Granted, I understand that you wrote this as an example, and this might not be the case with your co-workers actual code.



  • @thistooshallpass said:

    This is future-proof because this will handle any future DayOfWeek that scientists or accountants could create. Of course, if there is really a new DayOfWeek this will return the wrong value (unless the name of the new day starts with "Sat", in which case it won't be wrong but merely confusing). The most important thing is that the method will not fail and unless someone updates the test cases at the moment of the new DayOfWeek creation, this method will pass with flying colors. A lot can be accomplished with a clever usage of a switch.

    Nice -- because the Romans switched from an 8-day cycle to a 7 day cycle, and other civilizations had 10 day cycles and gravitated towards a 7 day cycle.  It's possible (but not probable) that the current 7 day week could be replaced with a longer (or shorter) period.

    And there have been proposals for multiple - differeng number of day weeks in each month in order to correlate with the lunar cycle.


  • Garbage Person

    @Medezark said:

     

    And there have been proposals for multiple - differeng number of day weeks in each month in order to correlate with the lunar cycle.

    Because the lunar cycle matters in any way to modern civilization. Seriously - if you're going to go realigning our calendar, do it based on something that has a modern importance, like the sun.


  • @dohpaz42 said:

    @Liquid Egg Product said:


    public void SomeFunction(string dateStr) {
         DateTime theDate = DateTime.Parse(dateStr);
         string queryDate = theDate.ToString("MM/dd/yyyy");
         string sQuery = "SELECT * FROM table WHERE theDate = '" + dateStr + "'";
         doQuery(sQuery);
    }

    I can almost defend this function. If the dateStr is a string, that means the date could come in as any formatted date (or garbage), and parsing that string into a specific format a) should throw an exception if the string is not a valid date, and 2) force the date string into the format that is recognized by the database column. Granted, I understand that you wrote this as an example, and this might not be the case with your co-workers actual code.
    See my earlier post.  DateTime.Parse uses different rules than the database server, not to mention the possiblility of a different locale.  Notice that the original string is jammed into the query, not the reformatted string.


  • @Weng said:

    @Medezark said:

     

    And there have been proposals for multiple - differeng number of day weeks in each month in order to correlate with the lunar cycle.

    Because the lunar cycle matters in any way to modern civilization. Seriously - if you're going to go realigning our calendar, do it based on something that has a modern importance, like corporations

    FTFY

    I can not wait to see the day when our calendar is decided in a bidding war by Big Corp Inc.



  • @serguey123 said:

    @Weng said:

    @Medezark said:

     

    And there have been proposals for multiple - differeng number of day weeks in each month in order to correlate with the lunar cycle.

    Because the lunar cycle matters in any way to modern civilization. Seriously - if you're going to go realigning our calendar, do it based on something that has a modern importance, like corporations

    FTFY

    I can not wait to see the day when our calendar is decided in a bidding war by Big Corp Inc.

    The Year of the Depend Adult Undergarment?


  • @joe.edwards said:

    @thistooshallpass said:
    Besides the obvious sql injection issue, this kind of code will cause endless (and seemingly random) nightmares in non-US locales. As an example, if this was to run on a server configured to use French locale, it would return the wrong value when the days is lower than 13th (because French format is DD/MM/YYYY), otherwise it would crash or return the right value, depending on how forgiving is the database engine date library.

    I'm not seriously defending this (l2parameters n00b), but SQL injection isn't really possible because ParseDate will throw an exception on anything but a valid date string.

    I'd also like to note that queryDate is MM/dd/yyyy, but dateStr is passed raw into the query, so it remains in whatever format it came into the function; queryDate is a dead store, and since ToString has no side-effects it may be optimized away entirely.

    Using dateStr will open the door to sql injection:

    SomeFunction("2000-01-01'; OR 1=1") 
    

    But if the query was built with queryDate then the locale problems would occur. So it's kind of a win-win scenario, which makes this mehod awesome.



  • @serguey123 said:

    I can not wait to see the day when our calendar is decided in a bidding war by Big Corp Inc.

     

    What a gruesome thought.



  • @__moz said:

    @serguey123 said:

    I can not wait to see the day when our calendar is decided in a bidding war by Big Corp Inc.

     

    What a gruesome thought.



    Fortunately, that's such a stupid idea it could never happen.  Why, it'd be as if some huge faceless entity suddenly decided to make all the television tuners obsolete (even if they gave out rebates on a gizmo that would "adapt" them that would work on all but a healthy handful of sets).  Or if some government agency suddenly decided that the lightbulbs we've been using for a century and a half were now evil, and forbid the use of them in favor of a new type that wouldn't work in enclosed fixtures, fixtures controlled by dimmers, fixtures in cold environments, fixtures subject to vibration, etc, and which incidentally contained so much of a toxic material that you'd be advised to follow hazmat procedures to clean up a broken bulb.

     



  • I'm a big fan of the Mayan Haab calendar. It has exactly 365 days, so it gets out of sync-- but the Mayans knew it got out of sync, so they compensated for it by just remembering (for example) "ok this year June is mid-winter..."


  • Trolleybus Mechanic

    @blakeyrat said:

    I'm a big fan of the Mayan Haab calendar. It has exactly 365 days, so it gets out of sync-- but the Mayans knew it got out of sync, so they compensated for it by just remembering (for example) "ok this year June is mid-winter..."
     

    Except that their baktun rollover inspired a Rolland Emmerich movie, so that's a major strike against them.

    Swinging back to their favor, though, is the Uayeb concept.  Technically the calendar was 360 days, and they'd have these five days left over at the end that didn't fit into any months. So they figured "eh, fudge it, those days don't exist so nothing can happen" and took them off. How's that for an excuse to take time off. "Sorry, I can't come into work today because technically the world doesn't exist."



  • @Lorne Kates said:

    Except that their baktun rollover inspired a Rolland Emmerich movie, so that's a major strike against them.

    The Long Count is a totally different calendar. Also, Godzilla also inspired an Emmerich movie, and Godzilla kicks ass. So fuck you.

    @Lorne Kates said:

    Swinging back to their favor, though, is the Uayeb concept.  Technically the calendar was 360 days, and they'd have these five days left over at the end that didn't fit into any months. So they figured "eh, fudge it, those days don't exist so nothing can happen"

    Actually, I think they thought demons were let loose and hid in their houses and prayed. But... same deal.


  • Trolleybus Mechanic

    @blakeyrat said:

    @Lorne Kates said:
    Except that their baktun rollover inspired a Rolland Emmerich movie, so that's a major strike against them.

    The Long Count is a totally different calendar. Also, Godzilla also inspired an Emmerich movie, and Godzilla kicks ass. So fuck you.

    I checked the math, and your logic is infallible. Consider me fucked.

     @blakeyrat said:

    @Lorne Kates said:

    Swinging back to their favor, though, is the Uayeb concept.  Technically the calendar was 360 days, and they'd have these five days left over at the end that didn't fit into any months. So they figured "eh, fudge it, those days don't exist so nothing can happen"

    Actually, I think they thought demons were let loose and hid in their houses and prayed. But... same deal.

     

    But over time it became just another non-religious ceremony where everyone just ate maize and watched the Super Tlatchtli Bowl



  • @da Doctah said:

    Or if some government agency suddenly decided that the lightbulbs we've been using for a century and a half were now evil, and forbid the use of them in favor of a new type that wouldn't work in enclosed fixtures, fixtures controlled by dimmers, fixtures in cold environments, fixtures subject to vibration, etc, and which incidentally contained so much of a toxic material that you'd be advised to follow hazmat procedures to clean up a broken bulb.
    Luckily, you can still buy heatbulbs which as a side effect also produce light.


  • Discourse touched me in a no-no place

    @ender said:

    @da Doctah said:
    Or if some government agency suddenly decided that the lightbulbs we've been using for a century and a half were now evil, and forbid the use of them in favor of a new type that wouldn't work in enclosed fixtures, fixtures controlled by dimmers, fixtures in cold environments, fixtures subject to vibration, etc, and which incidentally contained so much of a toxic material that you'd be advised to follow hazmat procedures to clean up a broken bulb.
    Luckily, you can still buy heatbulbs which as a side effect also produce light.
    I'm sure that idea got knocked on the head pretty sharpish.



  • @PJH said:

    @ender said:
    @da Doctah said:
    Or if some government agency suddenly decided that the lightbulbs we've been using for a century and a half were now evil, and forbid the use of them in favor of a new type that wouldn't work in enclosed fixtures, fixtures controlled by dimmers, fixtures in cold environments, fixtures subject to vibration, etc, and which incidentally contained so much of a toxic material that you'd be advised to follow hazmat procedures to clean up a broken bulb.
    Luckily, you can still buy heatbulbs which as a side effect also produce light.
    I'm sure that idea got knocked on the head pretty sharpish.

    I thought it turned out that it was an Al-Qaeda plot to keep us dependent on middle-eastern oil all along.



Log in to reply