public void testGetFieldTypes() {
   LocalTime test = new LocalTime(10, 20, 30, 40);
   DateTimeFieldType[] fields = test.getFieldTypes();
   assertSame(DateTimeFieldType.hourOfDay(), fields[0]);
   assertSame(DateTimeFieldType.minuteOfHour(), fields[1]);
   assertSame(DateTimeFieldType.secondOfMinute(), fields[2]);
   assertSame(DateTimeFieldType.millisOfSecond(), fields[3]);
   assertNotSame(test.getFieldTypes(), test.getFieldTypes());
 }
 public FlightSchedule(
     DateTime validFromInclusive,
     DateTime validUntilExclusive,
     int flightHourOfDay,
     int flightMinuteOfHour) {
   this.validFromInclusive = validFromInclusive;
   this.validUntilInclusive = validUntilExclusive;
   flightTimeOfDay =
       new Partial()
           .with(DateTimeFieldType.hourOfDay(), 12)
           .with(DateTimeFieldType.minuteOfHour(), 30);
 }
 public void testGetFieldType_int() {
   LocalTime test = new LocalTime(10, 20, 30, 40);
   assertSame(DateTimeFieldType.hourOfDay(), test.getFieldType(0));
   assertSame(DateTimeFieldType.minuteOfHour(), test.getFieldType(1));
   assertSame(DateTimeFieldType.secondOfMinute(), test.getFieldType(2));
   assertSame(DateTimeFieldType.millisOfSecond(), test.getFieldType(3));
   try {
     test.getFieldType(-1);
   } catch (IndexOutOfBoundsException ex) {
   }
   try {
     test.getFieldType(5);
   } catch (IndexOutOfBoundsException ex) {
   }
 }
  // -----------------------------------------------------------------------
  public void testWithField_DateTimeFieldType_int_1() {
    LocalTime test = new LocalTime(10, 20, 30, 40);
    LocalTime result = test.withField(DateTimeFieldType.hourOfDay(), 15);

    assertEquals(new LocalTime(10, 20, 30, 40), test);
    assertEquals(new LocalTime(15, 20, 30, 40), result);
  }
 public void testWithField_DateTimeFieldType_int_3() {
   LocalTime test = new LocalTime(10, 20, 30, 40);
   try {
     test.withField(DateTimeFieldType.dayOfMonth(), 6);
     fail();
   } catch (IllegalArgumentException ex) {
   }
 }
Exemple #6
0
 /**
  * Gets the property object for the specified type, which contains many useful methods.
  *
  * @param type the field type to get the chronology for
  * @return the property object
  * @throws IllegalArgumentException if the field is null or unsupported
  * @since 1.2
  */
 public Property property(DateTimeFieldType type) {
   if (type == null) {
     throw new IllegalArgumentException("The DateTimeFieldType must not be null");
   }
   DateTimeField field = type.getField(getChronology());
   if (field.isSupported() == false) {
     throw new IllegalArgumentException("Field '" + type + "' is not supported");
   }
   return new Property(this, field);
 }
  /**
   * Gets a copy of this date with the specified field set to a new value.
   *
   * <p>If this partial did not previously support the field, the new one will. Contrast this
   * behaviour with {@link #withField(DateTimeFieldType, int)}.
   *
   * <p>For example, if the field type is <code>dayOfMonth</code> then the day would be
   * changed/added in the returned instance.
   *
   * @param fieldType the field type to set, not null
   * @param value the value to set
   * @return a copy of this instance with the field set
   * @throws IllegalArgumentException if the value is null or invalid
   */
  public Partial with(DateTimeFieldType fieldType, int value) {
    if (fieldType == null) {
      throw new IllegalArgumentException("The field type must not be null");
    }
    int index = indexOf(fieldType);
    if (index == -1) {
      DateTimeFieldType[] newTypes = new DateTimeFieldType[iTypes.length + 1];
      int[] newValues = new int[newTypes.length];

      // find correct insertion point to keep largest-smallest order
      int i = 0;
      DurationField unitField = fieldType.getDurationType().getField(iChronology);
      if (unitField.isSupported()) {
        for (; i < iTypes.length; i++) {
          DateTimeFieldType loopType = iTypes[i];
          DurationField loopUnitField = loopType.getDurationType().getField(iChronology);
          if (loopUnitField.isSupported()) {
            int compare = unitField.compareTo(loopUnitField);
            if (compare > 0) {
              break;
            } else if (compare == 0) {
              if (fieldType.getRangeDurationType() == null) {
                break;
              }
              if (loopType.getRangeDurationType() == null) {
                continue;
              }
              DurationField rangeField = fieldType.getRangeDurationType().getField(iChronology);
              DurationField loopRangeField = loopType.getRangeDurationType().getField(iChronology);
              if (rangeField.compareTo(loopRangeField) > 0) {
                break;
              }
            }
          }
        }
      }
      System.arraycopy(iTypes, 0, newTypes, 0, i);
      System.arraycopy(iValues, 0, newValues, 0, i);
      newTypes[i] = fieldType;
      newValues[i] = value;
      System.arraycopy(iTypes, i, newTypes, i + 1, newTypes.length - i - 1);
      System.arraycopy(iValues, i, newValues, i + 1, newValues.length - i - 1);
      // use public constructor to ensure full validation
      // this isn't overly efficient, but is safe
      Partial newPartial = new Partial(newTypes, newValues, iChronology);
      iChronology.validate(newPartial, newValues);
      return newPartial;
    }
    if (value == getValue(index)) {
      return this;
    }
    int[] newValues = getValues();
    newValues = getField(index).set(this, index, newValues, value);
    return new Partial(this, newValues);
  }
  // -----------------------------------------------------------------------
  @SuppressWarnings("deprecation")
  public void testCompareTo() {
    LocalTime test1 = new LocalTime(10, 20, 30, 40);
    LocalTime test1a = new LocalTime(10, 20, 30, 40);
    assertEquals(0, test1.compareTo(test1a));
    assertEquals(0, test1a.compareTo(test1));
    assertEquals(0, test1.compareTo(test1));
    assertEquals(0, test1a.compareTo(test1a));

    LocalTime test2 = new LocalTime(10, 20, 35, 40);
    assertEquals(-1, test1.compareTo(test2));
    assertEquals(+1, test2.compareTo(test1));

    LocalTime test3 = new LocalTime(10, 20, 35, 40, GregorianChronology.getInstanceUTC());
    assertEquals(-1, test1.compareTo(test3));
    assertEquals(+1, test3.compareTo(test1));
    assertEquals(0, test3.compareTo(test2));

    DateTimeFieldType[] types =
        new DateTimeFieldType[] {
          DateTimeFieldType.hourOfDay(),
          DateTimeFieldType.minuteOfHour(),
          DateTimeFieldType.secondOfMinute(),
          DateTimeFieldType.millisOfSecond(),
        };
    int[] values = new int[] {10, 20, 30, 40};
    Partial p = new Partial(types, values);
    assertEquals(0, test1.compareTo(p));
    assertEquals(0, test1.compareTo(new TimeOfDay(10, 20, 30, 40)));
    try {
      test1.compareTo(null);
      fail();
    } catch (NullPointerException ex) {
    }
    //        try {
    //            test1.compareTo(new Date());
    //            fail();
    //        } catch (ClassCastException ex) {}
  }
