Regex for ISO 8601 durations

被刻印的时光 ゝ 提交于 2019-11-30 13:28:20

If you have almost all parts optional, but you want to make sure there is something else after P or T, you can make use of look-aheads:

^P(?=\d+[YMWD])(\d+Y)?(\d+M)?(\d+W)?(\d+D)?(T(?=\d+[HMS])(\d+H)?(\d+M)?(\d+S)?)?$
  ^^^^^^^^^^^^                               ^^^^^^^^^^^^

They require a sequence of digits followed by a letter from the specified set to appear right after the preceding pattern.

See demo

UPDATE

If P can be "empty", use

^P(?!$)(\d+Y)?(\d+M)?(\d+W)?(\d+D)?(T(?=\d+[HMS])(\d+H)?(\d+M)?(\d+S)?)?$

See another demo. Here, (?!$) makes sure the string is not equal to P, and there must be some other symbols on the right.

Or, as @UlugbekUmirov suggests, it is enough to just use T(?=\d) (since all the optional parts start with a digit):

^P(?!$)(\d+Y)?(\d+M)?(\d+W)?(\d+D)?(T(?=\d)(\d+H)?(\d+M)?(\d+S)?)?$

UPDATE 2

If the numbers can be both float or integers, add (?:\.\d+)? after each \d+. Here is an updated pattern from Update 1:

^P(?!$)(\d+(?:\.\d+)?Y)?(\d+(?:\.\d+)?M)?(\d+(?:\.\d+)?W)?(\d+(?:\.\d+)?D)?(T(?=\d)(\d+(?:\.\d+)?H)?(\d+(?:\.\d+)?M)?(\d+(?:\.\d+)?S)?)?$

The answers above don't include the situation of a decimal fraction (see here for details). The decimal fraction can occur on the last element. The following regex includes decimal fraction:

^P(?!$)((\d+Y)|(\d+\.\d+Y$))?((\d+M)|(\d+\.\d+M$))?((\d+W)|(\d+\.\d+W$))?((\d+D)|(\d+\.\d+D$))?(T(?=\d)((\d+H)|(\d+\.\d+H$))?((\d+M)|(\d+\.\d+M$))?(\d+(\.\d+)?S)?)??$

See here for tests.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!