15

I'm using codeigniter with PHP. I'm using following form,

<?php
    echo form_open('/register/create_new', $form_params);
?>

DOB: <input type="text" id="dob" name="reg[dob]">
     <input type="submit" value="Create Account" />
</form>

here, #dob is in dd-mm-yyyy format.

my validation code is,

array(
  'field' => 'reg[dob]',
  'label' => 'DOB',
  'rules' => 'required'
)

How can i set the rules for correct date validation?

KarSho
  • 5,699
  • 13
  • 45
  • 78
  • If possible - consider using separate dropdown menus for day month year . Less errors for your users, especially with the month and day mixups that can happen. – cartalot Jan 16 '13 at 16:26
  • 1
    @cartalot but, im using jquery datepicker – KarSho Jan 17 '13 at 05:08

10 Answers10

22

You can take use of CodeIgniters callback functions by creating a callback_date_valid() function that check if the date is valid.

And to check if it is valid, you could use PHP's checkdate function

array(
  'field' => 'reg[dob]',
  'label' => 'DOB',
  'rules' => 'required|date_valid'
)

function callback_date_valid($date){
    $day = (int) substr($date, 0, 2);
    $month = (int) substr($date, 3, 2);
    $year = (int) substr($date, 6, 4);
    return checkdate($month, $day, $year);
}
Winks
  • 395
  • 2
  • 9
22

I have a pretty clean solution for this. You can extend codeigniters form validation library.

Do this by putting a MY_Form_validation.php file in your application/libraries folder. This file should look like this:

class MY_Form_validation extends CI_Form_validation {

    public function __construct($rules = array()) {
        parent::__construct($rules);
    }


    public function valid_date($date) {
        $d = DateTime::createFromFormat('Y-m-d', $date);
        return $d && $d->format('Y-m-d') === $date;
    }
}

To add the error message, you go to your application/language/ folder and open the form_validation_lang.php file. Add an entry to the $lang array at the end of the file, like so:

$lang['form_validation_valid_date'] = 'The field {field} is not a valid date';

Note that the key here must be the same as the function name (valid_date).

Then in your controller you use this as any other form validation function like for example 'required'

$this->form_validation->set_rules('date','Date','trim|required|valid_date');
Joha
  • 935
  • 12
  • 32
  • 4
    This is a very elegant solution, and I would like to recommend an additional change to allow better customisation. Adding a parameter for the date format: function valid_date($date, $format = 'Y-m-d') and referencing it in the function. You can pass this parameter in the validation rules like: 'trim|required|valid_date[d-m-y]' Then the lang file can use {param} to specify the expected format on error. – CYMA Apr 21 '17 at 00:19
  • https://stackoverflow.com/questions/12878863/adding-custom-callback-to-codeigniter-form-validation – Sushant Pimple Aug 09 '17 at 13:57
  • 1
    plus one for nice standard way.....need to add format parameter aswell. – Imran Qamer Mar 15 '18 at 07:49
  • 1
    This is by far the best answer! – Pieter-Jan Casteels Apr 16 '20 at 12:54
  • This should definitely be the accepted answer. Nice, elegant, standard. – Javier Larroulet Jun 12 '20 at 22:08
  • Nice comprehensive solution! I just changed the valid_date function to this: `return (bool)strtotime($date);` to cover all cases. – Dario Zadro Oct 13 '20 at 20:18
9

you can do it with regex

$this->form_validation->set_rules('reg[dob]', 'Date of birth', 'regex_match[(0[1-9]|1[0-9]|2[0-9]|3(0|1))-(0[1-9]|1[0-2])-\d{4}]'); 
Abin Manathoor Devasia
  • 1,945
  • 2
  • 21
  • 47
  • 4
    It's impossible to implement reliable date validation with regular expressions. Yours is actually quite good but, for instance, it claims that `29-02-2000` is not valid. – Álvaro González Aug 20 '13 at 08:10
  • @ÁlvaroG.Vicario i think its also possible with 'regex' – Abin Manathoor Devasia Aug 20 '13 at 08:21
  • 3
    Yeah, right, if you have the patience you can probably hard-code all the exceptions (including missing days due to transition to Gregorian calendar) but you know what I mean: regular expressions are not the best tool. – Álvaro González Aug 20 '13 at 08:25
  • @ÁlvaroG.Vicario http://stackoverflow.com/questions/8647893/regular-expression-leap-years-and-more?answertab=active#tab-top – Abin Manathoor Devasia Aug 27 '13 at 09:11
  • 1
    This regex format doesn't work. I had to enclose the pattern with `/.../`. Also, I can't get this pattern to work. `regex_match[/\d{4}-\d{2}-\d{2}/]` seems to work, but not `regex_match[/\d{4}-(0[1-9]|1[0-2])-\d{2}/]`. I'm gonna stick to the callback method. – akinuri Aug 27 '19 at 14:52
2

I know this is old, but I just encountered the same issue. I like the answer Winks provided, but found that the code did not work. I modified it to this:

  public function your_form_handler($date)
  {
    // ....
    $this->form_validation->set_rules('date', 'Date', 'required|callback_date_valid');
    // ....
  }

  /**
   * Validate dd/mm/yyyy
   */
  public function date_valid($date)
  {
    $parts = explode("/", $date);
    if (count($parts) == 3) {      
      if (checkdate($parts[1], $parts[0], $parts[2]))
      {
        return TRUE;
      }
    }
    $this->form_validation->set_message('date_valid', 'The Date field must be mm/dd/yyyy');
    return false;
  }