Exemple #9
0
 /**
  * Sets the value of one of the fields of the instant, such as hourOfDay.
  *
  * @param type a field type, usually obtained from DateTimeFieldType, not null
  * @param value the value to set the field to
  * @throws IllegalArgumentException if the value is null or invalid
  */
 public void set(DateTimeFieldType type, int value) {
   if (type == null) {
     throw new IllegalArgumentException("Field must not be null");
   }
   setMillis(type.getField(getChronology()).set(getMillis(), value));
 }
 // -----------------------------------------------------------------------
 public void testGet_DateTimeFieldType() {
   LocalTime test = new LocalTime(10, 20, 30, 40);
   assertEquals(10, test.get(DateTimeFieldType.hourOfDay()));
   assertEquals(20, test.get(DateTimeFieldType.minuteOfHour()));
   assertEquals(30, test.get(DateTimeFieldType.secondOfMinute()));
   assertEquals(40, test.get(DateTimeFieldType.millisOfSecond()));
   assertEquals(TEST_TIME_NOW / 60000, test.get(DateTimeFieldType.minuteOfDay()));
   assertEquals(TEST_TIME_NOW / 1000, test.get(DateTimeFieldType.secondOfDay()));
   assertEquals(TEST_TIME_NOW, test.get(DateTimeFieldType.millisOfDay()));
   assertEquals(10, test.get(DateTimeFieldType.hourOfHalfday()));
   assertEquals(DateTimeConstants.AM, test.get(DateTimeFieldType.halfdayOfDay()));
   test = new LocalTime(12, 30);
   assertEquals(0, test.get(DateTimeFieldType.hourOfHalfday()));
   assertEquals(12, test.get(DateTimeFieldType.clockhourOfHalfday()));
   assertEquals(12, test.get(DateTimeFieldType.clockhourOfDay()));
   assertEquals(DateTimeConstants.PM, test.get(DateTimeFieldType.halfdayOfDay()));
   test = new LocalTime(14, 30);
   assertEquals(2, test.get(DateTimeFieldType.hourOfHalfday()));
   assertEquals(2, test.get(DateTimeFieldType.clockhourOfHalfday()));
   assertEquals(14, test.get(DateTimeFieldType.clockhourOfDay()));
   assertEquals(DateTimeConstants.PM, test.get(DateTimeFieldType.halfdayOfDay()));
   test = new LocalTime(0, 30);
   assertEquals(0, test.get(DateTimeFieldType.hourOfHalfday()));
   assertEquals(12, test.get(DateTimeFieldType.clockhourOfHalfday()));
   assertEquals(24, test.get(DateTimeFieldType.clockhourOfDay()));
   assertEquals(DateTimeConstants.AM, test.get(DateTimeFieldType.halfdayOfDay()));
   try {
     test.get(null);
     fail();
   } catch (IllegalArgumentException ex) {
   }
   try {
     test.get(DateTimeFieldType.dayOfMonth());
     fail();
   } catch (IllegalArgumentException ex) {
   }
 }
  // -----------------------------------------------------------------------
  public void testProperty() {
    LocalTime test = new LocalTime(10, 20, 30, 40);
    assertEquals(test.hourOfDay(), test.property(DateTimeFieldType.hourOfDay()));
    assertEquals(test.minuteOfHour(), test.property(DateTimeFieldType.minuteOfHour()));
    assertEquals(test.secondOfMinute(), test.property(DateTimeFieldType.secondOfMinute()));
    assertEquals(test.millisOfSecond(), test.property(DateTimeFieldType.millisOfSecond()));
    assertEquals(test.millisOfDay(), test.property(DateTimeFieldType.millisOfDay()));

    assertEquals(test, test.property(DateTimeFieldType.minuteOfDay()).getLocalTime());
    assertEquals(test, test.property(DateTimeFieldType.secondOfDay()).getLocalTime());
    assertEquals(test, test.property(DateTimeFieldType.millisOfDay()).getLocalTime());
    assertEquals(test, test.property(DateTimeFieldType.hourOfHalfday()).getLocalTime());
    assertEquals(test, test.property(DateTimeFieldType.halfdayOfDay()).getLocalTime());
    assertEquals(test, test.property(DateTimeFieldType.clockhourOfHalfday()).getLocalTime());
    assertEquals(test, test.property(DateTimeFieldType.clockhourOfDay()).getLocalTime());

    try {
      test.property(DateTimeFieldType.dayOfWeek());
      fail();
    } catch (IllegalArgumentException ex) {
    }
    try {
      test.property(null);
      fail();
    } catch (IllegalArgumentException ex) {
    }
  }
 public void testWithField_DateTimeFieldType_int_4() {
   LocalTime test = new LocalTime(10, 20, 30, 40);
   LocalTime result = test.withField(DateTimeFieldType.hourOfDay(), 10);
   assertSame(test, result);
 }
  public void testIsSupported_DateTimeFieldType() {
    LocalTime test = new LocalTime(10, 20, 30, 40);
    assertEquals(true, test.isSupported(DateTimeFieldType.hourOfDay()));
    assertEquals(true, test.isSupported(DateTimeFieldType.minuteOfHour()));
    assertEquals(true, test.isSupported(DateTimeFieldType.secondOfMinute()));
    assertEquals(true, test.isSupported(DateTimeFieldType.millisOfSecond()));
    assertEquals(true, test.isSupported(DateTimeFieldType.minuteOfDay()));
    assertEquals(true, test.isSupported(DateTimeFieldType.secondOfDay()));
    assertEquals(true, test.isSupported(DateTimeFieldType.millisOfDay()));

    assertEquals(true, test.isSupported(DateTimeFieldType.hourOfHalfday()));
    assertEquals(true, test.isSupported(DateTimeFieldType.halfdayOfDay()));
    assertEquals(true, test.isSupported(DateTimeFieldType.clockhourOfHalfday()));
    assertEquals(true, test.isSupported(DateTimeFieldType.clockhourOfDay()));

    assertEquals(false, test.isSupported(DateTimeFieldType.dayOfMonth()));
    assertEquals(false, test.isSupported((DateTimeFieldType) null));

    DateTimeFieldType d =
        new DateTimeFieldType("hours") {
          private static final long serialVersionUID = 1L;

          public DurationFieldType getDurationType() {
            return DurationFieldType.hours();
          }

          public DurationFieldType getRangeDurationType() {
            return null;
          }

          public DateTimeField getField(Chronology chronology) {
            return chronology.hourOfDay();
          }
        };
    assertEquals(false, test.isSupported(d));

    d =
        new DateTimeFieldType("hourOfYear") {
          private static final long serialVersionUID = 1L;

          public DurationFieldType getDurationType() {
            return DurationFieldType.hours();
          }

          public DurationFieldType getRangeDurationType() {
            return DurationFieldType.years();
          }

          public DateTimeField getField(Chronology chronology) {
            return chronology.hourOfDay();
          }
        };
    assertEquals(false, test.isSupported(d));
  }
  /**
   * Constructs a Partial with the specified fields and values. The fields must be specified in the
   * order largest to smallest. For year and weekyear fields with equal duration, year is defined as
   * being larger than weekyear.
   *
   * <p>The constructor uses the specified chronology.
   *
   * @param types the types to create the partial from, not null
   * @param values the values to store, not null
   * @param chronology the chronology, null means ISO
   * @throws IllegalArgumentException if the types or values are invalid
   */
  public Partial(DateTimeFieldType[] types, int[] values, Chronology chronology) {
    super();
    chronology = DateTimeUtils.getChronology(chronology).withUTC();
    iChronology = chronology;
    if (types == null) {
      throw new IllegalArgumentException("Types array must not be null");
    }
    if (values == null) {
      throw new IllegalArgumentException("Values array must not be null");
    }
    if (values.length != types.length) {
      throw new IllegalArgumentException("Values array must be the same length as the types array");
    }
    if (types.length == 0) {
      iTypes = types;
      iValues = values;
      return;
    }
    for (int i = 0; i < types.length; i++) {
      if (types[i] == null) {
        throw new IllegalArgumentException("Types array must not contain null: index " + i);
      }
    }
    DurationField lastUnitField = null;
    for (int i = 0; i < types.length; i++) {
      DateTimeFieldType loopType = types[i];
      DurationField loopUnitField = loopType.getDurationType().getField(iChronology);
      if (i > 0) {
        if (loopUnitField.isSupported() == false) {
          if (lastUnitField.isSupported()) {
            throw new IllegalArgumentException(
                "Types array must be in order largest-smallest: "
                    + types[i - 1].getName()
                    + " < "
                    + loopType.getName());
          } else {
            throw new IllegalArgumentException(
                "Types array must not contain duplicate unsupported: "
                    + types[i - 1].getName()
                    + " and "
                    + loopType.getName());
          }
        }
        int compare = lastUnitField.compareTo(loopUnitField);
        if (compare < 0) {
          throw new IllegalArgumentException(
              "Types array must be in order largest-smallest: "
                  + types[i - 1].getName()
                  + " < "
                  + loopType.getName());
        } else if (compare == 0) {
          if (lastUnitField.equals(loopUnitField)) {
            DurationFieldType lastRangeType = types[i - 1].getRangeDurationType();
            DurationFieldType loopRangeType = loopType.getRangeDurationType();
            if (lastRangeType == null) {
              if (loopRangeType == null) {
                throw new IllegalArgumentException(
                    "Types array must not contain duplicate: "
                        + types[i - 1].getName()
                        + " and "
                        + loopType.getName());
              }
            } else {
              if (loopRangeType == null) {
                throw new IllegalArgumentException(
                    "Types array must be in order largest-smallest: "
                        + types[i - 1].getName()
                        + " < "
                        + loopType.getName());
              }
              DurationField lastRangeField = lastRangeType.getField(iChronology);
              DurationField loopRangeField = loopRangeType.getField(iChronology);
              if (lastRangeField.compareTo(loopRangeField) < 0) {
                throw new IllegalArgumentException(
                    "Types array must be in order largest-smallest: "
                        + types[i - 1].getName()
                        + " < "
                        + loopType.getName());
              }
              if (lastRangeField.compareTo(loopRangeField) == 0) {
                throw new IllegalArgumentException(
                    "Types array must not contain duplicate: "
                        + types[i - 1].getName()
                        + " and "
                        + loopType.getName());
              }
            }
          } else {
            if (lastUnitField.isSupported()
                && lastUnitField.getType() != DurationFieldType.YEARS_TYPE) {
              throw new IllegalArgumentException(
                  "Types array must be in order largest-smallest,"
                      + " for year-based fields, years is defined as being largest: "
                      + types[i - 1].getName()
                      + " < "
                      + loopType.getName());
            }
          }
        }
      }
      lastUnitField = loopUnitField;
    }

    iTypes = (DateTimeFieldType[]) types.clone();
    chronology.validate(this, values);
    iValues = (int[]) values.clone();
  }
