/** * Obtains an instance of `Duration` by parsing a text string. * * This will parse the ISO-8601 duration format `PnDTnHnMn.nS` * which is the format returned by `__toString()`. * * All of the values (days, hours, minutes, seconds, nanoseconds) are optional, * but the duration must at least contain one of the (days, hours, minutes, seconds) values. * * A day is considered to by 24 hours, or 86400 seconds. * * The 'T' separator must only be present if one the (hours, minutes, seconds) values are present. * * Each of the (days, hours, minutes, seconds) values can optionally be preceded with a '+' or '-' sign. * The whole string can also start with an optional '+' or '-' sign, which will further affect all the fields. * * @param string $text * * @return \Brick\DateTime\Duration * * @throws \Brick\DateTime\Parser\DateTimeParseException */ public static function parse($text) { $pattern = '/^' . '([\\-\\+]?)' . 'P' . '(?:([\\-\\+]?[0-9]+)D)?' . '(?:(T)' . '(?:([\\-\\+]?[0-9]+)H)?' . '(?:([\\-\\+]?[0-9]+)M)?' . '(?:([\\-\\+]?[0-9]+)(?:\\.([0-9]{1,9}))?S)?' . ')?' . '()$/i'; if (preg_match($pattern, $text, $matches) !== 1) { throw Parser\DateTimeParseException::invalidDuration($text); } list(, $sign, $days, $t, $hours, $minutes, $seconds, $nanos) = $matches; if ($hours === '' && $minutes === '' && $seconds === '') { if ($days === '' || $t === 'T') { throw Parser\DateTimeParseException::invalidDuration($text); } } $allNegative = $sign === '-'; $secondsNegative = $seconds !== '' && $seconds[0] === '-'; $nanos = str_pad($nanos, 9, '0', STR_PAD_RIGHT); $days = (int) $days; $hours = (int) $hours; $minutes = (int) $minutes; $seconds = (int) $seconds; $nanos = (int) $nanos; if ($secondsNegative) { $nanos = -$nanos; } if ($allNegative) { $days = -$days; $hours = -$hours; $minutes = -$minutes; $seconds = -$seconds; $nanos = -$nanos; } $seconds += LocalTime::SECONDS_PER_DAY * $days + LocalTime::SECONDS_PER_HOUR * $hours + LocalTime::SECONDS_PER_MINUTE * $minutes; if ($nanos < 0) { $nanos += LocalTime::NANOS_PER_SECOND; $seconds--; } return new Duration($seconds, $nanos); }
/** * Obtains an instance of `Period` by parsing a text string. * * This will parse the ISO-8601 period format `PnYnMnWnD` * which is the format returned by `__toString()`. * * All of the values (years, months, weeks, days) are optional, * but the period must at least contain one of these values. * * A week is converted to 7 days. * * Each of the (years, months, weeks, days) values can optionally be preceded with a '+' or '-' sign. * The whole string can also start with an optional '+' or '-' sign, which will further affect all the fields. * * @param string $text * * @return \Brick\DateTime\Period * * @throws \Brick\DateTime\Parser\DateTimeParseException */ public static function parse($text) { $pattern = '/^' . '([\\-\\+]?)' . 'P' . '(?:([\\-\\+]?[0-9]+)Y)?' . '(?:([\\-\\+]?[0-9]+)M)?' . '(?:([\\-\\+]?[0-9]+)W)?' . '(?:([\\-\\+]?[0-9]+)D)?' . '()$/i'; if (preg_match($pattern, $text, $matches) !== 1) { throw Parser\DateTimeParseException::invalidPeriod($text); } list(, $sign, $years, $months, $weeks, $days) = $matches; if ($years === '' && $months === '' && $weeks === '' && $days === '') { throw Parser\DateTimeParseException::invalidPeriod($text); } $years = (int) $years; $months = (int) $months; $weeks = (int) $weeks; $days = (int) $days; $days += LocalTime::DAYS_PER_WEEK * $weeks; if ($sign === '-') { $years = -$years; $months = -$months; $days = -$days; } return new Period($years, $months, $days); }