2016-05-17 8 views
4

Ich habe ein Datum (zB. JJJJ-MM-TT hh: mm: ss) und ich möchte in der Lage sein, wahr zurückzugeben, wenn wir eine Zeichenfolge haben, die diesem Muster entspricht, oder das teilweise mit diesem Muster übereinstimmt, vom Anfang bis zum Ende. z.B. 44 würde mit dem Muster übereinstimmen, da 44 mit dem JJ übereinstimmen würde, aber -12 würde nicht übereinstimmen, da kein gültiges "y" -Zeichen ist.passend zu einem Teil einer Zeichenfolge von Anfang an

Ein paar unelegante Lösungen kommen mir vor. Ich konnte preg_match auf so etwas tun:

#^\d(\d(\d(\d(-)?)?)?)?$# 

Das ist nur eine teilweise Übereinstimmung auf das Jahr durchführt. Es müßte für die Monat zu berücksichtigen, Tag, Stunde, Minute erweitert geführt werden, usw., aber das sollte Idee # zeigt 1.

ich auch etwas tun könnte, wie ...

$patterns = [ 
    '', 
    '\d', 
    '\d\d', 
    '\d\d\d', 
    '\d\d\d\d', 
    '\d\d\d\d-', 
    ... 
]; 
isset($patterns[strlen($str)] && preg_match('#^' . $patterns[strlen($str)] . '$#', $str) 

Aber auch das scheint gewunden zu sein.

Ich könnte auch dies tun:

switch (strlen($str)) { 
    case 1: return preg_match('#^\d$#', $str); 
    case 2: return preg_match('#^\d\d$#', $str); 
    case 3: return preg_match('#^\d\d\d$#', $str); 
    case 4: return preg_match('#^\d\d\d\d$#', $str); 
    case 5: return preg_match('#^\d\d\d\d-$#', $str); 
    ... 
} 

aber das scheint auch aufgebläht.

Mit anderen Worten, ich bin auf der Suche nach einer Funktion, für die 2005- True zurückgegeben wird, wie auch 2 und 2005-1. Aber -2005 wird false zurückgeben, ebenso wie oder neubert.

Ich möchte in der Lage sein, gültige Werte in eine SQL-Abfrage zu übergeben. z.B. WHERE date_column LIKE '$str%'. Wenn date_column ein DATETIME ist, dann ist die Suche nach -12- Zeitverschwendung, weil date_column das nicht als Wert haben kann.

Irgendwelche Ideen?

+0

Ich bin mit '^' und '' $ in meinem Muster. Meine erste und die zweite im 'preg_match'-Call. Das '$ patterns'-Array wird zwischen' #^'und' $ # 'verkettet. – neubert

+0

Welche Werte sind optional? Vielleicht '^ \ d {4} - \ d {2} - \ d {2} \ d {2}: \ d {2}: \ d {2} $'? Du könntest die '\ d's als erlaubte Bereiche erweitern, aber dann wird das schwer zu lesen sein. – chris85

+2

Können Sie einige gültige und ungültige Eingaben für obige Muster hinzufügen? – anubhava

Antwort

2

So etwas sollte funktionieren:

function doesMatch($str) { 
    // The date pattern split so that each array entry matches exactly one character 
    $pattern_chunks = array(
     '\d', '\d', '\d', '\d', '-', 
     '\d', '\d', '-', 
     '\d', '\d', 
     '\s', 
     '\d', '\d', ':', 
     '\d', '\d', ':', 
     '\d', '\d' 
    ); 

    $chunk_count = count($pattern_chunks); 
    $str_len = strlen($str); 

    // If the string is empty, it's clearly not a date 
    if ($str_len < 1) { return false; } 

    // If the string is longer than our pattern chunks, there's no way it matches 
    if ($str_len > $chunk_count) { return false; } 

    // Make a pattern using the first N chunks of our pattern parts 
    $pattern = '^' . implode('', array_slice($pattern_chunks, 0, $str_len)) . '$'; 

    // Return if the string matches 
    return (preg_match($pattern, $str) > 0); 
} 

Zum Beispiel ist Ihre Eingabezeichenfolge 6 Zeichen lang, sie verwendet nur die ersten 6 Teile des Datumsmusters (^\d\d\d\d-\d$).

0

Sie könnten auch strpos() mit übereinstimmen:

$a = "2016-05-17 was a good day."; 
if (strpos(substr($a, 0, 10), '2016-05-17') !== false) { 
    echo "Indeed it was"; 
} 
+0

Das ist nicht wirklich das, was ich tun möchte. Ich möchte sehen, ob die fragliche Zeichenfolge ein vollständiges Datum oder ein Teildatum und sonst nichts ist. Was Ihr Code tut, ist, dass er Ihnen sagt, ob ein Datum mit einer vorgegebenen Länge irgendwo in einer Zeichenkette vorhanden ist. – neubert

2

Basierend auf Kommentare unterhalb Ihrer Frage und wenn ich die Frage richtig verstanden, können Sie diese einzelne Regex verwenden, um Ihre Eingaben zu entsprechen:

^(?:\d{1,3}|\d{4}(?:-(?:\d{1,2}(?:-\d{0,2})?)?)?)$ 

RegEx Demo

+0

Es tut nicht hh: mm: ss aber ich sehe was du machst. Ich nehme an, hh: mm: ss würde ich wahrscheinlich weitermachen)?)?)?)? Ich mach das)?)?)?)?)?)?)?. Ich müsste auch etwas in der Mitte hinzufügen und ... ick. Scheint einfach wie eine schwer zu handhabende Regex lol. – neubert