Exemple #15
0
/**
 * TimeOfDay is an immutable partial supporting the hour, minute, second and millisecond fields.
 *
 * <p>NOTE: This class only supports the four fields listed above. Thus, you cannot query the
 * millisOfDay or secondOfDay fields for example. The new <code>LocalTime</code> class removes this
 * restriction.
 *
 * <p>Calculations on TimeOfDay are performed using a {@link Chronology}. This chronology is set to
 * be in the UTC time zone for all calculations.
 *
 * <p>Each individual field can be queried in two ways:
 *
 * <ul>
 *   <li><code>getHourOfDay()</code>
 *   <li><code>hourOfDay().get()</code>
 * </ul>
 *
 * The second technique also provides access to other useful methods on the field:
 *
 * <ul>
 *   <li>numeric value - <code>hourOfDay().get()</code>
 *   <li>text value - <code>hourOfDay().getAsText()</code>
 *   <li>short text value - <code>hourOfDay().getAsShortText()</code>
 *   <li>maximum/minimum values - <code>hourOfDay().getMaximumValue()</code>
 *   <li>add/subtract - <code>hourOfDay().addToCopy()</code>
 *   <li>set - <code>hourOfDay().setCopy()</code>
 * </ul>
 *
 * <p>TimeOfDay is thread-safe and immutable, provided that the Chronology is as well. All standard
 * Chronology classes supplied are thread-safe and immutable.
 *
 * @author Stephen Colebourne
 * @author Brian S O'Neill
 * @since 1.0
 * @deprecated Use LocalTime which has a much better internal implementation and has been available
 *     since 1.3
 */
public final class TimeOfDay extends BasePartial implements ReadablePartial, Serializable {
  // NOTE: No toDateTime(YearMonthDay) as semantics are confusing when
  // different chronologies

  /** Serialization version */
  private static final long serialVersionUID = 3633353405803318660L;
  /** The singleton set of field types */
  private static final DateTimeFieldType[] FIELD_TYPES =
      new DateTimeFieldType[] {
        DateTimeFieldType.hourOfDay(),
        DateTimeFieldType.minuteOfHour(),
        DateTimeFieldType.secondOfMinute(),
        DateTimeFieldType.millisOfSecond(),
      };

  /** Constant for midnight. */
  public static final TimeOfDay MIDNIGHT = new TimeOfDay(0, 0, 0, 0);

  /** The index of the hourOfDay field in the field array */
  public static final int HOUR_OF_DAY = 0;
  /** The index of the minuteOfHour field in the field array */
  public static final int MINUTE_OF_HOUR = 1;
  /** The index of the secondOfMinute field in the field array */
  public static final int SECOND_OF_MINUTE = 2;
  /** The index of the millisOfSecond field in the field array */
  public static final int MILLIS_OF_SECOND = 3;

  // -----------------------------------------------------------------------
  /**
   * Constructs a TimeOfDay from a <code>java.util.Calendar</code> using exactly the same field
   * values avoiding any time zone effects.
   *
   * <p>Each field is queried from the Calendar and assigned to the TimeOfDay. This is useful to
   * ensure that the field values are the same in the created TimeOfDay no matter what the time zone
   * is. For example, if the Calendar states that the time is 04:29, then the created TimeOfDay will
   * always have the time 04:29 irrespective of time zone issues.
   *
   * <p>This factory method ignores the type of the calendar and always creates a TimeOfDay with ISO
   * chronology.
   *
   * @param calendar the Calendar to extract fields from
   * @return the created TimeOfDay
   * @throws IllegalArgumentException if the calendar is null
   * @throws IllegalArgumentException if the time is invalid for the ISO chronology
   * @since 1.2
   */
  /*public static TimeOfDay fromCalendarFields(Calendar calendar) {
      if (calendar == null) {
          throw new IllegalArgumentException("The calendar must not be null");
      }
      return new TimeOfDay(
          calendar.get(Calendar.HOUR_OF_DAY),
          calendar.get(Calendar.MINUTE),
          calendar.get(Calendar.SECOND),
          calendar.get(Calendar.MILLISECOND)
      );
  }*/

