ISO 8601 持续时间的正则表达式
Regex for ISO 8601 durations
我需要一个正则表达式来验证 ISO 8601 duration format 中的持续时间(我不需要的小数部分除外)。
PnYnMnDTnHnMnS
PnW
这是我的:
^P(\d+Y)?(\d+M)?(\d+W)?(\d+D)?(T(\d+H)?(\d+M)?(\d+S)?)?$
唯一的问题是此正则表达式允许使用字符串 P
和 PT
,因为所有部分都是“零或一”?
。
- 至少需要有一个组成部分(日期或时间)
- 如果有
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'
来提供帮助,但不幸的是情况并非如此。
如果你几乎所有的部分都是可选的,但你想确保在 P
或 T
之后还有其他东西,你可以使用前瞻:
^P(?=\d+[YMWD])(\d+Y)?(\d+M)?(\d+W)?(\d+D)?(T(?=\d+[HMS])(\d+H)?(\d+M)?(\d+S)?)?$
^^^^^^^^^^^^ ^^^^^^^^^^^^
它们要求紧跟在前一个模式之后的一组数字后跟一个字母。
见demo
更新
如果P
可以"empty",使用
^P(?!$)(\d+Y)?(\d+M)?(\d+W)?(\d+D)?(T(?=\d+[HMS])(\d+H)?(\d+M)?(\d+S)?)?$
参见 another demo。这里,(?!$)
确保字符串不等于P
,并且右边一定有一些其他符号。
或者,正如@UlugbekUmirov 所建议的那样,它是 enough to just use 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)?)?$
以上答案不包括小数的情况(详见here)。小数部分可以出现在最后一个元素上。以下正则表达式包含小数部分:
^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)?)??$
请参阅 here 进行测试。
以上答案需要额外的 post 处理。
/^(-?)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]
如果您正在搜索包含开始日期 和 持续时间的正则表达式,请查看:
^(\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)$
根据 this message about 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)?)??$
我需要一个正则表达式来验证 ISO 8601 duration format 中的持续时间(我不需要的小数部分除外)。
PnYnMnDTnHnMnS
PnW
这是我的:
^P(\d+Y)?(\d+M)?(\d+W)?(\d+D)?(T(\d+H)?(\d+M)?(\d+S)?)?$
唯一的问题是此正则表达式允许使用字符串 P
和 PT
,因为所有部分都是“零或一”?
。
- 至少需要有一个组成部分(日期或时间)
- 如果有
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'
来提供帮助,但不幸的是情况并非如此。
如果你几乎所有的部分都是可选的,但你想确保在 P
或 T
之后还有其他东西,你可以使用前瞻:
^P(?=\d+[YMWD])(\d+Y)?(\d+M)?(\d+W)?(\d+D)?(T(?=\d+[HMS])(\d+H)?(\d+M)?(\d+S)?)?$
^^^^^^^^^^^^ ^^^^^^^^^^^^
它们要求紧跟在前一个模式之后的一组数字后跟一个字母。
见demo
更新
如果P
可以"empty",使用
^P(?!$)(\d+Y)?(\d+M)?(\d+W)?(\d+D)?(T(?=\d+[HMS])(\d+H)?(\d+M)?(\d+S)?)?$
参见 another demo。这里,(?!$)
确保字符串不等于P
,并且右边一定有一些其他符号。
或者,正如@UlugbekUmirov 所建议的那样,它是 enough to just use 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)?)?$
以上答案不包括小数的情况(详见here)。小数部分可以出现在最后一个元素上。以下正则表达式包含小数部分:
^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)?)??$
请参阅 here 进行测试。
以上答案需要额外的 post 处理。
/^(-?)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]
如果您正在搜索包含开始日期 和 持续时间的正则表达式,请查看:
^(\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)$
根据 this message about 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)?)??$