Regex pattern for HH:MM:SS time string - regex

I want to parse a hh:mm:ss string.
A simple one is ([0-1]?\d|2[0-3]):([0-5]?\d):([0-5]?\d) which expects 2:3:24 or 02:03:24 string.
I want to take it a step further and pass the validation even in cases like
if you enter just 56, it should be pass, as 56 can be considered as 56 secs [SS]
if you enter 2:3 or 02:03 or 02:3 or 2:03 it should pass. 2 minutes and 3 seconds [MM:SS]
If you enter 20:30:12 pass with 20 hrs, 30 minutes and 12 secs [HH:MM:SS]
if you enter 78:12 , do not pass 78 minutes is wrong....
Basically, if one ":" is found, consider number before ":" as MM and number after ":" as SS
. If two ":" are found consider as HH:MM:SS
I came up with this pattern.
(^([0-1]?\d|2[0-3]):([0-5]?\d):([0-5]?\d)$)|(^([0-5]?\d):([0-5]?\d)$)|(^[0-5]?\d$)
It seems to be working fine. I wanted to know any other simpler regular expression, that can do the job.

^(?:(?:([01]?\d|2[0-3]):)?([0-5]?\d):)?([0-5]?\d)$
Explanation:
^ # Start of string
(?: # Try to match...
(?: # Try to match...
([01]?\d|2[0-3]): # HH:
)? # (optionally).
([0-5]?\d): # MM: (required)
)? # (entire group optional, so either HH:MM:, MM: or nothing)
([0-5]?\d) # SS (required)
$ # End of string

#Tim Pietzcker covers the OP's requirement for a HH:MM:SS parser where SS was mandatory, i.e.
HH:MM:SS
MM:SS
SS
If you permit me to deviate from the OP's requirement for a bit, and consider a case where HH is mandatory, i.e.
HH
HH:MM
HH:MM:SS
The regex I came up with was:
^([0-1]?\d|2[0-3])(?::([0-5]?\d))?(?::([0-5]?\d))?$
Let's break it down:
([0-1]?\d|2[0-3]) - matches for hours
(?::([0-5]?\d))? - optionally matches for minutes
(?::([0-5]?\d))? - optionally matches for seconds

Related

Regex to check MM:SS [duplicate]

I'm using some validation in Google Sheets but I need the total minutes and seconds in the following format for each dive.
E.g.
42:38 (42 minutes, 38 seconds)
62:35
85:26
I do not want hours to be an option; I only want to work with minutes and seconds, as this is then converted in the database separately.
I have seen the below on another form but have no idea where to start with regex:
^(?:(?:([01]?\d|2[0-3]):)?([0-5]?\d):)?([0-5]?\d)$
This gives HH:MM:SS (with HH being optional); I have tried to have a play around with it but to no avail.
You can use
^(\d+):([0-5]?\d)$
Or, if \d is not supported as in POSIX ERE:
^([0-9]+):([0-5]?[0-9])$
See the regex demo. Details:
^ - start of string
(\d+) - Group 1: one or more digits
: - a colon
([0-5]?\d) - Group 2: a digit from 0 to 5 and then one digit
$ - end of string.

Regex MM:SS, unlimited minutes (no hours)

I'm using some validation in Google Sheets but I need the total minutes and seconds in the following format for each dive.
E.g.
42:38 (42 minutes, 38 seconds)
62:35
85:26
I do not want hours to be an option; I only want to work with minutes and seconds, as this is then converted in the database separately.
I have seen the below on another form but have no idea where to start with regex:
^(?:(?:([01]?\d|2[0-3]):)?([0-5]?\d):)?([0-5]?\d)$
This gives HH:MM:SS (with HH being optional); I have tried to have a play around with it but to no avail.
You can use
^(\d+):([0-5]?\d)$
Or, if \d is not supported as in POSIX ERE:
^([0-9]+):([0-5]?[0-9])$
See the regex demo. Details:
^ - start of string
(\d+) - Group 1: one or more digits
: - a colon
([0-5]?\d) - Group 2: a digit from 0 to 5 and then one digit
$ - end of string.

regExp for HH:mm format including intermediate value