  /**
   * Constructs a TimeOfDay from a <code>java.util.Date</code> using exactly the same field values
   * avoiding any time zone effects.
   *
   * <p>Each field is queried from the Date and assigned to the TimeOfDay. This is useful to ensure
   * that the field values are the same in the created TimeOfDay no matter what the time zone is.
   * For example, if the Calendar states that the time is 04:29, then the created TimeOfDay will
   * always have the time 04:29 irrespective of time zone issues.
   *
   * <p>This factory method always creates a TimeOfDay with ISO chronology.
   *
   * @param date the Date to extract fields from
   * @return the created TimeOfDay
   * @throws IllegalArgumentException if the calendar is null
   * @throws IllegalArgumentException if the date is invalid for the ISO chronology
   * @since 1.2
   */
  public static TimeOfDay fromDateFields(Date date) {
    if (date == null) {
      throw new IllegalArgumentException("The date must not be null");
    }
    return new TimeOfDay(
        date.getHours(), date.getMinutes(), date.getSeconds(), (int) (date.getTime() % 1000));
  }

  // -----------------------------------------------------------------------
  /**
   * Constructs a TimeOfDay from the specified millis of day using the ISO chronology.
   *
   * <p>The millisOfDay value may exceed the number of millis in one day, but additional days will
   * be ignored. This method uses the UTC time zone internally.
   *
   * @param millisOfDay the number of milliseconds into a day to convert
   */
  public static TimeOfDay fromMillisOfDay(long millisOfDay) {
    return fromMillisOfDay(millisOfDay, null);
  }

  /**
   * Constructs a TimeOfDay from the specified millis of day using the specified chronology.
   *
   * <p>The millisOfDay value may exceed the number of millis in one day, but additional days will
   * be ignored. This method uses the UTC time zone internally.
   *
   * @param millisOfDay the number of milliseconds into a day to convert
   * @param chrono the chronology, null means ISO chronology
   */
  public static TimeOfDay fromMillisOfDay(long millisOfDay, Chronology chrono) {
    chrono = DateTimeUtils.getChronology(chrono);
    chrono = chrono.withUTC();
    return new TimeOfDay(millisOfDay, chrono);
  }

  // Constructors
  // -----------------------------------------------------------------------
  /**
   * Constructs a TimeOfDay with the current time, using ISOChronology in the default zone to
   * extract the fields.
   *
   * <p>The constructor uses the default time zone, resulting in the local time being initialised.
   * Once the constructor is complete, all further calculations are performed without reference to a
   * timezone (by switching to UTC).
   */
  public TimeOfDay() {
    super();
  }

  /**
   * Constructs a TimeOfDay with the current time, using ISOChronology in the specified zone to
   * extract the fields.
   *
   * <p>The constructor uses the specified time zone to obtain the current time. Once the
   * constructor is complete, all further calculations are performed without reference to a timezone
   * (by switching to UTC).
   *
   * @param zone the zone to use, null means default zone
   * @since 1.1
   */
  public TimeOfDay(DateTimeZone zone) {
    super(ISOChronology.getInstance(zone));
  }

  /**
   * Constructs a TimeOfDay with the current time, using the specified chronology and zone to
   * extract the fields.
   *
   * <p>The constructor uses the time zone of the chronology specified. Once the constructor is
   * complete, all further calculations are performed without reference to a timezone (by switching
   * to UTC).
   *
   * @param chronology the chronology, null means ISOChronology in the default zone
   */
  public TimeOfDay(Chronology chronology) {
    super(chronology);
  }

  /**
   * Constructs a TimeOfDay extracting the partial fields from the specified milliseconds using the
   * ISOChronology in the default zone.
   *
   * <p>The constructor uses the default time zone, resulting in the local time being initialised.
   * Once the constructor is complete, all further calculations are performed without reference to a
   * timezone (by switching to UTC).
   *
   * @param instant the milliseconds from 1970-01-01T00:00:00Z
   */
  public TimeOfDay(long instant) {
    super(instant);
  }

  /**
   * Constructs a TimeOfDay extracting the partial fields from the specified milliseconds using the
   * chronology provided.
   *
   * <p>The constructor uses the time zone of the chronology specified. Once the constructor is
   * complete, all further calculations are performed without reference to a timezone (by switching
   * to UTC).
   *
   * @param instant the milliseconds from 1970-01-01T00:00:00Z
   * @param chronology the chronology, null means ISOChronology in the default zone
   */
  public TimeOfDay(long instant, Chronology chronology) {
    super(instant, chronology);
  }

  /**
   * Constructs a TimeOfDay from an Object that represents a time.
   *
   * <p>The recognised object types are defined in {@link org.joda.time.convert.ConverterManager
   * ConverterManager} and include ReadableInstant, String, Calendar and Date. The String formats
   * are described by {@link ISODateTimeFormat#timeParser()}.
   *
   * <p>The chronology used will be derived from the object, defaulting to ISO.
   *
   * <p>NOTE: Prior to v1.3 the string format was described by {@link
   * ISODateTimeFormat#dateTimeParser()}. Dates are now rejected.
   *
   * @param instant the datetime object, null means now
   * @throws IllegalArgumentException if the instant is invalid
   */
  public TimeOfDay(Object instant) {
    super(instant, null, ISODateTimeFormat.timeParser());
  }

  /**
   * Constructs a TimeOfDay from an Object that represents a time, using the specified chronology.
   *
   * <p>The recognised object types are defined in {@link org.joda.time.convert.ConverterManager
   * ConverterManager} and include ReadableInstant, String, Calendar and Date. The String formats
   * are described by {@link ISODateTimeFormat#timeParser()}.
   *
   * <p>The constructor uses the time zone of the chronology specified. Once the constructor is
   * complete, all further calculations are performed without reference to a timezone (by switching
   * to UTC). The specified chronology overrides that of the object.
   *
   * <p>NOTE: Prior to v1.3 the string format was described by {@link
   * ISODateTimeFormat#dateTimeParser()}. Dates are now rejected.
   *
   * @param instant the datetime object, null means now
   * @param chronology the chronology, null means ISO default
   * @throws IllegalArgumentException if the instant is invalid
   */
  public TimeOfDay(Object instant, Chronology chronology) {
    super(instant, DateTimeUtils.getChronology(chronology), ISODateTimeFormat.timeParser());
  }

  /**
   * Constructs a TimeOfDay with specified hour and minute and zero seconds and milliseconds using
   * <code>ISOChronology</code> in the default zone.
   *
   * <p>The constructor uses the no time zone initialising the fields as provided. Once the
   * constructor is complete, all further calculations are performed without reference to a timezone
   * (by switching to UTC).
   *
   * @param hourOfDay the hour of the day
   * @param minuteOfHour the minute of the hour
   */
  public TimeOfDay(int hourOfDay, int minuteOfHour) {
    this(hourOfDay, minuteOfHour, 0, 0, null);
  }

  /**
   * Constructs a TimeOfDay with specified hour and minute and zero seconds and milliseconds.
   *
   * <p>The constructor uses the time zone of the chronology specified. Once the constructor is
   * complete, all further calculations are performed without reference to a timezone (by switching
   * to UTC).
   *
   * @param hourOfDay the hour of the day
   * @param minuteOfHour the minute of the hour
   * @param chronology the chronology, null means ISOChronology in the default zone
   */
  public TimeOfDay(int hourOfDay, int minuteOfHour, Chronology chronology) {
    this(hourOfDay, minuteOfHour, 0, 0, chronology);
  }

