Using date_parse_from_format on PHP 5.2

Last week, I was working on a problem of the Datepicker formats been really weird on some cases for The Events Calendar plugin, as Modern Tribe does support WordPress minimum PHP required version for it's plugins, the developers have to solve some problems with the Tools that PHP 5.2 provides us.

The enemy! 😱

Fatal error: Call to undefined function date_parse_from_format()

On the case of dates, this becomes a real problem since we don't have support for the date_parse_from_format or DateTime::createFromFormat() we needed to be able to parse formats like 15/02/1993 formatted with d/m/Y.

So Looking around the Internet I found a few solutions for the problem but the one that I was able to include on the plugin and improve was the function below, please if you use this function and find a way to improve it even further comment below and let's make it ROCK!

/**
 * As PHP 5.2 doesn't have a good version of `date_parse_from_format`, this is how we deal with
 * possible weird date picker formats not working
 *
 * @param  string $format  The weird format you are using
 * @param  string $date    The date string to parse
 * @param  string $rformat A good Return Format
 *
 * @return string          The date formatted as you requested
 */
function bord_datetime_from_format( $format, $date, $rformat = null ) {

    // Reverse engineer the relevant date formats
    $keys = array(
        // Year with 4 Digits
        'Y' => array( 'year', '\d{4}' ),

        // Year with 2 Digits
        'y' => array( 'year', '\d{2}' ),

        // Month with leading 0
        'm' => array( 'month', '\d{2}' ),

        // Month without the leading 0
        'n' => array( 'month', '\d{1,2}' ),

        // Month ABBR 3 letters
        'M' => array( 'month', '[A-Z][a-z]{2}' ),

        // Month Name
        'F' => array( 'month', '[A-Z][a-z]{2,8}' ),

        // Day with leading 0
        'd' => array( 'day', '\d{2}' ),

        // Day without leading 0
        'j' => array( 'day', '\d{1,2}' ),

        // Day ABBR 3 Letters
        'D' => array( 'day', '[A-Z][a-z]{2}' ),

        // Day Name
        'l' => array( 'day', '[A-Z][a-z]{5,8}' ),

        // Hour 12h formatted, with leading 0
        'h' => array( 'hour', '\d{2}' ),

        // Hour 24h formatted, with leading 0
        'H' => array( 'hour', '\d{2}' ),

        // Hour 12h formatted, without leading 0
        'g' => array( 'hour', '\d{1,2}' ),

        // Hour 24h formatted, without leading 0
        'G' => array( 'hour', '\d{1,2}' ),

        // Minutes with leading 0
        'i' => array( 'minute', '\d{2}' ),

        // Seconds with leading 0
        's' => array( 'second', '\d{2}' ),
    );

    // Convert format string to regex
    $regex = '';
    $chars = str_split( $format );
    foreach ( $chars as $n => $char ) {
        $last_char = isset( $chars[ $n - 1 ] ) ? $chars[ $n - 1 ] : '';
        $skip_current = '\\' == $last_char;
        if ( ! $skip_current && isset( $keys[ $char ] ) ) {
            $regex .= '(?P<' . $keys[ $char ][0] . '>' . $keys[ $char ][1] . ')';
        } else if ( '\\' == $char ) {
            $regex .= $char;
        } else {
            $regex .= preg_quote( $char );
        }
    }

    $dt = array();

    // Now try to match it
    if ( preg_match( '#^' . $regex . '$#', $date, $dt ) ){
        // Remove unwanted Indexes
        foreach ( $dt as $k => $v ){
            if ( is_int( $k ) ){
                unset( $dt[ $k ] );
            }
        }

        // We need at least Month + Day + Year to work with
        if ( ! checkdate( $dt['month'], $dt['day'], $dt['year'] ) ){
            return false;
        }
    } else {
        return false;
    }

    $formatted = '{year}-{month}-{day}' . ( isset( $dt['hour'], $dt['minute'], $dt['second'] ) ? ' {hour}:{minute}:{second}' : '' );

    // If we don't have a formatted way out, we set it up
    if ( ! is_string( $rformat ) ){
        $rformat = 'Y-m-d' . ( isset( $dt['hour'], $dt['minute'], $dt['second'] ) ? ' H:i:s' : '' );
    }

    // Build the Formated Date
    foreach ( $dt as $key => $value ) {
        $formatted = str_replace( '{' . $key . '}', $value, $formatted );
    }

    // Now parse the formatted used.
    $utime = strtotime( $formatted );
    if ( ! $utime ){
        return false;
    }

    // Now return the formatted time
    return date( $rformat, $utime );
}

Discussions — No responses yet

Leave a Reply