I am trying to compose a regExp that accepts HH:mm time formats, but also accepts all of the intermediate values:
e.g. all of these are accepted:
0
1
12
12:
12:3
12:30
1:
1:3
1:30
For now, I came up with this: ^([\d]{1,2}):?([\d]{1,2})?$
But this accepts any numeric 1/2 digit values for hours and minutes (e.g. 25:66 is acceptable)
So I came relatively close to my goal, but I need to filter out values x>24 from the hours, and x>60 from the minutes?
Try this:
^((?:[01][0-9]?)|(?:2[0-4]?)|(?:[3-9]))(?::((?:[0-5][0-9]?)|(?:60))|:)?$
NOTE:
This accepts 24 for HH and 60 for MM as stated in your question:
but I need to filter out values x>24 from the hours, and x>60 from the minutes?
Thus ff. are accepted:
0
1
12
12:
12:3
12:30
1:
1:3
1:30
1:60
24:60
24:00
00:60
and below are not accepted:
25:30
00:61
Regex DEMO 1
If you want to exclude 24 HH and 60 MM, try this instead:
^((?:[01]\d?)|(?:2[0-3]?))(?::|(?::([0-5][0-9]?)))?$
Regex DEMO 2
Groups (applies to both cases):
\1 = HH
\2 = MM
You are looking for
^(?:[01]\d?|2[0-3]?)(?::(?:[0-5]\d?)?)?$
See the regex demo and the regex graph:
Details:
^ - start of string
(?:[01]\d?|2[0-3]?) - either a 0 or 1 followed by an optional digit, or a 2 followed with an optional 0, 1, 2 or 3
(?::(?:[0-5]\d?)?)? - an optional sequence of patterns:
: - a colon
(?:[0-5]\d?)? - an optional sequence of patterns:
[0-5] - a digit from 1 to 5
\d? - an optional digit
$ - end of string.

Complex Regex finding date and time

