Reputation: 2285
I'm trying to build a regex to match timesheet hours entry where user enters his hours in the format 20h 50m
.
In this format, the user can either enter hours only 20h
, or minutes only 50m
or both hours and minutes 20h 50m
.
Sample matches
45m
1h
2h 45m
The numbers can be anything other than 20
or 50
.
I came up with this regex ((([0-9]+h)\s([0-9]+m))|([0-9]+h)|([0-9]+m)){1}
, which is long and I'm trying to reduce it.
So I tried different solution: ((\d+h)?([\s]*(\d+m))?)
https://regex101.com/r/ZEBsle/1/ .But the issue with this solution is that it matches empty strings and doesn't match patterns like 2h 45m
.
How can I modify the last regex so it can match the following formats?
45m
1h
2h 45m
Upvotes: 3
Views: 125
Reputation: 163217
To match all variations, you could use
\b(?:\d+h(?: \d+m)?|\d+m)\b
Explanation
\b
A word boundary(?:
Non capture group
\d+h
Match 1+ digits and h
(?: \d+m)?
Optionally match a minute part|
Or\d+m
Match 1+ digits and m
)
Close group\b
A word boundaryIf you want to match hours and minutes in that order, you might use anchors ^
and $
^(?:\d+h(?: \d+m)?|\d+m)$
Upvotes: 0
Reputation: 206028
Here's my take at it:
/(?<=\b)\d+h \d+m|\d+[hm](?=\b)/g
const str = `45m
1h
4h 35m
some text before 2h 45m and after
travelled 66miles
2m 45h this one are inversed, so treat them separately
245m`;
const times = str.match(/(?<=\b)\d+h \d+m|\d+[hm](?=\b)/g);
console.log(times);
Upvotes: 1