  /**
   * Constructs a TimeOfDay with specified time field values and zero milliseconds using <code>
   * ISOChronology</code> in the default zone.
   *
   * <p>The constructor uses the no time zone initialising the fields as provided. Once the
   * constructor is complete, all further calculations are performed without reference to a timezone
   * (by switching to UTC).
   *
   * @param hourOfDay the hour of the day
   * @param minuteOfHour the minute of the hour
   * @param secondOfMinute the second of the minute
   */
  public TimeOfDay(int hourOfDay, int minuteOfHour, int secondOfMinute) {
    this(hourOfDay, minuteOfHour, secondOfMinute, 0, null);
  }

  /**
   * Constructs a TimeOfDay with specified time field values and zero milliseconds.
   *
   * <p>The constructor uses the time zone of the chronology specified. Once the constructor is
   * complete, all further calculations are performed without reference to a timezone (by switching
   * to UTC).
   *
   * @param hourOfDay the hour of the day
   * @param minuteOfHour the minute of the hour
   * @param secondOfMinute the second of the minute
   * @param chronology the chronology, null means ISOChronology in the default zone
   */
  public TimeOfDay(int hourOfDay, int minuteOfHour, int secondOfMinute, Chronology chronology) {
    this(hourOfDay, minuteOfHour, secondOfMinute, 0, chronology);
  }

  /**
   * Constructs a TimeOfDay with specified time field values using <code>ISOChronology</code> in the
   * default zone.
   *
   * <p>The constructor uses the no time zone initialising the fields as provided. Once the
   * constructor is complete, all further calculations are performed without reference to a timezone
   * (by switching to UTC).
   *
   * @param hourOfDay the hour of the day
   * @param minuteOfHour the minute of the hour
   * @param secondOfMinute the second of the minute
   * @param millisOfSecond the millisecond of the second
   */
  public TimeOfDay(int hourOfDay, int minuteOfHour, int secondOfMinute, int millisOfSecond) {
    this(hourOfDay, minuteOfHour, secondOfMinute, millisOfSecond, null);
  }

  /**
   * Constructs a TimeOfDay with specified time field values and chronology.
   *
   * <p>The constructor uses the time zone of the chronology specified. Once the constructor is
   * complete, all further calculations are performed without reference to a timezone (by switching
   * to UTC).
   *
   * @param hourOfDay the hour of the day
   * @param minuteOfHour the minute of the hour
   * @param secondOfMinute the second of the minute
   * @param millisOfSecond the millisecond of the second
   * @param chronology the chronology, null means ISOChronology in the default zone
   */
  public TimeOfDay(
      int hourOfDay,
      int minuteOfHour,
      int secondOfMinute,
      int millisOfSecond,
      Chronology chronology) {
    super(new int[] {hourOfDay, minuteOfHour, secondOfMinute, millisOfSecond}, chronology);
  }

  /**
   * Constructs a TimeOfDay with chronology from this instance and new values.
   *
   * @param partial the partial to base this new instance on
   * @param values the new set of values
   */
  TimeOfDay(TimeOfDay partial, int[] values) {
    super(partial, values);
  }

  /**
   * Constructs a TimeOfDay with values from this instance and a new chronology.
   *
   * @param partial the partial to base this new instance on
   * @param chrono the new chronology
   */
  TimeOfDay(TimeOfDay partial, Chronology chrono) {
    super(partial, chrono);
  }

  // -----------------------------------------------------------------------
  /**
   * Gets the number of fields in this partial.
   *
   * @return the field count
   */
  public int size() {
    return 4;
  }

  /**
   * Gets the field for a specific index in the chronology specified.
   *
   * <p>This method must not use any instance variables.
   *
   * @param index the index to retrieve
   * @param chrono the chronology to use
   * @return the field
   */
  protected DateTimeField getField(int index, Chronology chrono) {
    switch (index) {
      case HOUR_OF_DAY:
        return chrono.hourOfDay();
      case MINUTE_OF_HOUR:
        return chrono.minuteOfHour();
      case SECOND_OF_MINUTE:
        return chrono.secondOfMinute();
      case MILLIS_OF_SECOND:
        return chrono.millisOfSecond();
      default:
        throw new IndexOutOfBoundsException("Invalid index: " + index);
    }
  }

  /**
   * Gets the field type at the specified index.
   *
   * @param index the index to retrieve
   * @return the field at the specified index
   * @throws IndexOutOfBoundsException if the index is invalid
   */
  public DateTimeFieldType getFieldType(int index) {
    return FIELD_TYPES[index];
  }

  /**
   * Gets an array of the field type of each of the fields that this partial supports.
   *
   * <p>The fields are returned largest to smallest, Hour, Minute, Second, Millis.
   *
   * @return the array of field types (cloned), largest to smallest
   */
  public DateTimeFieldType[] getFieldTypes() {
    DateTimeFieldType[] ret = new DateTimeFieldType[FIELD_TYPES.length];
    ArrayUtils.copyArray(FIELD_TYPES, ret);
    return ret;
  }

  // -----------------------------------------------------------------------
  /**
   * Returns a copy of this time with the specified chronology. This instance is immutable and
   * unaffected by this method call.
   *
   * <p>This method retains the values of the fields, thus the result will typically refer to a
   * different instant.
   *
   * <p>The time zone of the specified chronology is ignored, as TimeOfDay operates without a time
   * zone.
   *
   * @param newChronology the new chronology, null means ISO
   * @return a copy of this datetime with a different chronology
   * @throws IllegalArgumentException if the values are invalid for the new chronology
   */
  public TimeOfDay withChronologyRetainFields(Chronology newChronology) {
    newChronology = DateTimeUtils.getChronology(newChronology);
    newChronology = newChronology.withUTC();
    if (newChronology == getChronology()) {
      return this;
    } else {
      TimeOfDay newTimeOfDay = new TimeOfDay(this, newChronology);
      newChronology.validate(newTimeOfDay, getValues());
      return newTimeOfDay;
    }
  }

  /**
   * Returns a copy of this time with the specified field set to a new value.
   *
   * <p>For example, if the field type is <code>minuteOfHour</code> then the day would be changed in
   * the returned instance.
   *
   * <p>These three lines are equivalent:
   *
   * <pre>
   * TimeOfDay updated = tod.withField(DateTimeFieldType.minuteOfHour(), 6);
   * TimeOfDay updated = tod.minuteOfHour().setCopy(6);
   * TimeOfDay updated = tod.property(DateTimeFieldType.minuteOfHour()).setCopy(6);
   * </pre>
   *
   * @param fieldType the field type to set, not null
   * @param value the value to set
   * @return a copy of this instance with the field set
   * @throws IllegalArgumentException if the value is null or invalid
   */
  public TimeOfDay withField(DateTimeFieldType fieldType, int value) {
    int index = indexOfSupported(fieldType);
    if (value == getValue(index)) {
      return this;
    }
    int[] newValues = getValues();
    newValues = getField(index).set(this, index, newValues, value);
    return new TimeOfDay(this, newValues);
  }

  /**
   * Returns a copy of this time with the value of the specified field increased, wrapping to what
   * would be a new day if required.
   *
   * <p>If the addition is zero, then <code>this</code> is returned.
   *
   * <p>These three lines are equivalent:
   *
   * <pre>
   * TimeOfDay added = tod.withFieldAdded(DurationFieldType.minutes(), 6);
   * TimeOfDay added = tod.plusMinutes(6);
   * TimeOfDay added = tod.minuteOfHour().addToCopy(6);
   * </pre>
   *
   * @param fieldType the field type to add to, not null
   * @param amount the amount to add
   * @return a copy of this instance with the field updated
   * @throws IllegalArgumentException if the value is null or invalid
   * @throws ArithmeticException if the new datetime exceeds the capacity
   */
  public TimeOfDay withFieldAdded(DurationFieldType fieldType, int amount) {
    int index = indexOfSupported(fieldType);
    if (amount == 0) {
      return this;
    }
    int[] newValues = getValues();
    newValues = getField(index).addWrapPartial(this, index, newValues, amount);
    return new TimeOfDay(this, newValues);
  }

