/**
  * Extracts the values of the partial from an object of this converter's type. This method checks
  * if the parser has a zone, and uses it if present. This is most useful for parsing local times
  * with UTC.
  *
  * @param fieldSource a partial that provides access to the fields. This partial may be incomplete
  *     and only getFieldType(int) should be used
  * @param object the object to convert
  * @param chrono the chronology to use, which is the non-null result of getChronology()
  * @param parser the parser to use, may be null
  * @return the array of field values that match the fieldSource, must be non-null valid
  * @throws ClassCastException if the object is invalid
  * @throws IllegalArgumentException if the value if invalid
  * @since 1.3
  */
 public int[] getPartialValues(
     ReadablePartial fieldSource, Object object, Chronology chrono, DateTimeFormatter parser) {
   if (parser.getZone() != null) {
     chrono = chrono.withZone(parser.getZone());
   }
   long millis = parser.withChronology(chrono).parseMillis((String) object);
   return chrono.get(fieldSource, millis);
 }
  /**
   * Sets the value of the mutable interval from the string.
   *
   * @param writableInterval the interval to set
   * @param object the String to convert, must not be null
   * @param chrono the chronology to use, may be null
   */
  public void setInto(ReadWritableInterval writableInterval, Object object, Chronology chrono) {
    String str = (String) object;

    int separator = str.indexOf('/');
    if (separator < 0) {
      throw new IllegalArgumentException("Format requires a '/' separator: " + str);
    }

    String leftStr = str.substring(0, separator);
    if (leftStr.length() <= 0) {
      throw new IllegalArgumentException("Format invalid: " + str);
    }
    String rightStr = str.substring(separator + 1);
    if (rightStr.length() <= 0) {
      throw new IllegalArgumentException("Format invalid: " + str);
    }

    DateTimeFormatter dateTimeParser = ISODateTimeFormat.dateTimeParser();
    dateTimeParser = dateTimeParser.withChronology(chrono);
    PeriodFormatter periodParser = ISOPeriodFormat.standard();
    long startInstant = 0, endInstant = 0;
    Period period = null;
    Chronology parsedChrono = null;

    // before slash
    char c = leftStr.charAt(0);
    if (c == 'P' || c == 'p') {
      period = periodParser.withParseType(getPeriodType(leftStr)).parsePeriod(leftStr);
    } else {
      DateTime start = dateTimeParser.parseDateTime(leftStr);
      startInstant = start.getMillis();
      parsedChrono = start.getChronology();
    }

    // after slash
    c = rightStr.charAt(0);
    if (c == 'P' || c == 'p') {
      if (period != null) {
        throw new IllegalArgumentException("Interval composed of two durations: " + str);
      }
      period = periodParser.withParseType(getPeriodType(rightStr)).parsePeriod(rightStr);
      chrono = (chrono != null ? chrono : parsedChrono);
      endInstant = chrono.add(period, startInstant, 1);
    } else {
      DateTime end = dateTimeParser.parseDateTime(rightStr);
      endInstant = end.getMillis();
      parsedChrono = (parsedChrono != null ? parsedChrono : end.getChronology());
      chrono = (chrono != null ? chrono : parsedChrono);
      if (period != null) {
        startInstant = chrono.add(period, endInstant, -1);
      }
    }

    writableInterval.setInterval(startInstant, endInstant);
    writableInterval.setChronology(chrono);
  }
 /** Serialization singleton. */
 private Object readResolve() {
   Chronology base = getBase();
   return base == null
       ? getInstance(DateTimeZone.UTC, getMinimumDaysInFirstWeek())
       : getInstance(base.getZone(), getMinimumDaysInFirstWeek());
 }