2016-05-17 46 views
4

我有一個日期(例如.yyyy-mm-dd hh:mm:ss),我希望能夠返回true,如果我們有一個匹配該模式的字符串,完全,或者部分匹配該模式,從頭到尾。例如。 44將匹配模式,因爲44將匹配yy,但-12不匹配,因爲-不是有效的「y」字符。匹配從一開始的一部分字符串

一些不雅的解決方案出現在我身上。我可以這樣做preg_match

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

這只是執行基於年份的部分匹配。它會需要擴展出佔月,日,小時,分鐘,等等,但應該表現出的想法#1

我也可以做類似...

$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) 

但是,這種情況似乎也很複雜。

我也可以這樣做:

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); 
    ... 
} 

但似乎臃腫爲好。

換句話說,我正在尋找2005-將返回true的函數,22005-1也會如此。但-2005將返回false,如205-neubert

我希望能夠做的是將有效值傳遞給SQL查詢。例如。 WHERE date_column LIKE '$str%'。如果date_column是DATETIME,那麼搜索-12-是浪費時間,因爲date_column不可能將其作爲值。

任何想法?

+0

我使用'^'和'$'在我的模式。我的第一個和在'preg_match'調用中的第二個一樣。 '$ patterns'數組在'#^'和'$#'之間連接。 – neubert

+0

什麼值是可選的?也許'^ \ d {4} - \ d {2} - \ d {2} \ d {2}:\ d {2}:\ d {2} $'?您可以將'\ d's擴展爲允許的範圍,但這會變得難以閱讀。 – chris85

+2

您可以爲上述模式添加一些有效和無效的輸入嗎? – anubhava

回答

2

像這樣的東西應該工作:

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); 
} 

例如,您的輸入字符串長度爲6個字符,它只使用日期模式的前6個塊(^\d\d\d\d-\d$)。

0

你也可以搭配使用strpos():根據您的問題,下面的評論

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

這不是我想要做的。我想看看問題的字符串是完整的日期還是部分日期,而不是別的。你的代碼正在做的是它告訴你一個預定義的長度的日期是否存在於字符串中的任何地方。 – neubert

2

,如果我理解問題的權利,你可以用這個單一的正則表達式來匹配您的輸入:

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

RegEx Demo

+0

它不會做......但是我明白你在做什麼。我想要做hh:mm:ss我可能不得不去強調)?)?)?)?進行中 )?)?)?)?)?)?)?。我也必須在中間添加一些東西,然後...... ick。只是似乎很難管理正則表達式哈哈。 – neubert

1

我知道這個問題已經被回答和關閉,但我認爲這是一個有趣的挑戰,我決心想出一個非正則表達式的解決方案。我也希望它更具可重用性,而不是針對特定情況的硬編碼。

這就是我最終的結果;我相信它可以進一步改善!根據你原來的問題:)

// 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; 
} 

用法示例:

$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 
相關問題