/**
  * This implementation looks for the longest matching string.
  * For example, parsing Etc/GMT-2 will return Etc/GMC-2 rather than just
  * Etc/GMC although both are valid.
  */
 public function parse(DateTimeParseContext $context, $text, $position)
 {
     $length = strlen($text);
     if ($position > $length) {
         throw new \OutOfRangeException();
     }
     if ($position === $length) {
         return ~$position;
     }
     // handle fixed time-zone IDs
     $nextChar = $text[$position];
     if ($nextChar === '+' || $nextChar === '-') {
         return $this->parseOffsetBased($context, $text, $position, $position, OffsetIdPrinterParser::INSTANCE_ID_Z());
     } else {
         if ($length >= $position + 2) {
             $nextNextChar = $text[$position + 1];
             if ($context->charEquals($nextChar, 'U') && $context->charEquals($nextNextChar, 'T')) {
                 if ($length >= $position + 3 && $context->charEquals($text[$position + 2], 'C')) {
                     return $this->parseOffsetBased($context, $text, $position, $position + 3, OffsetIdPrinterParser::INSTANCE_ID_ZERO());
                 }
                 return $this->parseOffsetBased($context, $text, $position, $position + 2, OffsetIdPrinterParser::INSTANCE_ID_ZERO());
             } else {
                 if ($context->charEquals($nextChar, 'G') && $length >= $position + 3 && $context->charEquals($nextNextChar, 'M') && $context->charEquals($text[$position + 2], 'T')) {
                     return $this->parseOffsetBased($context, $text, $position, $position + 3, OffsetIdPrinterParser::INSTANCE_ID_ZERO());
                 }
             }
         }
     }
     // parse
     $ppos = new ParsePosition($position);
     $parsedZoneId = $this->match($text, $ppos, $context->isCaseSensitive());
     /*
     $tree = $this->getTree($context);
     $parsedZoneId = $tree->match($text, $ppos);
     */
     if ($parsedZoneId === null) {
         if ($context->charEquals($nextChar, 'Z')) {
             $context->setParsedZone(ZoneOffset::UTC());
             return $position + 1;
         }
         return ~$position;
     }
     $context->setParsedZone(ZoneId::of($parsedZoneId));
     return $ppos->getIndex();
 }