PHP/regex: matching/replacing 24-hour times - php

How can I take a line like this:
Digital Presentation (10:45), (11:30), 12:00, 12:40, 13:20, 14:00, 14:40, 15:20, 16:00, 16:40, 17:20, 18:00, 18:40, 19:20, 20:00, 20:40, 21:20, 22:00, 22:40, 23:10, 23:40.
And match all the 24 hour times so I can convert to a more human readable format using date()?
Also I want to match times in the 24:00-24:59 range too
Thanks!

You could use a regular expression like the following, which allows values from 00:00 through to 24:59 inclusive.
(?:[01][0-9]|2[0-4]):[0-5][0-9]
You seem to know what you're doing, so I'll only give a brief example without converting the times into date strings.
$times = array();
if (preg_match_all('/(?:[01][0-9]|2[0-4]):[0-5][0-9]/', $subject, $matches)) {
$times = $matches[0];
}
print_r($times);
If the subject string has the chance of values like 1234:5678, which would result in false positives with the above regex, then you could wrap the pattern in \b or some other assertion to make sure the time formatted numbers lie on their own.

It's probably easiest to match something like (\d{2}):(\d{2}) (preg syntax), then convert both submatches to an integer and check whether they are in the correct range.

preg_match_all('/([0-2][\d]):(\d{2})/', $string, $matches)
Now $matches[0] array contains all human readable times.
If you wish to print those along with specific date, feed each time through strtotime() function, like this
foreach ($matches[0] as $time) echo date('Y-m-d H:i:s', strtotime($time));

Related

How to validate dates without leading zero on day and month?

