Вам не хватает нескольких моментов, которые легко решить, посмотрев описания случаев сбоя.Следующее регулярное выражение работает для всех случаев (и случаев сбоя), см. Regex 101
^(-?)P(?=.)((\d+)Y)?((\d+)M)?((\d+)D)?(T(?=.)((\d+)H)?((\d+)M)?(\d*(\.\d+)?S)?)?$
Прежде всего, посмотрите на P15.5Y only the seconds can be expressed as a decimal
.Вы используете [\d.]*
везде, что позволяет использовать одну или несколько цифр или точек везде.Но только секундам разрешено иметь одну точку, и за этой точкой должна следовать цифра.Итак, измените секунды на (\d*(\.\d+)?S)
, а все остальные на (\d+Y)
(и т. Д.).
Кроме того, строка должна начинаться с необязательного -
, а затем P
,так что используйте это:
^-?P
Затем, после P
должно быть что-то, просто используйте для этого предварительное утверждение:
(?=.)
Затем придет Y
,M
и D
, как уже обсуждалось.
Если есть компонент времени, сейчас должен прийти T
, поэтому убедитесь, что у нас есть T
, если что-то еще придет:
(T(?=.))
... и только если у нас было T
, нам разрешено иметь H
, M
или S
:
(T(?=.)(\d+H)?(\d+M)?(\d*(\.\d+)?S)?)
Предварительное утверждение гарантируетчто мы что-то найдем, а остальное захватит часть HMS.