code: private static long parseDuration(String value) throws ParseException {
      // Must ended with "s".
      if (value.isEmpty() || value.charAt(value.length() - 1) != 's') {
        throw new ParseException("Invalid duration string: " + value, 0);
      }
      boolean negative = false;
      if (value.charAt(0) == '-') {
        negative = true;
        value = value.substring(1);
      }
      String secondValue = value.substring(0, value.length() - 1);
      String nanoValue = "";
      int pointPosition = secondValue.indexOf('.');
      if (pointPosition != -1) {
        nanoValue = secondValue.substring(pointPosition + 1);
        secondValue = secondValue.substring(0, pointPosition);
      }
      long seconds = Long.parseLong(secondValue);
      int nanos = nanoValue.isEmpty() ? 0 : parseNanos(nanoValue);
      if (seconds < 0) {
        throw new ParseException("Invalid duration string: " + value, 0);
      }
      if (negative) {
        seconds = -seconds;
        nanos = -nanos;
      }
      try {
        return normalizedDuration(seconds, nanos);
      } catch (IllegalArgumentException e) {
        throw new ParseException("Duration value is out of range.", 0);
      }
    }
docs: Parse from a string to produce a duration.  Copy of
  {@link com.google.protobuf.util.Durations#parse}.
  
  @return A Duration parsed from the string.
  @throws ParseException if parsing fails.