2015-08-17 2 views
6

Мне нужно регулярное выражение для проверки продолжительности в ISO 8601 duration format (за исключением дробных частей, которые мне не нужны).Regex для ISO 8601 длительности

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' на элемент ввода, чтобы помочь, но к сожалению это не так.

+0

Вы можете установить длину мин в виде '^ (= {3,} $?.) Р (\ д + Y)? (\ d + М)? (\ d + W)? (\ D + D)? (Т (\ д + Н) + (\ д + М)? (\ d + S)?)? $ '. –

+0

@stribizhev Это будет охватывать только некоторые случаи, так как «P4DT» все равно может быть введен. Также любая причина для downvote? –

+0

@stribizhev Два очевидных уже были разделены 'P' и' PT'. Я отредактировал, чтобы уточнить, пожалуйста, дайте мне знать, если есть что-то еще, что я могу добавить. –

ответ

8

Если у вас есть почти все части необязательны, но вы хотите, чтобы убедиться, что есть что-то еще после P или T, вы можете использовать заглядывая aheads:

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

Они требуют последовательности цифр с последующим по буквам из указанного набора, чтобы появиться сразу после предыдущего шаблона.

См demo

UPDATE

Если P может быть "пустым", используйте

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

Пожалуйста, оставьте здесь комментарий, если все еще есть проблемы. –

+0

Это очень близко, но могут быть случаи, когда задан только компонент времени (например, «PT3H»). –

+0

См. Мое редактирование. Я вижу, что часть 'P' может быть пустой, но строка не может равняться' P'. –

Смежные вопросы