开发者

Problem with simple regular expression in PHP

The best way to explain my problem is to j开发者_StackOverflowust show you.

Input String:

/04-11-2010/12:45/

Regular Expression to get date and time parts:

preg_match('@/(\d\d)-(\d\d)-(\d\d\d\d)/(\d\d):(\d\d)/@', $input, $matches);

PHP Matches Array:

Array
(
    [0] => /01-11-2010/12:45/
    [1] => 01
    [2] => 11
    [3] => 2010
    [4] => 12
    [5] => 45
)

Now the above regex works perfectly at getting the individual component parts that represent the date and time in the input string.

The problem is that the time part needs to be optional without bringing down the entire regular expression.

Problem Input String:

/04-11-2010//

PHP Matches Array

Array
(
)

Basically what I need to be returned by the matches array is:

Array
(
    [0] => /01-11-2010/12:45/
    [1] => 01
    [2] => 11
    [3] => 2010
    [4] => 
    [5] => 
)

Note array elements 4 and 5 still need to exist but return empty.


Use the question mark operator and a non-capturing group to make stuff optional.

@/(\d\d)-(\d\d)-(\d\d\d\d)/(?:(\d\d):(\d\d))?/@

I'm not sure how this interacts with the match array - if having the empty array elements is absolutely critical, you might need to instead go for

@/(\d\d)-(\d\d)-(\d\d\d\d)/((?:\d\d)?):?((?:\d\d)?)/@

Which has its own false-positives (the colon in the time is now optional).


Make the second part optional:

'@/(\d\d)-(\d\d)-(\d\d\d\d)/(?:(\d\d):(\d\d))?/@'

Here a non-capturing group (?:…) is used that cannot be referenced and thus doesn’t change the matching groups.


  @/(\d\d)-(\d\d)-(\d\d\d\d)/((?:\d\d)?):?((?:\d\d)?)/@

does what you want (i.e. populates groups 4 and 5), but also accepts incomplete times like in

    /04-11-2010/12:/

don't know if this is fine with you


I'm not a php-head, but how about:

preg_match('@/(\d\d)-(\d\d)-(\d\d\d\d)/(\d\d)?:?(\d\d)?/@', $input, $matches);

As far as regexps go, that should match a string that has no time field.


@OP, don't need messy regex.

$str="/04-11-2010/12:45/";
$s = array_filter(explode('/',$str));
$date=$s[1];
$time=$s[2];
$date_parts=explode("-",$date);
$time_parts=explode(":",$time);
if ( checkdate($date_parts[1],$date_parts[0],$date_parts[2]) ){
    print "date ok\n";
}


Use native PHP functions for this task, using regular expressions is a bit of an overkill.

PHP 5 has the date_parse function:

$string = '/04-11-2010/12:45/';
$dateArray = date_parse(str_replace('/', ' ', $string));
print_r($dateArray);

$string = '/04-11-2010//';
$dateArray = date_parse(str_replace('/', ' ', $string));
print_r($dateArray);

Output:

Array
(
    [year] => 2010
    [month] => 11
    [day] => 4
    [hour] => 12
    [minute] => 45
    [second] => 0
    [fraction] => 0
    [warning_count] => 0
    [warnings] => Array
        (
        )

    [error_count] => 0
    [errors] => Array
        (
        )

    [is_localtime] => 
)

Array
(
    [year] => 2010
    [month] => 11
    [day] => 4
    [hour] => 
    [minute] => 
    [second] => 
    [fraction] => 
    [warning_count] => 0
    [warnings] => Array
        (
        )

    [error_count] => 0
    [errors] => Array
        (
        )

    [is_localtime] => 
)

PHP 5.3 has a more flexible date_parse_from_format function that you could also use.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