  /**
   * Returns a copy of this time with the specified period added, wrapping to what would be a new
   * day if required.
   *
   * <p>If the addition is zero, then <code>this</code> is returned. Fields in the period that
   * aren't present in the partial are ignored.
   *
   * <p>This method is typically used to add multiple copies of complex period instances. Adding one
   * field is best achieved using methods like {@link #withFieldAdded(DurationFieldType, int)} or
   * {@link #plusHours(int)}.
   *
   * @param period the period to add to this one, null means zero
   * @param scalar the amount of times to add, such as -1 to subtract once
   * @return a copy of this instance with the period added
   * @throws ArithmeticException if the new datetime exceeds the capacity
   */
  public TimeOfDay withPeriodAdded(ReadablePeriod period, int scalar) {
    if (period == null || scalar == 0) {
      return this;
    }
    int[] newValues = getValues();
    for (int i = 0; i < period.size(); i++) {
      DurationFieldType fieldType = period.getFieldType(i);
      int index = indexOf(fieldType);
      if (index >= 0) {
        newValues =
            getField(index)
                .addWrapPartial(
                    this, index, newValues, FieldUtils.safeMultiply(period.getValue(i), scalar));
      }
    }
    return new TimeOfDay(this, newValues);
  }

  // -----------------------------------------------------------------------
  /**
   * Returns a copy of this time with the specified period added, wrapping to what would be a new
   * day if required.
   *
   * <p>If the amount is zero or null, then <code>this</code> is returned.
   *
   * <p>This method is typically used to add complex period instances. Adding one field is best
   * achieved using methods like {@link #plusHours(int)}.
   *
   * @param period the duration to add to this one, null means zero
   * @return a copy of this instance with the period added
   * @throws ArithmeticException if the new datetime exceeds the capacity of a long
   */
  public TimeOfDay plus(ReadablePeriod period) {
    return withPeriodAdded(period, 1);
  }

  // -----------------------------------------------------------------------
  /**
   * Returns a copy of this time plus the specified number of hours.
   *
   * <p>This time instance is immutable and unaffected by this method call.
   *
   * <p>The following three lines are identical in effect:
   *
   * <pre>
   * TimeOfDay added = dt.plusHours(6);
   * TimeOfDay added = dt.plus(Period.hours(6));
   * TimeOfDay added = dt.withFieldAdded(DurationFieldType.hours(), 6);
   * </pre>
   *
   * @param hours the amount of hours to add, may be negative
   * @return the new time plus the increased hours
   * @since 1.1
   */
  public TimeOfDay plusHours(int hours) {
    return withFieldAdded(DurationFieldType.hours(), hours);
  }

  /**
   * Returns a copy of this time plus the specified number of minutes.
   *
   * <p>This time instance is immutable and unaffected by this method call.
   *
   * <p>The following three lines are identical in effect:
   *
   * <pre>
   * TimeOfDay added = dt.plusMinutes(6);
   * TimeOfDay added = dt.plus(Period.minutes(6));
   * TimeOfDay added = dt.withFieldAdded(DurationFieldType.minutes(), 6);
   * </pre>
   *
   * @param minutes the amount of minutes to add, may be negative
   * @return the new time plus the increased minutes
   * @since 1.1
   */
  public TimeOfDay plusMinutes(int minutes) {
    return withFieldAdded(DurationFieldType.minutes(), minutes);
  }

  /**
   * Returns a copy of this time plus the specified number of seconds.
   *
   * <p>This time instance is immutable and unaffected by this method call.
   *
   * <p>The following three lines are identical in effect:
   *
   * <pre>
   * TimeOfDay added = dt.plusSeconds(6);
   * TimeOfDay added = dt.plus(Period.seconds(6));
   * TimeOfDay added = dt.withFieldAdded(DurationFieldType.seconds(), 6);
   * </pre>
   *
   * @param seconds the amount of seconds to add, may be negative
   * @return the new time plus the increased seconds
   * @since 1.1
   */
  public TimeOfDay plusSeconds(int seconds) {
    return withFieldAdded(DurationFieldType.seconds(), seconds);
  }

  /**
   * Returns a copy of this time plus the specified number of millis.
   *
   * <p>This time instance is immutable and unaffected by this method call.
   *
   * <p>The following three lines are identical in effect:
   *
   * <pre>
   * TimeOfDay added = dt.plusMillis(6);
   * TimeOfDay added = dt.plus(Period.millis(6));
   * TimeOfDay added = dt.withFieldAdded(DurationFieldType.millis(), 6);
   * </pre>
   *
   * @param millis the amount of millis to add, may be negative
   * @return the new time plus the increased millis
   * @since 1.1
   */
  public TimeOfDay plusMillis(int millis) {
    return withFieldAdded(DurationFieldType.millis(), millis);
  }

  // -----------------------------------------------------------------------
  /**
   * Returns a copy of this time with the specified period taken away, wrapping to what would be a
   * new day if required.
   *
   * <p>If the amount is zero or null, then <code>this</code> is returned.
   *
   * <p>This method is typically used to subtract complex period instances. Subtracting one field is
   * best achieved using methods like {@link #minusHours(int)}.
   *
   * @param period the period to reduce this instant by
   * @return a copy of this instance with the period taken away
   * @throws ArithmeticException if the new time exceeds capacity
   */
  public TimeOfDay minus(ReadablePeriod period) {
    return withPeriodAdded(period, -1);
  }

  // -----------------------------------------------------------------------
  /**
   * Returns a copy of this time minus the specified number of hours.
   *
   * <p>This time instance is immutable and unaffected by this method call.
   *
   * <p>The following three lines are identical in effect:
   *
   * <pre>
   * TimeOfDay subtracted = dt.minusHours(6);
   * TimeOfDay subtracted = dt.minus(Period.hours(6));
   * TimeOfDay subtracted = dt.withFieldAdded(DurationFieldType.hours(), -6);
   * </pre>
   *
   * @param hours the amount of hours to subtract, may be negative
   * @return the new time minus the increased hours
   * @since 1.1
   */
  public TimeOfDay minusHours(int hours) {
    return withFieldAdded(DurationFieldType.hours(), FieldUtils.safeNegate(hours));
  }

  /**
   * Returns a copy of this time minus the specified number of minutes.
   *
   * <p>This time instance is immutable and unaffected by this method call.
   *
   * <p>The following three lines are identical in effect:
   *
   * <pre>
   * TimeOfDay subtracted = dt.minusMinutes(6);
   * TimeOfDay subtracted = dt.minus(Period.minutes(6));
   * TimeOfDay subtracted = dt.withFieldAdded(DurationFieldType.minutes(), -6);
   * </pre>
   *
   * @param minutes the amount of minutes to subtract, may be negative
   * @return the new time minus the increased minutes
   * @since 1.1
   */
  public TimeOfDay minusMinutes(int minutes) {
    return withFieldAdded(DurationFieldType.minutes(), FieldUtils.safeNegate(minutes));
  }

