const regex = /(?(DEFINE)
(?# Date )
(?# Day ranges )
(?<d_day28>0[1-9]|1\d|2[0-8])
(?<d_day29>0[1-9]|1\d|2\d)
(?<d_day30>0[1-9]|1\d|2\d|30)
(?<d_day31>0[1-9]|1\d|2\d|3[01])
(?# Month specifications )
(?<d_month28>02)
(?<d_month29>02)
(?<d_month30>0[469]|11)
(?<d_month31>0[13578]|1[02])
(?# Year specifications )
(?<d_year>\d+)
(?<d_yearLeap>(?:\d*?(?:(?:(?!00)[02468][048]|[13579][26])|(?:(?:[02468][048]|[13579][26])00))|[48]00|[48])(?=\D|\b))
(?# Valid date formats )
(?<d_format>
(?&d_day28)\/(?&d_month28)\/(?&d_year)|
(?&d_day29)\/(?&d_month29)\/(?&d_yearLeap)|
(?&d_day30)\/(?&d_month30)\/(?&d_year)|
(?&d_day31)\/(?&d_month31)\/(?&d_year)
)
(?# Time )
(?# Time properties )
(?<t_period12>(?i)[ap]m|[ap]\.m\.(?-i))
(?# Hours )
(?<t_hours12>0\d|1[01])
(?<t_hours24>[01]\d|2[0-3])
(?# Minutes )
(?<t_minutes>[0-5]\d)
(?# Seconds )
(?<t_seconds>[0-5]\d)
(?# Milliseconds )
(?<t_milliseconds>\d{3})
(?# Valid time formats )
(?<t_format>
(?&t_hours12):(?&t_minutes):(?&t_seconds)(?:\.(?&t_milliseconds))?\ ?(?&t_period12)|
(?&t_hours24):(?&t_minutes):(?&t_seconds)(?:\.(?&t_milliseconds))?
)
(?# Datetime )
(?<dt_format>(?&d_format)\ (?&t_format))
)
\b(?&dt_format)\b/gm;
// Alternative syntax using RegExp constructor
// const regex = new RegExp('(?(DEFINE)
(?# Date )
(?# Day ranges )
(?<d_day28>0[1-9]|1\\d|2[0-8])
(?<d_day29>0[1-9]|1\\d|2\\d)
(?<d_day30>0[1-9]|1\\d|2\\d|30)
(?<d_day31>0[1-9]|1\\d|2\\d|3[01])
(?# Month specifications )
(?<d_month28>02)
(?<d_month29>02)
(?<d_month30>0[469]|11)
(?<d_month31>0[13578]|1[02])
(?# Year specifications )
(?<d_year>\\d+)
(?<d_yearLeap>(?:\\d*?(?:(?:(?!00)[02468][048]|[13579][26])|(?:(?:[02468][048]|[13579][26])00))|[48]00|[48])(?=\\D|\\b))
(?# Valid date formats )
(?<d_format>
(?&d_day28)\\\/(?&d_month28)\\\/(?&d_year)|
(?&d_day29)\\\/(?&d_month29)\\\/(?&d_yearLeap)|
(?&d_day30)\\\/(?&d_month30)\\\/(?&d_year)|
(?&d_day31)\\\/(?&d_month31)\\\/(?&d_year)
)
(?# Time )
(?# Time properties )
(?<t_period12>(?i)[ap]m|[ap]\\.m\\.(?-i))
(?# Hours )
(?<t_hours12>0\\d|1[01])
(?<t_hours24>[01]\\d|2[0-3])
(?# Minutes )
(?<t_minutes>[0-5]\\d)
(?# Seconds )
(?<t_seconds>[0-5]\\d)
(?# Milliseconds )
(?<t_milliseconds>\\d{3})
(?# Valid time formats )
(?<t_format>
(?&t_hours12):(?&t_minutes):(?&t_seconds)(?:\\.(?&t_milliseconds))?\\ ?(?&t_period12)|
(?&t_hours24):(?&t_minutes):(?&t_seconds)(?:\\.(?&t_milliseconds))?
)
(?# Datetime )
(?<dt_format>(?&d_format)\\ (?&t_format))
)
\\b(?&dt_format)\\b', 'gm')
const str = `29/02/2016 23:10:59 - valid
29/02/2017 23:10:59 - invalid (not leap year)
30/03/2016 23:10:59 - valid`;
// Reset `lastIndex` if this regex is defined globally
// regex.lastIndex = 0;
let m;
while ((m = regex.exec(str)) !== null) {
// This is necessary to avoid infinite loops with zero-width matches
if (m.index === regex.lastIndex) {
regex.lastIndex++;
}
// The result can be accessed through the `m`-variable.
m.forEach((match, groupIndex) => {
console.log(`Found match, group ${groupIndex}: ${match}`);
});
}
Please keep in mind that these code samples are automatically generated and are not guaranteed to work. If you find any syntax errors, feel free to submit a bug report. For a full regex reference for JavaScript, please visit: https://developer.mozilla.org/en/docs/Web/JavaScript/Guide/Regular_Expressions