1

I have as scenario where the $string variable sent to DateTime::modify($string) is read from a database edited by users, how can i validate that $string is a proper string for DateTime::modify() ?

AddWeb Solution Pvt Ltd
  • 21,025
  • 5
  • 26
  • 57
FroboZ
  • 437
  • 1
  • 6
  • 17
  • May this link will help you. http://stackoverflow.com/questions/16075159/check-if-a-string-is-a-valid-date-using-datetime-tryparse – Ravi Hirani Jan 20 '16 at 12:15
  • @RaviHirani Your link regards a C# question which is similar but I'm not sure the implementation suggested there can be done with PHP? – FroboZ Jan 20 '16 at 12:18

4 Answers4

1

try this function for validating time stamp string based on the format

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

function was copied from this answer or php.net

Community
  • 1
  • 1
Sivagopal Manpragada
  • 1,554
  • 13
  • 33
0

It's generally best practice to check the user input before it is saved to the database so you can be confident of it on the way out.

You could use a try/catch block as well:

try {
    $date = new DateTime('2016-12-12');
    $date->modify('+1 dayBLA');
    echo $date->format('Y-m-d');
} catch (Exception $e) {
    echo 'Caught exception: ',  $e->getMessage(), "\n";
}

EDIT: after looking at this, if the string passed to modify is invalid (not the date string as I originally supposed), your code will throw a Warning not an exception.

You may be able to trigger a Warning to temporarily be treated like an exception with set_error_handler.

function warning_handler($errno, $errstr, $errfile, $errline, array $errcontext) {
    throwErrorException($errstr, 0, $errno, $errfile, $errline);
}
set_error_handler('warning_handler', E_WARNING);

try {
    $date = new DateTime('2016-12-12');
    $date->modify('+1 daybla');
    echo $date->format('Y-m-d');
} catch (Exception $e) {
    echo 'Caught exception: ',  $e->getMessage(), "\n";
}

restore_error_handler();

However, this is starting to look a bit nasty. It might be cleaner (in your code, not your logs probably) to compare the date before and after the modify method is called to see if they are different.

$date = new DateTime('2016-12-12');
$origDate = clone $date; //I believe this will get you an independent object
$date->modify('+1 daybla');
if ($origDate == $date) {
    echo "Bad value passed to modify, probably a warning in the logs :(";
}
pherris
  • 17,195
  • 8
  • 42
  • 58
  • I agree the input should be checked before being entered into the database and I do but I want to validate on this end as well if possible- just in case. I tried adding a try and catch as you suggested but this still raises a warning when modify fails? – FroboZ Jan 20 '16 at 12:13
  • I was just noticing that too - after looking around I'm not seeing a great way to do this. Obviously a regex on the string you are passing to `modify` would be best, but the strings that method takes seem to be hugely disparate. Maybe you could solve by being more restrictive about the user input e.g. three inputs: 1) `+`/`-`, 2) `hour`/`day` 3) count (an int). I edited the answer with a few other options you can try - good luck! – pherris Jan 20 '16 at 12:34
0

You could do something like this, and call it before you pass the string into your actual date:

function modifyIsValid($modifyString) {
    $d = new DateTime();
    $isValid = $d->modify($modifyString);

    if ($isValid === false) {
        return false;
    }

    return true;
}

->modify() returns false is the string passed is not valid, although it will also throw up an E_Warning which is not ideal.

$d = new DateTime();
$string = 'not a valid modifier';

if (modifyIsValid($string)) {
    // Continue 
}  else {
    // Print a friendly error message.
}

You can find more information about it in the manual: http://php.net/manual/en/datetime.modify.php

Hope it helps.

Mikey
  • 2,606
  • 1
  • 12
  • 20
  • This looks like a good way to validate the string but I need to handle the warning, would this be a scenario where it's maybe okay to simply suppress the warning? – FroboZ Jan 20 '16 at 12:15
  • @ChristopherKarlsson That could be one potential way of getting rid of the error, afterall even you are supressing the error, you are still handling it so it should be fine. The other way to perform the check would most likely to use regex to validate the string against all the valid formats found here: http://php.net/manual/en/datetime.formats.php – Mikey Jan 20 '16 at 12:20
  • I will accept this answer because it seems to be the closest you can get to do a clean validation even if it raises a warning, I will handle the warning as suggested in @pherris answer. – FroboZ Jan 20 '16 at 13:04
0

Bit late to the party here, this works perfectly for me...

function isDateModifyValid($String)
{
    if (strlen($String) == 0) { return false; }
    $now = new \DateTime(null, new \DateTimeZone("UTC"));
    $rtn = false; // Default return value
    @$now->modify($String) && $rtn = true; 
     // If modify($string) fails, $rtn won't set to true, else $rtn will set to true
    // ^ ^ @ suppress error
    return $rtn;
}

//TEST DATA
foreach (array("+1 hour", "+2 hour, -5 minutes", "12:00", "dsfv", "13:00, + 1 hour", "Yesterday, 12:00", "Neext weeekc", "Next month") as $testString)
{
    if (isDateModifyValid($testString))
    {
        echo "VALID ::: $testString\n";
    } else {
        echo "INVALID ::: $testString\n";
    }
}

VALID ::: +1 hour VALID ::: +2 hour, -5 minutes VALID ::: 12:00 INVALID ::: dsfv VALID ::: 13:00, + 1 hour VALID ::: Yesterday, 12:00 INVALID ::: Neext weeekc VALID ::: Next month

Noam Hacker
  • 4,671
  • 7
  • 34
  • 55