  /**
   * Returns a copy of this time minus the specified number of seconds.
   *
   * <p>This time instance is immutable and unaffected by this method call.
   *
   * <p>The following three lines are identical in effect:
   *
   * <pre>
   * TimeOfDay subtracted = dt.minusSeconds(6);
   * TimeOfDay subtracted = dt.minus(Period.seconds(6));
   * TimeOfDay subtracted = dt.withFieldAdded(DurationFieldType.seconds(), -6);
   * </pre>
   *
   * @param seconds the amount of seconds to subtract, may be negative
   * @return the new time minus the increased seconds
   * @since 1.1
   */
  public TimeOfDay minusSeconds(int seconds) {
    return withFieldAdded(DurationFieldType.seconds(), FieldUtils.safeNegate(seconds));
  }

  /**
   * Returns a copy of this time minus the specified number of millis.
   *
   * <p>This time instance is immutable and unaffected by this method call.
   *
   * <p>The following three lines are identical in effect:
   *
   * <pre>
   * TimeOfDay subtracted = dt.minusMillis(6);
   * TimeOfDay subtracted = dt.minus(Period.millis(6));
   * TimeOfDay subtracted = dt.withFieldAdded(DurationFieldType.millis(), -6);
   * </pre>
   *
   * @param millis the amount of millis to subtract, may be negative
   * @return the new time minus the increased millis
   * @since 1.1
   */
  public TimeOfDay minusMillis(int millis) {
    return withFieldAdded(DurationFieldType.millis(), FieldUtils.safeNegate(millis));
  }

  // -----------------------------------------------------------------------
  /**
   * Gets the property object for the specified type, which contains many useful methods.
   *
   * @param type the field type to get the property for
   * @return the property object
   * @throws IllegalArgumentException if the field is null or unsupported
   */
  public Property property(DateTimeFieldType type) {
    return new Property(this, indexOfSupported(type));
  }

  // -----------------------------------------------------------------------
  /**
   * Converts this object to a LocalTime with the same time and chronology.
   *
   * @return a LocalTime with the same time and chronology
   * @since 1.3
   */
  public LocalTime toLocalTime() {
    return new LocalTime(
        getHourOfDay(),
        getMinuteOfHour(),
        getSecondOfMinute(),
        getMillisOfSecond(),
        getChronology());
  }

  // -----------------------------------------------------------------------
  /**
   * Converts this partial to a full datetime using the default time zone setting the time fields
   * from this instance and the date fields from the current time.
   *
   * @return this date as a datetime with the time as the current time
   */
  public DateTime toDateTimeToday() {
    return toDateTimeToday(null);
  }

  /**
   * Converts this partial to a full datetime using the specified time zone setting the time fields
   * from this instance and the date fields from the current time.
   *
   * <p>This method uses the chronology from this instance plus the time zone specified.
   *
   * @param zone the zone to use, null means default
   * @return this date as a datetime with the time as the current time
   */
  public DateTime toDateTimeToday(DateTimeZone zone) {
    Chronology chrono = getChronology().withZone(zone);
    long instantMillis = DateTimeUtils.currentTimeMillis();
    long resolved = chrono.set(this, instantMillis);
    return new DateTime(resolved, chrono);
  }

  // -----------------------------------------------------------------------
  /**
   * Get the hour of day (0-23) field value.
   *
   * @return the hour of day
   */
  public int getHourOfDay() {
    return getValue(HOUR_OF_DAY);
  }

  /**
   * Get the minute of hour field value.
   *
   * @return the minute of hour
   */
  public int getMinuteOfHour() {
    return getValue(MINUTE_OF_HOUR);
  }

  /**
   * Get the second of minute field value.
   *
   * @return the second of minute
   */
  public int getSecondOfMinute() {
    return getValue(SECOND_OF_MINUTE);
  }

  /**
   * Get the millis of second field value.
   *
   * @return the millis of second
   */
  public int getMillisOfSecond() {
    return getValue(MILLIS_OF_SECOND);
  }

  // -----------------------------------------------------------------------
  /**
   * Returns a copy of this time with the hour of day field updated.
   *
   * <p>TimeOfDay is immutable, so there are no set methods. Instead, this method returns a new
   * instance with the value of hour of day changed.
   *
   * @param hour the hour of day to set
   * @return a copy of this object with the field set
   * @throws IllegalArgumentException if the value is invalid
   * @since 1.3
   */
  public TimeOfDay withHourOfDay(int hour) {
    int[] newValues = getValues();
    newValues = getChronology().hourOfDay().set(this, HOUR_OF_DAY, newValues, hour);
    return new TimeOfDay(this, newValues);
  }

  /**
   * Returns a copy of this time with the minute of hour field updated.
   *
   * <p>TimeOfDay is immutable, so there are no set methods. Instead, this method returns a new
   * instance with the value of minute of hour changed.
   *
   * @param minute the minute of hour to set
   * @return a copy of this object with the field set
   * @throws IllegalArgumentException if the value is invalid
   * @since 1.3
   */
  public TimeOfDay withMinuteOfHour(int minute) {
    int[] newValues = getValues();
    newValues = getChronology().minuteOfHour().set(this, MINUTE_OF_HOUR, newValues, minute);
    return new TimeOfDay(this, newValues);
  }

  /**
   * Returns a copy of this time with the second of minute field updated.
   *
   * <p>TimeOfDay is immutable, so there are no set methods. Instead, this method returns a new
   * instance with the value of second of minute changed.
   *
   * @param second the second of minute to set
   * @return a copy of this object with the field set
   * @throws IllegalArgumentException if the value is invalid
   * @since 1.3
   */
  public TimeOfDay withSecondOfMinute(int second) {
    int[] newValues = getValues();
    newValues = getChronology().secondOfMinute().set(this, SECOND_OF_MINUTE, newValues, second);
    return new TimeOfDay(this, newValues);
  }

  /**
   * Returns a copy of this time with the millis of second field updated.
   *
   * <p>TimeOfDay is immutable, so there are no set methods. Instead, this method returns a new
   * instance with the value of millis of second changed.
   *
   * @param millis the millis of second to set
   * @return a copy of this object with the field set
   * @throws IllegalArgumentException if the value is invalid
   * @since 1.3
   */
  public TimeOfDay withMillisOfSecond(int millis) {
    int[] newValues = getValues();
    newValues = getChronology().millisOfSecond().set(this, MILLIS_OF_SECOND, newValues, millis);
    return new TimeOfDay(this, newValues);
  }

  // -----------------------------------------------------------------------
  /**
   * Get the hour of day field property which provides access to advanced functionality.
   *
   * @return the hour of day property
   */
  public Property hourOfDay() {
    return new Property(this, HOUR_OF_DAY);
  }

  /**
   * Get the minute of hour field property which provides access to advanced functionality.
   *
   * @return the minute of hour property
   */
  public Property minuteOfHour() {
    return new Property(this, MINUTE_OF_HOUR);
  }

  /**
   * Get the second of minute field property which provides access to advanced functionality.
   *
   * @return the second of minute property
   */
  public Property secondOfMinute() {
    return new Property(this, SECOND_OF_MINUTE);
  }

  /**
   * Get the millis of second property which provides access to advanced functionality.
   *
   * @return the millis of second property
   */
  public Property millisOfSecond() {
    return new Property(this, MILLIS_OF_SECOND);
  }

  // -----------------------------------------------------------------------
  /**
   * Output the time in the ISO8601 format THH:mm:ss.SSS.
   *
   * @return ISO8601 formatted string
   */
  public String toString() {
    return ISODateTimeFormat.tTime().print(this);
  }

