从PHP中的字符串中识别日期格式

时间:2017-05-09 15:06:34

标签: php sql-server date

我正在尝试更新数据库中的所有日期字段,以便为所有表格中的每个日期添加5天。

我设法将日期和行id拉入数组,然后生成SQL代码语句来更新它们。但是,每个表都有不同的日期格式,有些时间包括一些没有。我想在约会中添加5天然后将其保存回来。目前,如果所有日期都具有相同的格式但是不足以解决我的问题,我可以这样做。

我想要的是一个可以从日期字符串生成字符串格式的代码。例如:

日期字符串<input type="number" name="quantity" min="-100" max="100" step="0.01">我希望代码说这个日期格式为2014-12-04。如果日期字符串为Y-m-d,我希望代码说这个日期格式为2017-04-03 11:11:48.653

2 个答案:

答案 0 :(得分:3)

格式化日期并了解日期格式的最佳方法,解决方案。我还添加了 ISO8601日期格式

function date_extract_format( $d, $null = '' ) {
    // check Day -> (0[1-9]|[1-2][0-9]|3[0-1])
    // check Month -> (0[1-9]|1[0-2])
    // check Year -> [0-9]{4} or \d{4}
    $patterns = array(
        '/\b\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d{3,8}Z\b/' => 'Y-m-d\TH:i:s.u\Z', // format DATE ISO 8601
        '/\b\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])\b/' => 'Y-m-d',
        '/\b\d{4}-(0[1-9]|[1-2][0-9]|3[0-1])-(0[1-9]|1[0-2])\b/' => 'Y-d-m',
        '/\b(0[1-9]|[1-2][0-9]|3[0-1])-(0[1-9]|1[0-2])-\d{4}\b/' => 'd-m-Y',
        '/\b(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])-\d{4}\b/' => 'm-d-Y',

        '/\b\d{4}\/(0[1-9]|[1-2][0-9]|3[0-1])\/(0[1-9]|1[0-2])\b/' => 'Y/d/m',
        '/\b\d{4}\/(0[1-9]|1[0-2])\/(0[1-9]|[1-2][0-9]|3[0-1])\b/' => 'Y/m/d',
        '/\b(0[1-9]|[1-2][0-9]|3[0-1])\/(0[1-9]|1[0-2])\/\d{4}\b/' => 'd/m/Y',
        '/\b(0[1-9]|1[0-2])\/(0[1-9]|[1-2][0-9]|3[0-1])\/\d{4}\b/' => 'm/d/Y',

        '/\b\d{4}\.(0[1-9]|1[0-2])\.(0[1-9]|[1-2][0-9]|3[0-1])\b/' => 'Y.m.d',
        '/\b\d{4}\.(0[1-9]|[1-2][0-9]|3[0-1])\.(0[1-9]|1[0-2])\b/' => 'Y.d.m',
        '/\b(0[1-9]|[1-2][0-9]|3[0-1])\.(0[1-9]|1[0-2])\.\d{4}\b/' => 'd.m.Y',
        '/\b(0[1-9]|1[0-2])\.(0[1-9]|[1-2][0-9]|3[0-1])\.\d{4}\b/' => 'm.d.Y',

        // for 24-hour | hours seconds
        '/\b(?:2[0-3]|[01][0-9]):[0-5][0-9](:[0-5][0-9])\.\d{3,6}\b/' => 'H:i:s.u',
        '/\b(?:2[0-3]|[01][0-9]):[0-5][0-9](:[0-5][0-9])\b/' => 'H:i:s',
        '/\b(?:2[0-3]|[01][0-9]):[0-5][0-9]\b/' => 'H:i',

        // for 12-hour | hours seconds
        '/\b(?:1[012]|0[0-9]):[0-5][0-9](:[0-5][0-9])\.\d{3,6}\b/' => 'h:i:s.u',
        '/\b(?:1[012]|0[0-9]):[0-5][0-9](:[0-5][0-9])\b/' => 'h:i:s',
        '/\b(?:1[012]|0[0-9]):[0-5][0-9]\b/' => 'h:i',

        '/\.\d{3}\b/' => '.v'
    );
    //$d = preg_replace('/\b\d{2}:\d{2}\b/', 'H:i',$d);
    $d = preg_replace( array_keys( $patterns ), array_values( $patterns ), $d );

    return preg_match( '/\d/', $d ) ? $null : $d;
}


function date_formating( $date, $format = 'd/m/Y H:i', $in_format = false, $f = '' ) {
    $isformat = date_extract_format( $date );
    $d = DateTime::createFromFormat( $isformat, $date );
    $format = $in_format ? $isformat : $format;
    if ( $format ) {
        if ( in_array( $format, [ 'Y-m-d\TH:i:s.u\Z', 'DATE_ISO8601', 'ISO8601' ] ) ) {
            $f = $d ? $d->format( 'Y-m-d\TH:i:s.' ) . substr( $d->format( 'u' ), 0, 3 ) . 'Z': '';
        } else {
            $f = $d ? $d->format( $format ) : '';
        }
    }
    return $f;
} // end function


