how can i replace date/time in this format 'Fri Mar 23 15:21:08 2012' with preg_replace?
Date in this format is present couple of times in my text and i need to replace it with current time/date.
Thanks,
Chris
Well, what you need is an expression that will match 3 letters (Fri) followed by a space and another three letters (Mar).
First we need to match some letters:
/[a-z]/
We can match exactly 3 letters like this:
/[a-z]{3}/
...and we'll need it to be case insensitive:
/[a-z]{3}/i
...so the first part is just:
/[a-z]{3} [a-z]{3}/i
Next, we need to match either 1 or 2 numerics. A numeric can be represented with the escape sequence \d, so we'd use:
/\d{1,2}/
Next we match the time string, using the same escape sequence:
/\d{2}:\d{2}:\d{2}/
...followed by a final 4 digit year:
/\d{4}/
Put it all together and we get:
/[a-z]{3} [a-z]{3} \d{1,2} \d{2}:\d{2}:\d{2} \d{4}/i
// Fri Mar 23 15 : 21 : 08 2012
Now, we need to replace it with the current date and time. The usual place we'd go for that is the date() function, but how to we get that into the replacement dynamically? Well we could pass it as a string literal, or we could use a callback function to get it from preg_replace_callback(). But, preg_replace() gives us the e modifier which causes the replacement string to be evaluated for PHP code. We have to be careful and sparing with it's use, as with any PHP eval(), but this is a legitimate use case.
So our final PHP code looks like this:
preg_replace(
'/[a-z]{3} [a-z]{3} \d{1,2} \d{2}:\d{2}:\d{2} \d{4}/ie',
"date('D M j H:i:s Y')",
$str
);
See it working
I think listing the finite sets of options is kind of better for these task and it will also save you from false positives. These are the patterns to match each part of the date format:
Days: (?:Mon|Tue|Wed|Thu|Fri|Sat|Sun)
Months: (?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)
Day: \d{1,2}
Time: \d{1,2}:\d{2}:\d{2}
Year: \d{4}
Putting everything together:
(?:Mon|Tue|Wed|Thu|Fri|Sat|Sun) (?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) \d{1,2} \d{1,2}:\d{2}:\d{2} \d{4}
The code might look like:
$current_date = date('D M j H:i:s Y');
$text = preg_replace(
'/(?:Mon|Tue|Wed|Thu|Fri|Sat|Sun) (?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) \d{1,2} \d{1,2}:\d{2}:\d{2} \d{4}/i',
$current_date,
$text
);
See a working example.
preg_replace('/Fri Mar 23 15:21:08 2012/',date('D M d H:i:s Y'),$string);
Normally do what you want.
Related
I have a question regarding one case.
I'm using php preg_replace() function to format data from this string:
12:05 Place1 12:40 14:00 16:30 Place2 "Test" 29 Janury
I need it to be outputed like this:
<li>29 January - Place1 - 12:05</li>
<li>29 January - Place2 "Test" - 12:40 14:00 16:30</li>
My regular expression:
/(\d[0-9]:\d[0-9]).+?(\D+).+?(\d[0-9]\s(January|February|March))/
I'm currently using something like this:
$text = "12:05 Place1 12:40 14:00 16:30 Place2 "Test" 29 Janury";
$data = preg_replace("/(\d[0-9]:\d[0-9]).+?(\D+).+?(\d[0-9]\s(January|February|March))/", "<li>$3 - $2 - $1</li>", $text);
echo $data;
The problem it shows only first matches,
29 January - Place1 - 12:05
Maybe someone know how to solve this case?
Thanks :)
It is not possible to do in one regex because you want to use a match from the end of the string before the PCRE engine has reached it. You need to do this in two steps:
preg_match() with PREG_OFFSET_CAPTURE to capture the date from the end of the string into another variable. Use the offset it provides to truncate the original string.
preg_match_all() the truncated string to get the times & places as an array, then iterate the array to use each match & the date variable to create the list. '/((?:\s*+\d\d:\d\d)++)\s++((?:.(?!\d\d:\d\d\s))++)\s*+/' is a suitable pattern.
I am trying to change a string which may have a date inside e.g.
"This is the test string with 22/12/2012. 23/12/12 could anywhere in the string"
I need to change above string so that date are in the format d-m-y i.e.
"This is the test string with 22-12-2012. 23-12-12 could appear anywhere in the string"
EDIT:
Please note that the date will could changed in terms of years i.e. 2012 or 12 could be used at time i.e 20/06/2012, 20/06/12. Only year could be 2 or 4 digits, rest will be same.
Any help will be highly appreciated.
Cheers,
Use preg_replace like this:
$repl = preg_replace('~(\d{2})/(\d{2})/(\d{2,4})~', '$1-$2-$3', $str);
Live Demo: http://ideone.com/7HDNZa
$string = preg_replace("/([0-9]{2})\/([0-9]{2})\/([0-9]{2,4})/", "$1-$2-$3", $string);
The regex will find 3 lots of 2 numbers (or 2x2 + 1x4) separated by /'s and replace them with the same numbers separated by -'s.
You could try something like this:
preg_replace('~\b([0-2]?[1-9]|3[01])/(0?[1-9]|1[0-2])/(?=(?:\d\d|\d{4})\b)~', '$1-$2-', $str);
Should match valid dates only. Does match dates where the prefix 0 is not present, e.g. 4/16/13 if this is not desierable, remove the two first question marks (in [0-2]? and 0?)
PHP REGEX is a weakness of mine, but still I manage to get some things done with online tools. Consider the following:
A subject string which generally follows this pattern: 1551 UTC 04 June 2012
I want to extract the "04" and assign it to the $day variable using below:
$day = preg_replace("/^([0-9]{4})\s([A-Z]{3})\s([0-9]{2})\s([A-Za-z]{3,})\s([0-9]{4})$/", "$3", $weather['date']);
This works on the following website: http://sqa.fyicenter.com/Online_Test_Tools/Test_Regular_Expression_Search_Replace.php
but I can't get it to work in my script... $day would equal the whole subject string.
The result of your var_dump() is string(38) "1551 UTC 04 June 2012 ". It has 38 chars while it should be only 21. So it looks like there are multiple whitespaces in the string.
Try to trim() your input string and replace \s with \s+ to support multiple whitespaces:
$day = preg_replace("/^([0-9]{4})\s+([A-Z]{3})\s+([0-9]{2})\s+([A-Za-z]{3,})\s+([0-9]{4})$/", "$3", trim($weather['date']));
you say preg_replace, but I think you want to use preg_match(). Is that correct that you don't want to replace the "04" but you just want to put it into a the variable $day? If so use preg_match(). In your description you say you want to capture only the "04" part, but your regex has many capture groups (anything within "()" is a capture group and will be returned in the array you give to preg_match).
I am trying to extract a date from a string variable and was hoping to get some help.
$editdate = "Content last modified on 17 May 2011 at 23:13";
from this string, I am trying to extract 17 May 2011, please keep in mind that the date will vary and the code needs to be able to extract any date in this format, DD MMM YYYY.
I thought of using preg_match to do this but I couldn't come up with a proper regex pattern that would extract the date properly.
Is this possible to do with regex or should I use a different function?
Thanks for the help !
Try:
$timestamp = strtotime( str_replace( array("Content last modified ", "at"), "", $editdate ) );
Which will leave you with an epoch time stamp that you can then output however you like using date()
This is possible with a regex. Given the format DD MMM YYYY you would need a regex that matches two (or one?) digits, then one space, three letters, one space and four digits.
That would look like:
$regex = '/(\d{2} [a-z]{3} \d{4})/i';
This can be optimized further.
Presuming the textual content of your string is always the same, and that it always ends with the time...
$editdate = substr($editdate, 25, -9); // 17 May 2011
However, this is very inflexible if the date format were ever to change.
Try this 'un:
preg_match('/(\d?\d [A-Za-z]+ \d\d\d\d) at (\d\d\:\d\d)/', $editdate, $matches);
print_r($matches);
$date = $matches[1];
$time = $matches[2];
I THINK that'll work in all cases (though it is pretty ugly).... :)
This might be the pattern that does the trick:
([0-9]){1}([0-9]){0,1}(\s.*\s)([0-9]){4}
Search for 1 digit then there might be another, followed by a space and character, a space and 4 digits for the year.
What is the RegEx pattern for DateTime (2008-09-01 12:35:45 ) ?
I get this error:
No ending delimiter '^' found
Using:
preg_match('(?n:^(?=\d)((?<day>31(?!(.0?[2469]|11))|30(?!.0?2)|29(?(.0?2)(?=.{3,4}(1[6-9]|[2-9]\d)(0[48]|[2468][048]|[13579][26])|(16|[2468][048]|[3579][26])00))|0?[1-9]|1\d|2[0-8])(?<sep>[/.-])(?<month>0?[1-9]|1[012])\2(?<year>(1[6-9]|[2-9]\d)\d{2})(?:(?=\x20\d)\x20|$))?(?<time>((0?[1-9]|1[012])(:[0-5]\d){0,2}(?i:\ [AP]M))|([01]\d|2[0-3])(:[0-5]\d){1,2})?$)', '2008-09-01 12:35:45');
Gives this error:
Warning: preg_match() [function.preg-match]: Compilation failed: nothing to repeat at offset 0 in E:\www\index.php on line 19
#Espo: I just have to say that regex is incredible. I'd hate to have to write the code that did something useful with the matches, such as if you wanted to actually find out what date and time the user typed.
It seems like Tom's solution would be more tenable, as it is about a zillion times simpler and with the addition of some parentheses you can easily get at the values the user typed:
(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})
If you're using perl, then you can get the values out with something like this:
$year = $1;
$month = $2;
$day = $3;
$hour = $4;
$minute = $5;
$second = $6;
Other languages will have a similar capability. Note that you will need to make some minor mods to the regex if you want to accept values such as single-digit months.
A simple version that will work for the format mentioned, but not all the others as per #Espos:
(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})
http://regexlib.com/REDetails.aspx?regexp_id=610
^(?=\d)(?:(?:31(?!.(?:0?[2469]|11))|(?:30|29)(?!.0?2)|29(?=.0?2.(?:(?:(?:1[6-9]|[2-9]\d)?(?:0[48]|[2468][048]|[13579][26])|(?:(?:16|[2468][048]|[3579][26])00)))(?:\x20|$))|(?:2[0-8]|1\d|0?[1-9]))([-./])(?:1[012]|0?[1-9])\1(?:1[6-9]|[2-9]\d)?\d\d(?:(?=\x20\d)\x20|$))?(((0?[1-9]|1[012])(:[0-5]\d){0,2}(\x20[AP]M))|([01]\d|2[0-3])(:[0-5]\d){1,2})?$
This RE validates both dates and/or
times patterns. Days in Feb. are also
validated for Leap years. Dates: in
dd/mm/yyyy or d/m/yy format between
1/1/1600 - 31/12/9999. Leading zeroes
are optional. Date separators can be
either matching dashes(-), slashes(/)
or periods(.) Times: in the hh:MM:ss
AM/PM 12 hour format (12:00 AM -
11:59:59 PM) or hh:MM:ss military time
format (00:00:00 - 23:59:59). The 12
hour time format: 1) may have a
leading zero for the hour. 2) Minutes
and seconds are optional for the 12
hour format 3) AM or PM is required
and case sensitive. Military time 1)
must have a leading zero for all hours
less than 10. 2) Minutes are
manditory. 3) seconds are optional.
Datetimes: combination of the above
formats. A date first then a time
separated by a space. ex) dd/mm/yyyy
hh:MM:ss
Edit: Make sure you copy the RegEx from the regexlib.com website as StackOverflow sometimes removes/destroys special chars.
$date = "2014-04-01 12:00:00";
preg_match('/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/',$date, $matches);
print_r($matches);
$matches will be:
Array (
[0] => 2014-04-01 12:00:00
[1] => 2014
[2] => 04
[3] => 01
[4] => 12
[5] => 00
[6] => 00
)
An easy way to break up a datetime formated string.
^([2][0]\d{2}\/([0]\d|[1][0-2])\/([0-2]\d|[3][0-1]))$|^([2][0]\d{2}\/([0]\d|[1][0-2])\/([0-2]\d|[3][0-1])\s([0-1]\d|[2][0-3])\:[0-5]\d\:[0-5]\d)$
regarding to Imran answer from Sep 1th 2008 at 12:33
there is a missing : in the pattern
the correct patterns are
preg_match('/\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/', '2008-09-01 12:35:45', $m1);
print_r( $m1 );
preg_match('/\d{4}-\d{2}-\d{2} \d{1,2}:\d{2}:\d{2}/', '2008-09-01 12:35:45', $m2);
print_r( $m2 );
preg_match('/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/', '2008-09-01 12:35:45', $m3);
print_r( $m3 );
this returns
Array ( [0] => 2008-09-01 12:35:45 )
Array ( [0] => 2008-09-01 12:35:45 )
Array ( [0] => 2008-09-01 12:35:45 )
Adding to #Greg Hewgill answer: if you want to be able to match both date-time and only date, you can make the "time" part of the regex optional:
(\d{4})-(\d{2})-(\d{2})( (\d{2}):(\d{2}):(\d{2}))?
this way you will match both 2008-09-01 12:35:42 and 2008-09-01
simple regex datetime with validation
^(\d{4})-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01]) ([01][0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9])$
but it can't validation month which not include 31day (ex. 2022-11-31, 2022-02-30)
Here is my solution:
/^(2[0-9]{3})-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01]) (0[0-9]|1[0-9]|2[0123])\:([012345][0-9])\:([012345][0-9])$/u
I have modified the regex pattern from http://regexlib.com/REDetails.aspx?regexp_id=610. The following pattern should match your case.
^(?=\d)(?:(?:1[6-9]|[2-9]\d)?\d\d([-.\/])(?:1[012]|0?[1-9])\1(?:31(?<!.(?:0[2469]|11))|(?:30|29)(?<!.02)|29(?=.0?2.(?:(?:(?:1[6-9]|[2-9]\d)?(?:0[48]|[2468][048]|[13579][26])|(?:(?:16|[2468][048]|[3579][26])00)))(?:\x20|$))|(?:2[0-8]|1\d|0?[1-9]))(?:(?=\x20\d)\x20|$))?(((0?[1-9]|1[012])(:[0-5]\d){0,2}(\x20[AP]M))|([01]\d|2[0-3])(:[0-5]\d){1,2})?$
YYYY-MM-DD HH:MM:SS
This is my soloution:
[1-9][0-9][0-9][0-9]-(0[1-9]|1[0-2])-(0[1-9]|1[0-9]|2[0-9]|3[0-1])
PHP preg functions needs your regex to be wrapped with a delimiter character, which can be any character. You can't use this delimiter character without escaping inside the regex. This should work (here the delimiter character is /):
preg_match('/\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/', '2008-09-01 12:35:45');
// or this, to allow matching 0:00:00 time too.
preg_match('/\d{4}-\d{2}-\d{2} \d{1,2}:\d{2}:\d{2}/', '2008-09-01 12:35:45');
If you need to match lines that contain only datetime, add ^ and $ at the beginning and end of the regex.
preg_match('/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/', '2008-09-01 12:35:45');
Link to PHP Manual's preg_match()
Here is my solution:
[12]\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01]) ([01][0-9]|2[0-3]):[0-5]\d
Debuggex Demo
https://regex101.com/r/lbthaT/4
Here is a simplified version (originated from Espo's answer). It checks the correctness of date (even leap year), and hh:mm:ss is optional
Examples that work:
- 31/12/2003 11:59:59
- 29-2-2004
^(?=\d)(?:(?:31(?!.(?:0?[2469]|11))|(?:30|29)(?!.0?2)|29(?=.0?2.(?:(?:(?:1[6-9]|[2-9]\d)?(?:0[48]|[2468][048]|[13579][26])|(?:(?:16|[2468][048]|[3579][26])00)))(?:\x20|$))|(?:2[0-8]|1\d|0?[1-9]))([-./])(?:1[012]|0?[1-9])\1(?:1[6-9]|[2-9]\d)?\d\d(?:(?=\x20\d)\x20|$))(|([01]\d|2[0-3])(:[0-5]\d){1,2})?$