I need to validate a precise date format in php.
In my case the optimum date format should be: e.g. 1/1/2017 (without leading zeros) and the code should allow me to avoid the rest of date's format.
The following code is what i wrote but with no result:
if(preg_match("/([1-9]|[1-2][0-9]|3[0-1]-([1-9]|1[0-2])-^[0-9]{4})$/", $date){
// insert into etc. etc....
}else{
// update etc. etc....
}
The problem is that the code doesn't properly validate the date; it accepts every kind of date format.
I noticed that the OP's submitted answer was not bulletproof, so I started to research some of the functions mentioned in the comments under the question and some of my own thoughts.
I agree with apokryfos in that using regex to validate a date expression is not best practice. A pure regex solution is going to be an increasingly verbose and decreasingly comprehensible pattern because it will have to factor leap years both in the past and future. For this reason, I've investigated a few date functions that php has on offer.
date_parse_from_format() as suggested by Alex Howansky. Unfortunately, it will not be a stand-alone solution for this case because the format parameter obeys the syntax/rules of DateTime::createFromFormat():
See how d and j are grouped together, as are m and n. Consequently, this function will catch invalid dates, but not the unwanted leading zeros.
strptime() as suggested by Casimir et Hippolyte. This function affords matching days without leading zeros using %e. This function does not have a character that matches non-zero-leading month numbers. Furthermore, there can be hiccups with this function bases on the operating system.
check_date() seems like a logical choice, but again it will not flinch at zero-led numbers. Furthermore, this function requires a bit more data preparation than the others, because it requires the month, day, and year values to be individualized.
if(!DateTime::createFromFormat('j/n/Y', $date)) suggested by deceze regarding a slightly different scenario will not work in this case. createFromFormat() will go to great lengths to construct a valid date -- even a string like 99/99/9999 will make it through.
In an attempt to create the most concise expression, here is what I can offer as a seemingly bulletproof solution using a DateTime class:
if (($d=DateTime::createFromFormat('n/j/Y',$date)) && $date==$d->format('n/j/Y')){
// valid
}else{
// invalid
}
strtotime() can be used with a single condition for this case because the OP's date format uses slashes as a delimiter and this function will correctly parse the date expression "American-style".
This seems to be the simplest way to check for a valid date without leading zeros: Demo Link
if(date('n/j/Y',strtotime($date))==$date){
// valid
}else{
// invalid
}
If you are dealing with datetime expressions and don't wish to check the time portion, you can call this line before conditional line:
$date = explode(' ', $date)[0]; // create an array of two elements: date and time, then only access date
Demo Link
or
$date = strstr($date, ' ', true); // extract substring prior to first space
you can use with Carbon
$date->format('j')
Your date delimiter is / and not -, so add \/ to regex for /. And use ^ at the start of regex:
if(preg_match("/^([1-9]|[1-2][0-9]|3[0-1])\/([1-9]|1[0-2])\/([0-9]{4})$/", $date){
After several hours finally i found the correct answer. The correct pattern for php is to use single quote (') and not the double quote (") e.g.:
preg_match('/^([1-9]|[1-2][0-9]|3[0-1])\/([1-9]|1[0-2])\/([0-9]{4})/',$date)
this works fine for me... Thanks everyone especially to #Mohammad Hamedani 'cause the expression was correct but the f******g quote makes me gone crazy

Extract date from string in format "DD MMM YYYY"

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.

How to extract year using preg_match

I have textarea where users enter details, I want to extract year from the textarea. The problem is users enter year in different ways.
some users input dates as 1999 or '99 or september 99. how can I use a single regex string to extract year.
This should work for extracting the mentioned dates out of text:
preg_match_all('/(^|\s+)(\d{4}|\'\d{2}|(january|february|march|april|may|june|july|august|september|october|november|december) \d{2})(\s+|$)/i', $text, $matches);
This came to my mind, too (it gives the user a little more freedom):
preg_match_all('/(^|\s+)((january|february|march|april|may|june|july|august|september|october|november|december|jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)?(\s|\s?\')(\d{2}|\d{4}))(\s+|$)/i', $text, $matches);
All of the above would be easier when parsed with multiple expressions. Why do you need a single one?
If you simply want to parse a string that contains nothing else than this, you should use PHP's strtotime()-function.
\b\d\d(?:\d\d)?\b
will match a two- or four-digit number. So if your string only contains year numbers, that should be enough.
if (preg_match('/\b\d\d(?:\d\d)?\b/', $subject, $regs)) {
$result = $regs[0];
}
You can try to use strtotime:
strtotime — Parse about any English textual datetime description into a Unix timestamp
date('Y', strtotime($userinput));
[. -]((?:\d\d|')\d\d)$
Extract only digits from your string :
/\b(\d+)\b/

Any Elegant Ideas on how to parse this Dataset?

I'm using PHP 5.3 to receive a Dataset from a web service call that brings back information on one or many transactions. Each transaction's return values are delimited by a pipe (|), and beginning/ending of a transaction is delimited by a space.
2109695|49658|25446|4|NSF|2010-11-24 13:34:00Z 2110314|45276|26311|4|NSF|2010-11-24 13:34:00Z 2110311|52117|26308|4|NSF|2010-11-24 13:34:00Z (etc)
Doing a simple split on space doesn't work because of the space in the datetime stamp. I know regex well enough to know that there are always different ways to break this down, so I thought getting a few expert opinions would help me come up with the most airtight regex.
If each timestamp is going to have a Z at the end you can use positive lookbehind assertion to split on space only if it's preceded by a Z as:
$transaction = preg_split('/(?<=Z) /',$input);
Once you get the transactions, you can split them on | to get the individual parts.
Codepad link
Note that if your data has a Z followed a space anywhere else other than the timestamp, the above logic will fail. To overcome than you can split on space only if it's preceded by a timestamp pattern as:
$transaction = preg_split('/(?<=\d\d:\d\d:\d\dZ) /',$input);
As others have said, if you know for sure that there will be no Z characters anywhere other than in the date, you could just do:
$records = explode('Z', $data);
But if you have them elsewhere, you'll need to do something a bit fancier.
$regex = '#(?<=\d{2}:\d{2}:\d{2}Z)\s#i';
$records = preg_split($regex, $data, -1, PREG_SPLIT_NO_EMPTY);
Basically, that record looks for the time portion (00:00:00) followed by a Z. Then it splits on the following white-space character...
Each timestamp is going to have a Z at the end so explode it by 'Z '. You don't need a regular expression. There's no chance that the date has a Z after it only the time.
example
Use explode('|', $data) function

PHP: Time validation RegEx?

I am using following regex to validate date in format dd/mm/yyyy in php:
preg_match("/([0-9]{2})\/([0-9]{2})\/([0-9]{4})/", $e_startdate, $matches)
But what will be the regex to validate time in the format 10:20 PM or AM. I want a regex which will validate following format for me.
<number><number><colon><number><number><space><AM or PM>
Thanks
You can use the regex:
(0[0-9]|1[0-2]):[0-5][0-9] [AP]M
The following should validate the format you requested:
preg_match("/(\d{2}):(\d{2}) (AM|PM)/", $e_startdate, $matches);
Note that this is not necessarily a valid time. You could enter stuff like 32:62 AM. You need something like this for time validation:
preg_match("/(0?\d|1[0-2]):(0\d|[0-5]\d) (AM|PM)/i", $e_startdate, $matches);
Mind to match the whole thing case-insensitive (like i did in the second example). Otherwise lowercase am, pm, etc. are not going to work.
Regular Expression:
(([0-1][0-9])|([2][0-3])):([0-5][0-9]):([0-5][0-9])
Validates time in MySQL time format. 24 hour time colon separated hours:minutes:seconds hh:mm:ss
Matches: 09:30:00 | 17:45:20 | 23:59:59
Non-Matches: 24:00:00
/\d{2}:\d{2} (AM|PM)/
I started with elusive's answer, but needed a bit more flexibility. This one makes the minutes optional, as well as the space before AM/PM
/(0?\d|1[0-2])(:(0\d|[0-5]\d))?[ ]?(A|P)M/i

Categories