Page 1 of 1

PHP - IsDate method

Posted: Tue Jul 14, 2009 5:36 pm
by andyhoneycutt
Hey everyone. Quick question about dates here. I'm working on a data viewer for one of my projects (it's form intense, so I'm rewriting some very noob code I wrote a long time ago, for performance and scalability). The user is going to want to sort by whichever field is presented in the data view.

So far, I've allowed the programmer to use two different approaches to my class(es). They can allow the class to determine the data type of the sorting column, or they can specify one. The auto-sort works well, with the exception of some items it thinks are dates, but actually aren't. My question here is twofold: 1. - Is it worth solving to allow a programmer to stuff things into my class and it works like *magic*, 2. - What could I do to better determine if a scalar is, indeed, a date?

Below is the code for my logical structure as well as the IsDate Helper.

The chunk that decides what type we're working with

Code: Select all

   /**
     * If we're running an auto sort, figure out what data type we're
     * working with, commit the sort.
     */
    if( self::$sort_type == self::SORT_AUTO )
    {
      if(is_numeric($data[0][self::$sortby_key]))
        usort($data,'SimpleSort::Cmp');
 
      elseif(is_float($data[0][self::$sortby_key]))
        usort($data,'SimpleSort::Cmp');
 
      elseif(self::IsDate($data[0][self::$sortby_key]))
        usort($data,'SimpleSort::DateCmp');
 
      else
        usort($data,'SimpleSort::StringCmp');
    }
The IsDate Helper.

Code: Select all

 /**
   * Helper method for SimpleSort::Sort(). This function evaluates and
   * breaks down a string to determine if it's a valid date. Buggy.
   *
   * TODO: provide bug examples.
   */
  private static function IsDate($string)
  {
    $t = strtotime($string);
    $m = date('m',$t);
    $d = date('d',$t);
    $y = date('Y',$t);
    return checkdate ($m, $d, $y);
  }
Thanks much all!
-Andy

Re: PHP - IsDate method

Posted: Wed Jul 15, 2009 11:40 am
by andyhoneycutt
Any ideas on this one?

Re: PHP - IsDate method

Posted: Wed Jul 15, 2009 12:04 pm
by omniuni
Well, *MAGIC* is not usually good, but if you understand WHY it works, then it's not really magic, just a good suggestion. If you've got a line or two of code that will help fix the problem, integrate it, but do it together, so you both understand what's going on and why.

Re: PHP - IsDate method

Posted: Wed Jul 15, 2009 12:52 pm
by andyhoneycutt
My thoughts are this: either I should remove auto-config altogether, or make sure it's not buggy at all. I don't see the point of having an auto-config for my sort class if certain parts of it aren't reliable. My goal is to make using these classes as easy as possible, without sacrificing scalability. I'm not entirely sure who all may end up using these classes, so sitting down and explaining the code isn't necessarily an option.

I can post the entire class group here if that would help. I'm really stumped on this one. A regular expression isn't a reliable way to determine if the string is a date, there are too many possibilities to consider. check_date() just informs me whether the resultant date is valid...

Re: PHP - IsDate method

Posted: Thu Jul 23, 2009 2:26 pm
by andyhoneycutt
This appears to be the stumbling block for my current "solution": http://us3.php.net/manual/en/function.s ... .php#86277

Re: PHP - IsDate method

Posted: Thu Jul 23, 2009 2:52 pm
by requinix
andyhoneycutt wrote:This appears to be the stumbling block for my current "solution": http://us3.php.net/manual/en/function.s ... .php#86277
So redefine what "buggy" means. If strtotime can understand the string then it's a date, otherwise it's not a date.

By the way, try IsDate("cookie")... ;)

Re: PHP - IsDate method

