比较2个字符串并根据动态模式提取变量

时间:2014-12-02 13:34:20

标签: php string date

所以我有两个字符串:

$date_format = "yyyy-dd-mm";
$actual_date = "2014-05-12";

现在,它可以采用不同的格式(不同的分隔符,y,m,d的不同位置),例如:

$date_format = "yyyy/dd/mm";
$actual_date = "2014/05/12";

OR

$date_format = "dd|mm|yyyy";
$actual_date = "05|12|2014";

但是2种格式的字符串总是匹配。

分隔符也可能有所不同,但大部分都是 - 或/或\或| 。我只想比较yyyy,mm和dd,并将这些值中的任何内容分配给这些变量。

如何确保通过比较两个字符串来提取年份,月份和日期?

所以,我需要这样的东西:

$yyyy = 2014;
$mm = 12;
$dd = 5;

我想避免对年,月日期和分隔符的每种可能组合使用多个if条件。

1 个答案:

答案 0 :(得分:1)

晚会到这里没有人; - /

<强> Working code at Viper-7 - PHP 5.3.18

要求: 匹配有限数量的日期格式。检查它们是否有效并将它们转换为“标准”格式。

我们希望通过编辑“数据”来添加“新”日期格式,而不是以“if'son”控制语句的格式添加新的“代码”。

好的,让我们看看我们可以对所请求的,提供的“日期”格式应用哪些规则:

  • '年,月和'日'组件需要按特定顺序排列。
  • 需要一个分隔符
  • 需要检查日期组件的每个部分的有效范围。
  • '最小'长度检查和最大长度检查

如果输入日期与每种格式的所有上述规则相匹配,那么我们可以相当确定它是有效的。

那么,如何在“数据”结构中表示那些可以轻松添加到新“格式”中的“规则”?使用'array:

示例:

$patterns = array(
    "yyyy-dd-mm" => array('order' => array('yyyy', 'mm', 'dd'),
                           'sepchar' => '-',
                           'ranges' => array('yyyy' => array('minLength' => 4, 'maxLength' => 4,  'from' => 1900, 'to' => 3000),
                                              'mm'   => array('minLength' => 1, 'maxLength' => 2, 'from' => 1,    'to' => 12),
                                              'dd'   => array('minLength' => 1, 'maxLength' => 2, 'from' => 1,    'to' => 31)
                                       ),
    ),
);

现在,我们需要一些代码来使用数组'日期格式规则'条目并应用所有检查并返回我们可用于创建标准日期的信息。

完成工作的例程:

/**
 * Try and match the input date against the pattern
 *
 * @param string $pattern
 * @param array $rules
 *
 * @return array('match' => boolean,
 *                'yyyy' => value,
 *                'mm'   => value,
 *                'dd'   => value,
 *                )
 * so you can format for input into 'DateTime' object...
 */
function checkPattern($date, array $rules) {
    $result = array('match' => false, 'yyyy' => '', 'dd' => '', 'mm' => '');

    $sepCount = substr_count($date, $rules['sepchar']);
    if ($sepCount !== 2) { // valid seperators
        return $result;
    }


    $dateParts = explode($rules['sepchar'], $date);

    // check the parts are in the correct order...
    foreach($rules['order'] as $reqdPart) { // $reqdPart is the key into 'ranges'...
        $datePart = current($dateParts);


        // build result array with the input date parts
        $result[$reqdPart] = $datePart; // assume input date is valid

        // check individual parts agains the 'ranges' checks
        $result['match'] =    (     strlen($reqdPart) >= $rules['ranges'][$reqdPart]['minLength']
                                && strlen($reqdPart) <= $rules['ranges'][$reqdPart]['maxLength'])
                           && (    intval($datePart) >= $rules['ranges'][$reqdPart]['from']
                                && intval($datePart) <= $rules['ranges'][$reqdPart]['to']);

        next($dateParts);

        if (!$result['match']) { // ok so far?
            break;
        }
    }

    // add any extra test here to try and validate the data...
    return $result;
}

备注

  • 它返回一个数组,以便可以构建任何格式字符串
  • '匹配'条目始终是正确的。

使用$ pattern数组运行输入的代码。这是评论。