  // -----------------------------------------------------------------------
  /**
   * The property class for <code>TimeOfDay</code>.
   *
   * <p>This class binds a <code>TimeOfDay</code> to a <code>DateTimeField</code>.
   *
   * @author Stephen Colebourne
   * @since 1.0
   * @deprecated Use LocalTime which has a much better internal implementation
   */
  public static class Property extends AbstractPartialFieldProperty implements Serializable {

    /** Serialization version */
    private static final long serialVersionUID = 5598459141741063833L;

    /** The partial */
    private final TimeOfDay iTimeOfDay;
    /** The field index */
    private final int iFieldIndex;

    /**
     * Constructs a property.
     *
     * @param partial the partial instance
     * @param fieldIndex the index in the partial
     */
    Property(TimeOfDay partial, int fieldIndex) {
      super();
      iTimeOfDay = partial;
      iFieldIndex = fieldIndex;
    }

    /**
     * Gets the field that this property uses.
     *
     * @return the field
     */
    public DateTimeField getField() {
      return iTimeOfDay.getField(iFieldIndex);
    }

    /**
     * Gets the partial that this property belongs to.
     *
     * @return the partial
     */
    protected ReadablePartial getReadablePartial() {
      return iTimeOfDay;
    }

    /**
     * Gets the partial that this property belongs to.
     *
     * @return the partial
     */
    public TimeOfDay getTimeOfDay() {
      return iTimeOfDay;
    }

    /**
     * Gets the value of this field.
     *
     * @return the field value
     */
    public int get() {
      return iTimeOfDay.getValue(iFieldIndex);
    }

    // -----------------------------------------------------------------------
    /**
     * Adds to the value of this field in a copy of this TimeOfDay, wrapping to what would be the
     * next day if necessary.
     *
     * <p>The value will be added to this field. If the value is too large to be added solely to
     * this field then it will affect larger fields. Smaller fields are unaffected.
     *
     * <p>If the result would be too large, beyond 23:59:59:999, then the calculation wraps to
     * 00:00:00.000. For the alternate strict behaviour with no wrapping see {@link
     * #addNoWrapToCopy(int)}.
     *
     * <p>The TimeOfDay attached to this property is unchanged by this call. Instead, a new instance
     * is returned.
     *
     * @param valueToAdd the value to add to the field in the copy
     * @return a copy of the TimeOfDay with the field value changed
     * @throws IllegalArgumentException if the value isn't valid
     */
    public TimeOfDay addToCopy(int valueToAdd) {
      int[] newValues = iTimeOfDay.getValues();
      newValues = getField().addWrapPartial(iTimeOfDay, iFieldIndex, newValues, valueToAdd);
      return new TimeOfDay(iTimeOfDay, newValues);
    }

    /**
     * Adds to the value of this field in a copy of this TimeOfDay, throwing an Exception if the
     * bounds are exceeded.
     *
     * <p>The value will be added to this field. If the value is too large to be added solely to
     * this field then it will affect larger fields. Smaller fields are unaffected.
     *
     * <p>If the result would be too large (beyond 23:59:59:999) or too small (less than
     * 00:00:00.000) then an Execption is thrown. For the alternate behaviour which wraps to the
     * next 'day', see {@link #addToCopy(int)}.
     *
     * <p>The TimeOfDay attached to this property is unchanged by this call. Instead, a new instance
     * is returned.
     *
     * @param valueToAdd the value to add to the field in the copy
     * @return a copy of the TimeOfDay with the field value changed
     * @throws IllegalArgumentException if the value isn't valid
     */
    public TimeOfDay addNoWrapToCopy(int valueToAdd) {
      int[] newValues = iTimeOfDay.getValues();
      newValues = getField().add(iTimeOfDay, iFieldIndex, newValues, valueToAdd);
      return new TimeOfDay(iTimeOfDay, newValues);
    }

    /**
     * Adds to the value of this field in a copy of this TimeOfDay wrapping within this field if the
     * maximum value is reached.
     *
     * <p>The value will be added to this field. If the value is too large to be added solely to
     * this field then it wraps within this field. Other fields are unaffected.
     *
     * <p>For example, <code>12:59:37</code> addWrapField one minute returns <code>12:00:37</code>.
     *
     * <p>The TimeOfDay attached to this property is unchanged by this call. Instead, a new instance
     * is returned.
     *
     * @param valueToAdd the value to add to the field in the copy
     * @return a copy of the TimeOfDay with the field value changed
     * @throws IllegalArgumentException if the value isn't valid
     */
    public TimeOfDay addWrapFieldToCopy(int valueToAdd) {
      int[] newValues = iTimeOfDay.getValues();
      newValues = getField().addWrapField(iTimeOfDay, iFieldIndex, newValues, valueToAdd);
      return new TimeOfDay(iTimeOfDay, newValues);
    }

    // -----------------------------------------------------------------------
    /**
     * Sets this field in a copy of the TimeOfDay.
     *
     * <p>The TimeOfDay attached to this property is unchanged by this call. Instead, a new instance
     * is returned.
     *
     * @param value the value to set the field in the copy to
     * @return a copy of the TimeOfDay with the field value changed
     * @throws IllegalArgumentException if the value isn't valid
     */
    public TimeOfDay setCopy(int value) {
      int[] newValues = iTimeOfDay.getValues();
      newValues = getField().set(iTimeOfDay, iFieldIndex, newValues, value);
      return new TimeOfDay(iTimeOfDay, newValues);
    }

    /**
     * Sets this field in a copy of the TimeOfDay to a parsed text value.
     *
     * <p>The TimeOfDay attached to this property is unchanged by this call. Instead, a new instance
     * is returned.
     *
     * @param text the text value to set
     * @param locale optional locale to use for selecting a text symbol
     * @return a copy of the TimeOfDay with the field value changed
     * @throws IllegalArgumentException if the text value isn't valid
     */
    public TimeOfDay setCopy(String text, Locale locale) {
      int[] newValues = iTimeOfDay.getValues();
      newValues = getField().set(iTimeOfDay, iFieldIndex, newValues, text, locale);
      return new TimeOfDay(iTimeOfDay, newValues);
    }

    /**
     * Sets this field in a copy of the TimeOfDay to a parsed text value.
     *
     * <p>The TimeOfDay attached to this property is unchanged by this call. Instead, a new instance
     * is returned.
     *
     * @param text the text value to set
     * @return a copy of the TimeOfDay with the field value changed
     * @throws IllegalArgumentException if the text value isn't valid
     */
    public TimeOfDay setCopy(String text) {
      return setCopy(text, null);
    }

    // -----------------------------------------------------------------------
    /**
     * Returns a new TimeOfDay with this field set to the maximum value for this field.
     *
     * <p>The TimeOfDay attached to this property is unchanged by this call.
     *
     * @return a copy of the TimeOfDay with this field set to its maximum
     * @since 1.2
     */
    public TimeOfDay withMaximumValue() {
      return setCopy(getMaximumValue());
    }

    /**
     * Returns a new TimeOfDay with this field set to the minimum value for this field.
     *
     * <p>The TimeOfDay attached to this property is unchanged by this call.
     *
     * @return a copy of the TimeOfDay with this field set to its minimum
     * @since 1.2
     */
    public TimeOfDay withMinimumValue() {
      return setCopy(getMinimumValue());
    }
  }
}
Exemple #16
0
 /** Reads the property from a safe serialization format. */
 private void readObject(ObjectInputStream oos) throws IOException, ClassNotFoundException {
   iInstant = (MutableDateTime) oos.readObject();
   DateTimeFieldType type = (DateTimeFieldType) oos.readObject();
   iField = type.getField(iInstant.getChronology());
 }