Home > Mobile >  Validating ISO 8601 Duration string with fractions
Validating ISO 8601 Duration string with fractions

Time:05-26

This might be a bit of a tricky one, I'm trying to come up with a regular expression to validate various given date intervals against the 8601 spec (https://en.wikipedia.org/wiki/ISO_8601#Durations). I have pretty much else all the cases working with the following regular expression:

^P(\d (?:[,.]\d )?Y)?(\d (?:[,.]\d )?M)?(\d (?:[,.]\d )?D)?(?:T(\d (?:[,.]\d )?H)?(\d (?:[,.]\d )?M)?(\d (?:[,.]\d )?S)?)?$

However the one place it falls down is in the aspect of the fractional unit only being allowed on the smallest supplied unit.

So for example:

P1DT1.5H is a valid string (The above regex technically allows this) P1.5DT1H is not a valid duration, as the hours are the smallest supplied unit. P1.5DT1.5H would also not be valid.

I've reached the end of my regex skills to try and figure out a way to incorporate this into the above. Anyone have any help or guidance on how this might be achived?

CodePudding user response:

Assuming the fractional part can only appear if there are no more digits to the right, you can use

^P(?!.*\d[,.]\d.*\d)(?!$)(\d (?:[,.]\d )?Y)?(\d (?:[,.]\d )?M)?(\d (?:[,.]\d )?W)?(\d (?:[,.]\d )?D)?(T(?=\d)(\d (?:[,.]\d )?H)?(\d (?:[,.]\d )?M)?(\d (?:[,.]\d )?S)?)?$

See the regex demo.

The (?!.*\d[,.]\d.*\d) negative lookahead fails the match if there is a number with a fractional part followed with another number anywhere in the string.

You can learn more about the pattern used here in the Regex for ISO 8601 durations post.

  • Related