Javascript regex to replace part of substring not working as expected?

Javascript regex to replace part of substring not working as expected?

Problem Description:

I’m working with times and meridiems.

I could have '2:0 a. m.' or '2:0 am' or '3:0 p. m.' or '3:0 pm'
Basically what I’m trying to do is transform the first in the second when it happens.

My attempts:

console.info('2:0 a. m.'.replace(/(.*?s)([ampAMP]*?)/, "$1")); // 2:0 a. m.

This one I really don’t understand…

'2:0 a. m.'.replace(/(.*?s)([ampAMP]).*?([ampAMP])/, "$1"); // 2:0 .

This one works but looks weird, not sure it’s the best way

'2:0 a. m.'.replace(/(.*?s)([ampAMP]).*?([ampAMP]).*?$/, "$1$2$3");

I was barely able to remove the meridiem from the time, but how can I replace all characters not matching [aAmMpP] just AFTER the first space?

Solution – 1

For now after many attempts this works, alghough not very clean

let time = "02:00 p. m.";
time = time.replace(/(.*?s)([ampAMP]).*?([ampAMP]).*?$/, "$1$2$3");
console.log(time);

with the selected answer I had

let time = "02:00 a. m.";
time = time.replace(/b(d{1,2})s*:s*(d{1,2})s*([ap]).s*m./i, "$1:$2 $3m");
console.log(time);

but by the way I ended up doing this:

let time = "02:00 a. m.";
time = time .replace(/.s*/g, "");
console.log(time);

because although it was good, I had performance issues.

hope it helps

Solution – 2

If you want to match am or pm, using [ampAMP] matches only a single character. If you use it twice, then you would allow for mm which is not a valid format.

You could make the pattern match more variations and capture what you want to keep. Then in the replacement use the capture groups to create the format that you want.

If the dots are mandatory:

b(d{1,2})s*:s*(d{1,2})s*([ap]).s*m.
  • b A word boundary
  • (d{1,2}) Capture group 1, match 1-2 digits
  • s*:s* Math : between optional whitespace chars
  • (d{1,2}) Capture group 2, match 1-2 digits
  • s* Match optional whitespace chars
  • ([ap]) Capture group 3, match either a or b
  • .s*m. Match . optional whitespace chars m and .

See a regex demo.

In the replacement use (as you already know that you have matched the m char)

$1:$2 $3m
const regex = /b(d{1,2})s*:s*(d{1,2})s*([ap]).s*m./;
[
  "2:0 a. m.",
  "2:0 p. m.",
  "3:0 p. m.",
  "3:0p.m.",
  "2:0 am"
].forEach(s => console.log(s.replace(regex, "$1:$2 $3m")));

A bit more time like specific pattern, allowing an optional digit 0-5 for the seconds part:

b([0-1]?[0-9]|2[0-3])s*:s*([0-5]?[0-9])s*([ap]).s*m.

Regex demo

Rate this post
We use cookies in order to give you the best possible experience on our website. By continuing to use this site, you agree to our use of cookies.
Accept
Reject