Is there someone to help me with the following:
I'm trying to find specific date and time strings in a text (to be used within VBA Word).
Currently working with the following RegEx string:
(?:([0-9]{1,2})[ |-])?(?:(jan(?:uari)?|feb(?:ruari)?|m(?:aa)?rt|apr(?:il)?|mei|jun(?:i)?|jul(?:i)?|aug(?:ustus)?|sep(?:tember|t)?|okt(?:ober)?|nov(?:ember)?|dec(?:ember)?))?(?: |-)?(?(3)(?: around | at | ))?(?:([0-9]{1,2}:[0-9]{1,2})?(?: uur| u|u)?)?
Tested output on following text:
date with around time: 26 sep 2016 around 09:00u
date with at time: 1 sep 2016 at 09:00 uur
date and time u: 1 sep 2018 09:00 u
time without date: 08:30 uur
date with time u: 1 sep 2016 at 09:00u
only time: 09:00
only month: jan
month and year: feb 2019
only day: 02
only day with '-': 2-
day and month: 2 jan
month year: jan 2018
date with '-': 2-feb-2018 09:00
other month: 01 sept 2016
full month: 1 september 2018
shortened year: jul '18
Rules:
a date followed by time is valid
a date followed by text 'around' or 'at', followed by time is valid
a date without day number is valid
a date without year is valid
a date, month only is not valid
a day, without month or year not valid
a date may contain dashes '-'
a year may be shortenend with ', like jun '18
month name can be short or long
full match includes ' uur' or 'u' (to highlight the text in ms-Word)
submatches text from capture are without prepending or trailing spaces
example at: [https://regex101.com/r/6CFgBP/1/]
Expected output (when using in VBA Word):
An regex Matches collection object in which each Match.SubMatches contains the individual items d, m, y, hh:mm from the capture groups in the regex search string.
So for example 1: the Submatches (or capture groups) contains values: '26' ','sep','2016','09:00'
The RegEx works fine, but some false-positives need to be excluded:
In case there is a day without month/year, should be excluded from Regex (example 9 and 10)
In case there is a month without day, should be excluded (example 7)
(I was trying with som lookahead and reference \1 and ?(1), but was not able to get it running properly...)
Any advice highly appreciated!
As I understood, you require that each date/time part (day, month, year, hour
and minute) must be present.
So you should remove ? after relevant groups (they are not optional).
It is also a good practice to have each group captured as a relevant capturing group.
There is no need to write something like jun(?:i)?. It is enough
(and easier to read) when you write just juni? (the ? refers just
to preceding i).
Another hint: As the regex language contains \d char class, use just
it instead of [0-9] (the regex is shorter and easier to read.
Optional parts (at / around) should be an optional and non-capturing group.
Anything after the minute part is not needed in the regex.
So I propose a regex like below (for readability, I divided it into rows):
(\d{1,2})[ -](jan(?:uari)?|feb(?:ruari)?|m(?:aa)?rt|apr(?:il)?|mei|juni?
|juli?|aug(?:ustus)?|sep(?:tember|t)?|okt(?:ober)?|nov(?:ember)?|dec(?:ember)?)
[ -](\d{4}) (?:around |at )?(\d{1,2}:\d{1,2})
Details:
(\d{1,2}) - Day.
[ -] - A separator after the day (either a space or a minus).
(jan(?:uari)?|...dec(?:ember)?) - Month.
[ -] - A separator after the month.
(\d{4}) - year.
(?:around |at )? - Actually, 3 variants of a separator between year
and hour (space / around / at), note the space before (...)?.
(\d{1,2}:\d{1,2}) - Hour and minute.
It matches variants 1, 2, 3, 5 and 13.
All remaining fail to contain each required part, so they are not matched.
If you allow e.g. that the hour/minute part is optional, change the respective fragment
into:
( (?:around |at )?(\d{1,2}:\d{1,2}))?
i.e. surround the space/around/at / hour / minute part with ( and )?,
making this part an optional group. Then, variants 14 and 15 will also
be matched.
One more extension: If you also allow the hour/minute part alone,
add |(\d{1,2}:\d{1,2}) to the regex (all before is the first variant and
the added part is the second variant for just hour/minute.
Then, your variants No 4 and 6 will also be matched.
For a working example see https://regex101.com/r/33t1ps/1
Edit
Following your list of rules, I propose the following regex:
(\d{1,2}[ -])? - Day + separator, optional.
(jan(?:uari)?|...|dec(?:ember)?) - Month.
(?:[ -](\d{4}|'\d{2}))? - Separator + year (either 4 or 2 digits with "'").
( (?:around |at )?(\d{1,2}:\d{1,2}))? - Separator + hour/minute -
optional end of variant 1.
|(\d{1,2}:\d{1,2}) - Variant 2 - only hour and minute.
It does not match only your variants No 9 and 10.
For full regex, including also "uur" see https://regex101.com/r/33t1ps/3
Finally I found something that helps me using the month properly :-)
\b(?:([1-3]|[0-3]\d)[ |-](?'month'(?:[1-9]|\d[12])|(?:jan(?:uari)?|feb(?:ruari)?|m(?:aa)?rt|apr(?:il)?|mei|jun(?:i)?|jul(?:i)?|aug(?:ustus)?|sep(?:tember|t)?|okt(?:ober)?|nov(?:ember)?|dec(?:ember)?))?)?(?:(\g'month')[ |-]((?:19|20|\')(?:\d{2})))?\b(?: omstreeks | om | )?(?:(\d{1,2}[:]\d{2}(?: uur|u)?|[0-2]\d{3}(?: uur|u)))?\b
It uses a named constructor/subroutine. Found here:
https://www.regular-expressions.info/subroutine.html

String Split AND Replace

I am trying to replace a string based on the split portion. This string is a date, where the year should be formatted as a superscript.
Eg. Jan 24, 2014 needs to be split at 2014 then replaced with Jan 24, ^2014^ where 2014 is the superscript.
Example pseudo:
mydate.Split(" ", 2).Replace("^2014^")
But, instead of replacing the new split string, it should be the original (or copy of original). I can't just edit based on index because the formatting may not always be the same, at times the date may be expanded to January 24th, 2014 which would then break the traditional replace by index.
You can try
(?<=[A-Z][a-z]{2} \d{2}, )(\d{4})
Replaced with ^$1^ or ^\1^
Here is online demo and tested it on regexstorm
If you want to match January 24th, 2014 as well then try
([A-Z][a-z]{2,9} \d{2}[a-z]{0,2}, )(\d{4})
Replaced with $1^$2^
Here is demo
You can use a combination of lookarounds to achieve your result.
Regex.Replace(input, "(?<=\d{4})|(?=\d{4})", "^")
Explanation:
(?<= # look behind to see if there is:
\d{4} # digits (0-9) (4 times)
) # end of look-behind
| # OR
(?= # look ahead to see if there is:
\d{4} # digits (0-9) (4 times)
) # end of look-ahead
Live Demo
Normalize you date string by assigning it to a Date variable, then do the formatting from there.
Dim dt As Date = "Jan 24, 2014"
Dim s As String = dt.ToShortDateString.Replace("2014", "^2014^")
MsgBox(s)
' or '
s = dt.Month.ToString & "/" & dt.Day.ToString & "/^" & dt.Year.ToString & "^"
MsgBox(s)
IMO RegEx is write once code and is difficult to debug/maintain.