From 22e0e4aa38a1545e5de719ecf235de1a3017d0d2 Mon Sep 17 00:00:00 2001 From: Andrew Ruthven Date: Wed, 17 May 2017 11:06:29 +1200 Subject: [PATCH] Improve parsing of RFC5545 durations The previous regex failed to parse PT15M which is a valid duration. This version more correctly implements: https://tools.ietf.org/html/rfc5545#section-3.3.6 It isn't totally correct as it incorrectly allows: PT10H20S Which is invalid due to no minutes being present. Oh well. --- inc/RRule.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/inc/RRule.php b/inc/RRule.php index 4331229f..345029a6 100644 --- a/inc/RRule.php +++ b/inc/RRule.php @@ -72,7 +72,9 @@ class RepeatRuleTimeZone extends DateTimeZone { /** * Provide a useful way of dealing with RFC5545 duration strings of the form - * ^-?P(\dW)|((\dD)?(T(\dH)?(\dM)?(\dS)?)?)$ + * ^(-?)P(?:(\d+W)|(?:(?:(\d+)D)?(?:T(?:(\d+)H)?(?:(\d+)M)?(?:(\d+)S?)?)?))$ + * This doesn't fully implement the RFC, as it allows PT10H10S - which should + * be invalid as no minutes are present. */ class Rfc5545Duration { private $epoch_seconds = null; @@ -115,7 +117,7 @@ class Rfc5545Duration { */ function asSeconds() { if ( !isset($this->epoch_seconds) ) { - if ( preg_match('{^(-?)P(\d+W)|(?:(\d+)D?(?:T(\d+)H?(\d+)M?(\d+)S?)?)$}i', $this->as_text, $matches) ) { + if ( preg_match('{^(-?)P(?:(\d+W)|(?:(?:(\d+)D)?(?:T(?:(\d+)H)?(?:(\d+)M)?(?:(\d+)S?)?)?))$}i', $this->as_text, $matches) ) { // @printf("%s - %s - %s - %s - %s - %s\n", $matches[1], $matches[2], $matches[3], $matches[4], $matches[5], $matches[6]); $this->secs = 0; if ( !empty($matches[2]) ) {