1

Ich weiß, diese Frage wurde bereits beantwortet und geschlossen, aber ich dachte, es war eine interessante Herausforderung und ich war entschlossen, mit einer nicht-Regex-Lösung zu kommen. Ich wollte auch, dass es mehr wiederverwendbar ist, als für einen bestimmten Fall fest codiert.

Hier ist, was ich gelandet bin; Ich bin sicher, es könnte noch weiter verbessert werden!:)

// case-insensitive string format comparison 
// if $strict is true, the string lengths must also match 
// if $strict is false, the strings are compared left to right 
function strfcasecmp($str, $format, $strict = false) { 
    $len1 = strlen($str); 
    $len2 = strlen($format); 

    // make sure we have a valid length 
    if ($len1 < 1 || $len1 > $len2) { 
     return false; 
    } 

    // if strict, make sure length matches as well 
    if ($strict) { 
     if ($len1 !== $len2) { 
      return false; 
     } 
    } 

    // compare alpha, numeric, space & printable characters 
    for ($i = 0; $i < $len1; $i++) { 
     switch (true) { 
      case ctype_alpha($format[$i]): 
       if (!ctype_alpha($str[$i])) { 
        return false; 
       } 
       break; 

      case ctype_digit($format[$i]): 
       if (!ctype_digit($str[$i])) { 
        return false; 
       } 
       break; 

      case ctype_space($format[$i]): 
       if (!ctype_space($str[$i])) { 
        return false; 
       } 
       break; 

      case ctype_punct($format[$i]): 
       if ($str[$i] !== $format[$i]) { 
        return false; 
       } 
       break; 

      default: 
       // character must match at least one type specified above 
       return false; 
     } 
    } 

    return true; 
} 

Beispiel für die Verwendung auf der Grundlage Ihrer ursprünglichen Frage:

$format = '0000-00-00 00:00:00'; 
var_dump(strfcasecmp('44', $format)); // true 
var_dump(strfcasecmp('-12', $format)); // false 
var_dump(strfcasecmp('2005-', $format)); // true 
var_dump(strfcasecmp('2', $format)); // true 
var_dump(strfcasecmp('2005-1', $format)); // true 
var_dump(strfcasecmp('-2005', $format)); // false 
var_dump(strfcasecmp('205-', $format)); // false 
var_dump(strfcasecmp('neubert', $format)); // false 
Verwandte Themen