tmsimont
  • 2,651
  • 2
  • 25
  • 36
  • I found itz useful. But this also validates 21/07/1yyy. ie, one digit year also validated. – Dayz Apr 25 '17 at 06:41
2

There is no builtin date validation in Codeigniter form_validation Library, but you can use its callback to call a function and validate the date using PHP's own capabilities.

With DateTime you can make the shortest date&time validator for all formats.

function validateDate($date, $format = 'Y-m-d H:i:s')
{
    $d = DateTime::createFromFormat($format, $date);
    return $d && $d->format($format) == $date;
}

var_dump(validateDate('2012-02-28 12:12:12')); # true
var_dump(validateDate('2012-02-30 12:12:12')); # false
var_dump(validateDate('2012-02-28', 'Y-m-d')); # true
var_dump(validateDate('28/02/2012', 'd/m/Y')); # true
var_dump(validateDate('30/02/2012', 'd/m/Y')); # false
var_dump(validateDate('14:50', 'H:i')); # true
var_dump(validateDate('14:77', 'H:i')); # false
var_dump(validateDate(14, 'H')); # true
var_dump(validateDate('14', 'H')); # true

var_dump(validateDate('2012-02-28T12:12:12+02:00', 'Y-m-d\TH:i:sP')); # true
# or
var_dump(validateDate('2012-02-28T12:12:12+02:00', DateTime::ATOM)); # true

var_dump(validateDate('Tue, 28 Feb 2012 12:12:12 +0200', 'D, d M Y H:i:s O')); # true
# or
var_dump(validateDate('Tue, 28 Feb 2012 12:12:12 +0200', DateTime::RSS)); # true
var_dump(validateDate('Tue, 27 Feb 2012 12:12:12 +0200', DateTime::RSS)); # false

function was copied from this answer or php.net

Glavić
  • 42,781
  • 13
  • 77
  • 107
Muhammad
  • 6,725
  • 5
  • 47
  • 54
1

Try this one out...i think it's more simple.

$this->form_validation->set_rules('date', 'Date', 'trim|required|callback_checkDateFormat');

function checkDateFormat($date) {
        $d = DateTime::createFromFormat('Y-m-d', $date);
        if(($d && $d->format('Y-m-d') === $date) === FALSE){
            $this->form_validation->set_message('checkDateFormat', ''.$date.' is not a valid date format.');
            return FALSE;
        }else{
            return TRUE;
        }
}
curiosity
  • 834
  • 8
  • 20
0

I like the answer tmsimont provided, but found that the code did not work if non numeric values enterd. Modified code is given below:

/**
    * Validate dd/mm/yyyy
    */
    public function date_valid(){
        $date=$this->input->post('dob');
        $parts = explode("/", $date);
        if (count($parts) == 3) {     
            if (is_numeric($parts[2])) {  
                if (is_numeric($parts[0])) {
                    if (is_numeric($parts[1])) {    
                        if (checkdate($parts[1], $parts[0], $parts[2])){
                            return TRUE;
                        }
                    }
                }
            }
        }

        $this->form_validation->set_message('date_valid', 'The Date field must be mm/dd/yyyy');
        return false;
    }
Dayz
  • 269
  • 2
  • 12
0

The actual Regex for Codeigniter Date validation :

$this->form_validation->set_rules('reg[dob]','Date of birth',array('regex_match[/^((0[1-9]|[12][0-9]|3[01])[- \/.](0[1-9]|1[012])[- \/.](19|20)\d\d)$/]'));

I am using same expression for format dd-mm-yyyy and dd/mm/yyyy

No Warnings and errors :-)

0

I've written this custom validator for ci3 - validates the d/m/Y H:i format - you can easily change that.

$this->form_validation->set_rules("start_date", "Start Date", 'trim|callback__check_date_valid');


   public function _check_date_valid($date){

    $this->form_validation->set_message('_check_date_valid', "Please enter a valid date");
    $d = DateTime::createFromFormat('d/m/Y H:i', $date);

    if($d && $d->format('d/m/Y H:i') === $date || $date == ''){
        return true;
    }else{

        return false;
    }

}
Edmunds22
  • 715
  • 9
  • 10
  • Unless you're good with regex - this is safer and allows you to explicitly set the php date format to validate against. – Edmunds22 Jun 29 '18 at 10:52
0

According to iamyojimbo answer,

    $date = [
        '28.02.2012', // true
        '28/02/2012', // true
        '28-02-2012', // true
        '28 02 2012', // true
        '28 02 1812', // false
    ];

    $pattern = '/^(0[1-9]|[12][0-9]|3[01])[\.\/\-\ ](0[1-9]|1[012])[\.\/\-\ ](19|20)\d\d$/';

    foreach ($date as $subject) {
        print_r(
            preg_match(
                $pattern,
                $subject
            )
        );
    }
Lysak
  • 333
  • 1
  • 4
  • 7