Posted: Thu Jul 23, 2009 3:46 pm
by andyhoneycutt
Ok, after a couple more hours trying to solve this one (am close, but I honestly feel there isn't a 100% true solution), I give up. Here's my code if anyone wants to take a stab at it.

Code: Select all

function IsDate($string)
{
  if( $string < 1 )
    return -1;
  if( strlen($string) < 6 )
    return -1;
 
  $white_list = array(
    "january",   "february", "march",    "april",
    "may",       "june",     "july",     "august",
    "september", "october",  "november", "december",
    "sunday",    "monday",   "tuesday",  "wednesday",
    "thursday",  "friday",   "saturday"
  );
  $words = explode(" ", strtolower($string));
 
  $t = strtotime($string);
  $m = date('m',$t);
  $d = date('d',$t);
  $y = date('Y',$t);
 
  if( !is_numeric($string) )
  {
    if( in_array($words[0],$white_list) )
    {
      if( is_numeric($t) )
        if(checkdate($m,$d,$y))
          return date("Y-m-d H:i:s",$t);
    }
    return -1;
  }
  else
  {
    if( $t )
      if( $y < 3000 )
        if(checkdate($m,$d,$y))
          return date("Y-m-d H:i:s",$t);
  }
 
  return -1;
}
Sample usage:

Code: Select all

while($r = mysql_fetch_assoc($result))
{
  foreach($r as $k => $c)
  {
    $j = trim($c);
    if( ($x = IsDate($j)) !== -1 )
    {
      echo "$k, $c = $x\t\t";
    }
    if( $x !== -1 )
    {
      echo "\n";
    }
  }
}
I know it's not working properly, I'm not going to get it back to a working point, but feel free to tool around with the idea...

-Andy :banghead:

Re: PHP - IsDate method

Posted: Thu Jul 23, 2009 3:50 pm
by andyhoneycutt
tasairis wrote:
andyhoneycutt wrote:This appears to be the stumbling block for my current "solution": http://us3.php.net/manual/en/function.s ... .php#86277
So redefine what "buggy" means. If strtotime can understand the string then it's a date, otherwise it's not a date.

By the way, try IsDate("cookie")... ;)
Anything that it can't see as a date, but is a string it will use the first letter of the string as a special date identifier. E.g. strtotime('a'), strtotime('b'), etc., etc.

Maybe i'm just burned out or overly-frustrated, but I don't see the import of IsDate("cookie"), seems to return the lowest value possible for a date/time counting from unix 0.

Re: PHP - IsDate method

Posted: Thu Jul 23, 2009 4:13 pm
by requinix
andyhoneycutt wrote:Anything that it can't see as a date, but is a string it will use the first letter of the string as a special date identifier. E.g. strtotime('a'), strtotime('b'), etc., etc.
Not quite.

Code: Select all

var_dump(strtotime("cookie")); // bool(false)
It won't try its hardest to get a date out of a string: it merely knows a bunch of formats. Who are you to say that "A" should not be interpreted as a date?

If you want IsDate to accept a date in one of a specific set of formats, that's different, but if you want something simple,

Code: Select all

function IsDate($date) {
    return (strtotime($date) !== false);
}
andyhoneycutt wrote:Maybe i'm just burned out or overly-frustrated, but I don't see the import of IsDate("cookie"), seems to return the lowest value possible for a date/time counting from unix 0.
If strtotime fails to convert the string to a time then it returns false. Which, numerically, is 0. Which is the date January 1st 1970 12:00am GMT. Which is day=1 month=1 year=1970 (or 31,12,1969 or 2,1,1970, depending on your timezone). Which is a valid date.

No matter what you threw at IsDate it would always return true.

Re: PHP - IsDate method

Posted: Thu Jul 23, 2009 4:30 pm
by andyhoneycutt
True. Absolutely true. All of it.

The problem is also that excepting the first thousand iterations, all of these return valid dates (strtotime($i) !== false):

Code: Select all

for($i=0;$i<10000;$i++)
  if( strtotime($i) )
    echo $i, "\n";
I'm stepping back from this problem for a couple days. I'll probably hit it up with enthusiasm on Monday.

Thanks very much for your input, btw! :D

-Andy