2

im trying to validate a date to see if it matchs the mysql format

this is the code

$match = "/^\d{4}-\d{2}-\d{2} [0-2][0-3]:[0-5][0-9]:[0-5][0-9]$/";

    $s = $this->input->post("report_start"). " " . $this->input->post("report_start_time").":00";
    $e = $this->input->post("report_end"). " " . $this->input->post("report_end_time").":59";

    if($this->input->post("action") != "")
    {
        echo trim($s). " => " . preg_match($match, trim($s));
        echo "<br>";
        echo trim($e). " => " . preg_match($match, trim($e));
}

the date format goes into $s and $e are

$s = 2011-03-01 00:00:00
$e = 2011-03-01 23:59:59

and they both return false (0).

i tested the pattern on http://www.spaweditor.com/scripts/regex/index.php and it returns true (1)

http://pastebin.com/pFZSKYpj

however if i manual inter the date strings into preg_match like

preg_match($match, "2011-03-01 00:00:00")

it works.

i have no idea what im doing wrong

======================

now that i think about it, i only need to validate the houre:min part of the datetime string.

im manually adding the seconds and the date is forced by a datepicker and users cant edit it

heshanh
  • 367
  • 3
  • 6
  • 19
  • 1
    What exactly do you post as `report_start` and `report_end`? – Nils Werner Feb 28 '11 at 17:16
  • im not using strtotime/date because if the date/times are wrong i want to throw and error, i dont want it to default to 00:00. this snippet is part of a bigger function that returns number of hours logged between the give date range and it defaults to 00:00 it'll return wrong number of hours – heshanh Feb 28 '11 at 17:30
  • var_dump on $s/$e returns string(20) – heshanh Feb 28 '11 at 17:31
  • For datetime validating you can use [this function](http://stackoverflow.com/a/12323025/67332). Example: `var_dump(validateDate('13:59:59', 'H:i:s'));` – Glavić Oct 24 '13 at 12:42

7 Answers7

2

You're making your work harder that it needs to be. In php there are many date handling functions that mean you don't have to treat dates like strings. So, rather than test that your input dates are in the correct format, just insist on the correct format:

$adate= date_create('January 6, 1983 1:30pm'); //date format that you don't want
$mysqldate= $adate->format("Y-m-d h:i:s");//date format that you do want

There are also functions to check that a date is a real date, like checkdate.

dnagirl
  • 20,196
  • 13
  • 80
  • 123
  • There is no need to create an object, which may or may not be disposed in a timely manner, when you can simply use a function call. – UnkwnTech Feb 28 '11 at 17:23
  • @Unkwntech: I prefer to use DateTime objects and ancillaries like DateInterval, DateTimeZone and DatePeriod because common problems like daylight savings time are automatically taken care of. If you're concerned about an unused object not being managed properly, I expect you're not using OOP at all. I am. So one more object makes little difference to me. – dnagirl Feb 28 '11 at 18:53
  • I do use OOP almost exclusively, however I also build apps which respond to millions of requests a day, so I build with as small of a footprint as humanly possible. This includes not using objects when a simple (built-in)function call will do the trick. I guess it's just a counter opinion. – UnkwnTech Feb 28 '11 at 21:05
2

ok heres wat i did. since im forcing the date format and the ending seconds of the time part

i just validated the hour:mini part using "/^2[0-3]|[01][0-9]:[0-5][0-9]$"; and if that returns true i put everything together end reconstructed the final datetime string

    $match = "/^2[0-3]|[01][0-9]:[0-5][0-9]$/";

    $s_d = $this->input->post("report_start");
    $s_t = $this->input->post("report_start_time");
    $e_d = $this->input->post("report_end");
    $e_t = $this->input->post("report_end_time");

    if($this->input->post("action") != "")
    {


        if(
            ( preg_match($match , trim($s_d." ".$s_t.":00")) )
         && ( preg_match($match , trim($e_d." ".$e_t.":59")) )
         )
         {

            $r = $this->model_report->client_hours_logged(array($s,$e));
            $data['report'] = $r;
            var_dump($r);
            //$this->load->view("report/client_hours_per_client",$data);
         }
    }
sjngm
  • 12,423
  • 14
  • 84
  • 114
heshanh
  • 367
  • 3
  • 6
  • 19
1

Watch out:

[0-2][0-3] is not a good regex for hour values - it will match 01, 12, 23 and others, but it will fail 04 through 09 and 14 through 19.

Better use (2[0-3]|[01][0-9]) instead.

Tim Pietzcker
  • 328,213
  • 58
  • 503
  • 561
  • doing this "/^\d{4}-\d{2}-\d{2} 2[0-3]|[01][0-9]:[0-5][0-9]:[0-5][0-9]$/" actually fixed the first date '2011-03-01 00:00:00' – heshanh Feb 28 '11 at 17:32
  • question regarding this... clearly my regx isnt good. but cant i check for the whole hour. as in say i have 10:20 (h/m). instead of checking for each char 1,0 : 2,0 cant i check for 10 and 20? – heshanh Feb 28 '11 at 17:39
1

I use this to validate a 'Y-m-d H:i:s' format date string:

match = '/^[12][0-9]{3}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[01]) ([01][0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9]$/';
x7BiT
  • 447
  • 4
  • 5
0

You could use strtotime and date to parse and format the date properly.

Nils Werner
  • 34,832
  • 7
  • 76
  • 98
0

Why not just simply force the date into the format you want:

$e = '2011-03-01 00:00:00';
$mysqlFormat = date('Y-m-d H:i:s', strtotime($e));

Also, there is a bit of an error in your regex [0-2][0-3]:[0-5][0-9]:[0-5][0-9] will only match the hours of 00,01,02,03,10,11,12,13,20,21,22,23 so it will never match 4am, or 3pm among others. That aside I looked over your RegEx and I don't see any problems with it matching the test cases you've offered. I would check to make sure there is not extra whitespace on either side of date string with trim().

UnkwnTech
  • 88,102
  • 65
  • 184
  • 229
  • i thought of doing this. but what is they enter an invalid val for hour/min? say 33:99 wouldnt that default to 00:00? – heshanh Feb 28 '11 at 17:25
  • @heshan actually it does some rather nasty stuff, I just tested with var_dump(date('Y-m-d H:i:s', '2001-03-01 33:99:00')) and it outputs string(19) "1970-01-01 01:33:21" – UnkwnTech Feb 28 '11 at 18:01
0

I concur with Tim : MySQL behaves in quirks mode and always tries to go easy on DATE and DATE_TIME column types. You can omit certain parts of your input and it still will try to compensate and achieve that goal successfully to some degree... That's why, most numbers your Reg-ex considers as invalid, MySQL will accept as valid.

Gelmir
  • 1,829
  • 1
  • 18
  • 28