【问题标题】:Identify date format from a string in PHP从 PHP 中的字符串中识别日期格式
【发布时间】:2017-05-09 15:06:34
【问题描述】:

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

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

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

日期字符串2014-12-04 我想让代码说这个日期有Y-m-d 格式。如果日期字符串是2017-04-03 11:11:48.653,我希望代码说这个日期格式是Y-m-d h:i:s

【问题讨论】:

  • 问题不清楚;使用值发布您的代码和数据库架构
  • 我们讨论了多少种不同的格式? 2? 5? 100?

标签: php sql-server date


【解决方案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;
}

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

【讨论】:

    【解决方案2】:

    格式化日期并了解日期格式的最佳方法,解决方案适合那些正在开发日期格式的人。我还添加了 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
    

    【讨论】:

    • 这不处理年份只有两位数的日期。您可能希望将它们添加到您的模式中。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-12-25
    • 2016-02-06
    • 2011-04-08
    • 2020-08-20
    • 1970-01-01
    • 1970-01-01
    • 2015-01-12
    相关资源
    最近更新 更多