// process the input dates - report as matched and which pattern...

    foreach($input as $date) {

        reset($patterns); // use internal array iterator...
        $result = array('match' => false); // stop the pattern matching if we find one
        while (current($patterns) !== false && !$result['match']) {
          $currentPattern = key($patterns); // save for use later
          $result = checkPattern($date, current($patterns));
          next($patterns); // next pattern to check
        }

        if ($result['match']) {
            $dt = new DateTime($result['yyyy'] .'-'. $result['mm'] .'-'. $result['dd']);
            echo '<br />Matched: ', $date, ' with format: ', $currentPattern,
                  '(', $dt->format("Y-m-d") ,')' ;
        }
        else {
            echo '<br />Failed: ', $date;
        }
    }

示例输入:

$input = array("2014-05-12", "2014/05/12", "05|12|2014",
                '12/never/2014', /* rubbish */
                '1/1/2014',  /* uk:  dd/md/yyyy */
                '7-20-2014', /* usa: mm-dd-yyyy */
                '1/14/2014',  /* uk: invalid  dd/md/yyyy */
                '14-20-2014' /* usa: invalid mm-dd-yyyy */
    );

示例输出:

Matched: 2014-05-12 with format: yyyy-dd-mm(2014-05-12)
Matched: 2014/05/12 with format: yyyy/dd/mm(2014-05-12)
Matched: 05|12|2014 with format: dd|mm|yyyy(2014-12-05)
Failed: 12/never/2014
Matched: 1/1/2014 with format: dd/mm/yyyy(2014-01-01)
Matched: 7-20-2014 with format: mm-dd-yyyy(2014-07-20)
Failed: 1/14/2014
Failed: 14-20-2014

完整的'模式'数组:

$patterns = array(
    "yyyy-dd-mm" => array('order' => array('yyyy', 'mm', 'dd'),
                           'sepchar' => '-',
                           'ranges' => array('yyyy' => array('minLength' => 4, 'maxLength' => 4,  'from' => 1900, 'to' => 3000),
                                              'mm'   => array('minLength' => 1, 'maxLength' => 2, 'from' => 1,    'to' => 12),
                                              'dd'   => array('minLength' => 1, 'maxLength' => 2, 'from' => 1,    'to' => 31)
                                       ),
    ),

    "dd|mm|yyyy" => array('order' => array('dd', 'mm', 'yyyy'),
                           'sepchar' => '|',
                           'ranges' => array('yyyy' => array('minLength' => 4, 'maxLength' => 4, 'from' => 1900, 'to' => 3000),
                                              'mm'   => array('minLength' => 1, 'maxLength' => 2, 'from' => 1,    'to' => 12),
                                              'dd'   => array('minLength' => 1, 'maxLength' => 2, 'from' => 1,    'to' => 31)
                                       ),
    ),

    "yyyy/dd/mm" => array('order' => array('yyyy', 'mm', 'dd'),
                           'sepchar' => '/',
                           'ranges' => array('yyyy' => array('minLength' => 4, 'maxLength' => 4, 'from' => 1900, 'to' => 3000),
                                              'mm'   => array('minLength' => 1, 'maxLength' => 2, 'from' => 1,    'to' => 12),
                                              'dd'   => array('minLength' => 1, 'maxLength' => 2, 'from' => 1,    'to' => 31)
                                       ),
    ),
    // usa format
    "mm-dd-yyyy" => array('order' => array('mm', 'dd', 'yyyy'),
                           'sepchar' => '-',
                           'ranges' => array('yyyy' => array('minLength' => 4, 'maxLength' => 4, 'from' => 1900, 'to' => 3000),
                                              'mm'   => array('minLength' => 1, 'maxLength' => 2, 'from' => 1,    'to' => 12),
                                              'dd'   => array('minLength' => 1, 'maxLength' => 2, 'from' => 1,    'to' => 31)
                                       ),
    ),
    // uk format
    "dd/mm/yyyy" => array('order' => array('dd', 'mm', 'yyyy'),
                           'sepchar' => '/',
                           'ranges' => array('yyyy' => array('minLength' => 4, 'maxLength' => 4, 'from' => 1900, 'to' => 3000),
                                              'mm'   => array('minLength' => 1, 'maxLength' => 2, 'from' => 1,    'to' => 12),
                                              'dd'   => array('minLength' => 1, 'maxLength' => 2, 'from' => 1,    'to' => 31)
                                       ),
    ),
);