function date_convert_format( $old = '' ) {
    $old = trim( $old );
    if ( preg_match( '/^[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])$/', $old ) ) { // MySQL-compatible YYYY-MM-DD format
        $new = $old;
    } elseif ( preg_match( '/^[0-9]{4}-(0[1-9]|[1-2][0-9]|3[0-1])-(0[1-9]|1[0-2])$/', $old ) ) { // DD-MM-YYYY format
        $new = substr( $old, 0, 4 ) . '-' . substr( $old, 5, 2 ) . '-' . substr( $old, 8, 2 );
    } elseif ( preg_match( '/^(0[1-9]|[1-2][0-9]|3[0-1])-(0[1-9]|1[0-2])-[0-9]{4}$/', $old ) ) { // DD-MM-YYYY format
        $new = substr( $old, 6, 4 ) . '-' . substr( $old, 3, 2 ) . '-' . substr( $old, 0, 2 );
    } elseif ( preg_match( '/^(0[1-9]|[1-2][0-9]|3[0-1])-(0[1-9]|1[0-2])-[0-9]{2}$/', $old ) ) { // DD-MM-YY format
        $new = substr( $old, 6, 4 ) . '-' . substr( $old, 3, 2 ) . '-20' . substr( $old, 0, 2 );
    } else { // Any other format. Set it as an empty date.
        $new = '0000-00-00';
    }
    return $new;
}

$date_1 = '13/05/2020 19:20:15.156457';
$date_2 = '25-05-2020 10:20';
$date_3 = '2020.05.20 10:20';
$date_4 = '2020.25.05 18:20';
$date_5 = '05/05/2020 12:20';
$date_6 = '05.05.2020 10:20';
$date_7 = '2020-20-05';
//-----------------------------
echo "1($date_1): " . date_formating( $date_1, false, true ) . PHP_EOL;
// echo-> isformat: d/m/Y H:i:s.u
// 1(13/05/2020 19:20:15): 2020-05-13 19:20
echo "2($date_2): " . date_formating( $date_2 ) . PHP_EOL;
// echo-> isformat: d-m-Y H:i
// 2(25-05-2020 10:20): 25/05/2020 10:20
echo "3($date_3): " . date_formating( $date_3 ) . PHP_EOL;
// echo-> isformat: Y.m.d H:i
// 3(2020.05.20 10:20): 20/05/2020 10:20
echo "4($date_4): " . date_formating( $date_4 ) . PHP_EOL;
// echo-> isformat: Y.d.m H:i
// 4(2020.25.05 18:20): 25/05/2020 18:20
echo "5($date_5): " . date_formating( $date_5 ) . PHP_EOL;
// echo-> isformat: d/m/Y H:i
// 5(05/05/2020 12:20): 05/05/2020 12:20
echo "6($date_6): " . date_formating( $date_6 ) . PHP_EOL;
// echo-> isformat: d.m.Y H:i
// 6(05.05.2020 10:20): 05/05/2020 10:20
echo "7($date_7): " . date_formating( $date_7, false, true ) . PHP_EOL;
// echo-> isformat: Y-d-m
// 7(2020-20-05): 2020-20-05
echo "Date ISO8601: = " . date_formating( $date_1, 'DATE_ISO8601' ) . PHP_EOL;
// echo-> isformat: d/m/Y H:i:s.u
// Date ISO8601: = 2020-05-13T19:20:15.156Z
echo "7($date_7): = " . date_convert_format( $date_7 );
// 7(2020-20-05): = 2020-20-05

答案 1 :(得分:1)

如果您不需要保留格式(即您可以在添加五天时更改数据库中的格式),则可以将字符串抛出strtotime。如果可能的话,它会尝试检测格式:

$timestamp = strtotime($string_with_unknown_format);

或者,您可以使用正则表达式检查不同的格式:

function extractDateTimeFormat($string) {
    if (preg_match('/^\d{4}-\d{2}-\d{2}$/', $string))
        $return 'Y-m-d';

    if (preg_match('/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/', $string))
        return 'Y-m-d H:i:s';

    if (preg_match('/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d{3}$/', $string))
        return 'Y-m-d H:i:s.v';

    if (preg_match('/^\d{2}\/\d{2}\/\d{4}$/', $string))
        $return 'm/d/Y';

    if (preg_match('/^\d{2}\.\d{2}\.\d{4}$/', $string))
        $return 'd.m.Y';
}

然而,根据您期望的格式,这可能会很烦人。另一方面 - 有多少可以?

下一个替代方案是直接在字符串中用占位符替换数字 - 这将更灵活,但可能更不可预测。在这种情况下,线的顺序很重要。如果您需要添加12小时格式(AM / PM),则需要在H:i:s行之前插入行,否则它将无法正常工作。

function extractDateTimeFormat($string) {
    $string = preg_replace('/\b\d{4}-\d{2}-\d{2}\b/', 'Y-m-d');
    $string = preg_replace('/\b\d{2}\/\d{2}\/\d{4}\b/', 'm/d/Y');
    $string = preg_replace('/\b\d{2}\.\d{2}\.\d{4}\b/', 'd.m.Y');
    $string = preg_replace('/\b\d{2}:\d{2}\b:\d{2}\b/', 'H:i:s');
    $string = preg_replace('/\b\d{2}:\d{2}\b/', 'H:i');
    $string = preg_replace('/\.\d{3}\b/', '.v');

    if (preg_match('/\d/', $string) 
        return false;

    return $string;
}

这样,您就可以独立检测日期和时间格式,因此您不必考虑所有可能的组合。
您必须使用实时数据检查哪种方法效果更好。