13

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

PnYnMnDTnHnMnS

PNW

这是我所拥有的:

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

唯一的问题是这个正则表达式允许使用字符串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

不可接受的输入:

P         // no components
PT        // no components
P3MT      // T specified but not time components

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

4

5 回答 5

23

如果您几乎所有部分都是可选的,但您想确保Por之后还有其他内容T,则可以使用前瞻:

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

它们需要一个数字序列,后跟来自指定集合的​​一个字母,才能出现在前面的模式之后。

演示

更新

如果P可以为“空”,请使用

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

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

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

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

更新 2

如果数字既可以是浮点数也可以是整数,请(?:\.\d+)?在每个\d+. 这是更新 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)?)?$
于 2015-08-17T07:47:00.243 回答
3

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

^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)?)??$

请参阅此处进行测试。

于 2018-11-04T12:44:49.920 回答
1

根据有关ISO 8601-2:2019(en)的这条消息,负持续时间在 之前用减号表示,而且似乎可以用加号表示明确的正持续时间。-P+

有用的包括[-+]?(-|\+)?之前P

最后,该消息还显示了来自 ISO 8601-2:2019(en) 的以下示例,表明持续时间的每个组成部分都可以负号。

| EXAMPLE 7 '-P2M1D' is equivalent to 'P-2M-1D'.
| EXAMPLE 8 '-P5DT10H' is equivalent to 'P-5DT-10H'.

在组件中添加[-+]?前数字并允许-+前瞻T符合 8601-2 是有意义的

^[-+]?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)?)??$

于 2021-10-24T06:27:16.777 回答
0

上述答案需要额外的后处理。 /^(-?)P(?=\d|T\d)(?:(\d+)Y)?(?:(\d+)M)?(?:(\d+)([DW]))?(?:T(?:(\d+)H)?(?:(\d+)M)?(?:(\d+(?:\.\d+)?)S)?)?$/ 输出:

["P2Y9M3DT12H31M8.001S", "", "2", "9", "3", "D", "12", "31", "8.001", index: 0, input: "P2Y9M3DT12H31M8.001S", groups: undefined]
于 2020-04-20T08:41:30.847 回答
0

如果您正在搜索包含开始日期持续时间的正则表达式,请查看:

^(\d{4}(-\d{2}(-\d{2})?(?!:))?(T\d{2}(:\d{2}(:\d{2})?(\.\d+)?)?)?(Z|([+,-]\d{2}(:\d{2})?))?)?P(([0-9]+([.,][0-9]*)?Y)?([0-9]+([.,][0-9]*)?M)?([0-9]+([.,][0-9]*)?D)?T?([0-9]+([.,][0-9]*)?H)?([0-9]+([.,][0-9]*)?M)?([0-9]+([.,][0-9]*)?S)?)|\d{4}-?(0[1-9]|11|12)-?(?:[0-2]\d|30|31)T((?:[0-1][0-9]|[2][0-3]):?(?:[0-5][0-9]):?(?:[0-5][0-9]|60)|2400|24:00)$
于 2020-07-19T18:00:18.573 回答