正则表达式为ISO 8601持续时间

rin*_*t.6 8 regex dateinterval

我需要一个正则表达式来验证ISO 8601持续时间格式的持续时间(除了我不需要的小数部分).

PnYnMnDTnHnMnS

PNW

这是我有的:

^P(\d+Y)?(\d+M)?(\d+W)?(\d+D)?(T(\d+H)?(\d+M)?(\d+S)?)?$
Run Code Online (Sandbox Code Playgroud)

唯一的问题是字符串PPT这个正则表达式是允许的,因为所有部分都是"零或一" ?.

  • 至少需要一个组件(日期或时间)
  • 如果有,T则需要有时间分量(H,M或S)
  • 如果有,T则可能有也可能没有任何日期组件(Y,M或D)
  • 允许溢出(例如P72H,大部分相当于P3D)

可接受的投入:

P1Y        // date component only
P2MT30M    // date and time components
PT6H       // time component only
P5W        // another date component
Run Code Online (Sandbox Code Playgroud)

不可接受的投入:

P         // no components
PT        // no components
P3MT      // T specified but not time components
Run Code Online (Sandbox Code Playgroud)

现在无效的字符串正在通过客户端验证,但在服务器端失败,因为它被传入DateInteval但我想在可能的情况下在客户端失败.如果每个人都在使用Chrome 40+,我可以minlength='3'在输入元素上指定帮助,但遗憾的是并非如此.

Wik*_*żew 18

如果您几乎所有部件都是可选的,但您想确保在P或之后还有其他部分T,您可以使用预测:

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

它们需要一系列数字,后跟指定集合中的字母,紧跟在前一个模式之后.

演示

UPDATE

如果P可以"空",请使用

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

另一个演示.在这里,(?!$)确保字符串不等于P,并且右侧必须有一些其他符号.

或者,正如@UlugbekUmirov建议的那样,只需使用T(?=\d)(因为所有可选部分都以数字开头):

^P(?!$)(\d+Y)?(\d+M)?(\d+W)?(\d+D)?(T(?=\d)(\d+H)?(\d+M)?(\d+S)?)?$
Run Code Online (Sandbox Code Playgroud)

更新2

如果数字可以是浮点数或整数,则(?:\.\d+)?在每个数字后添加\d+.以下是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)?)?$
Run Code Online (Sandbox Code Playgroud)


Raf*_*afi 5

上面的答案不包括小数的情况(详见这里)。小数部分可以出现在最后一个元素上。以下正则表达式包含小数部分:

^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)?)??$
Run Code Online (Sandbox Code Playgroud)

请参阅此处进行测试。