简体   繁体   中英

Validate a xs:duration using a regular expression in Javascript

I'm trying to validate a xs:duration and then convert it to seconds. At this time, this is what i have:

/P^([-])?(([\d.]*)Y)?(([\d.]*)M)?(([\d.]*)D)?T?(([\d.]*)H)?(([\d.]*)M)?(([\d.]*)S)?/

However, is not rejecting these invalid values (taken from here ):

  • P-20M the minus sign must appear first
  • P20MT no time items are present, so "T" must not be present
  • P1YM5D no value is specified for months, so "M" must not be present

What am I missing?

I've found a similar question here , but that regex only works in Python.

You are missing several points, which are easily addressed by looking at the descriptions of the failure cases. The following regular expression works for all the cases (and failure cases), see Regex 101

^(-?)P(?=.)((\d+)Y)?((\d+)M)?((\d+)D)?(T(?=.)((\d+)H)?((\d+)M)?(\d*(\.\d+)?S)?)?$

First of all, look at P15.5Y only the seconds can be expressed as a decimal . You use [\\d.]* everywhere, which allows one or more digit or dots everywhere. But only the seconds are allowed to have a single dot, and that dot needs to be followed by a digit. So, change the seconds to (\\d*(\\.\\d+)?S) and all the others to (\\d+Y) (and so on).

Also, the string needs to start with an optional - , and then the P , so use that:

^-?P

Then, there must be something after the P , just use a lookahead assertion for that:

(?=.)

Then, there come Y , M and D , as discussed already.

If there is a time component, there must come a T now, so make sure we have a T if anything else comes:

(T(?=.))

... and only if we had a T , we are allowed to have H , M or S :

(T(?=.)(\d+H)?(\d+M)?(\d*(\.\d+)?S)?)

The lookahead assertion ensures that we will find something, and the rest captures the HMS part.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM