gt:         Chronology chrono = getChronology().withZone(zone);
context: /*
   *  Copyright 2001-2013 Stephen Colebourne
   *
   *  Licensed under the Apache License, Version 2.0 (the "License");
   *  you may not use this file except in compliance with the License.
   *  You may obtain a copy of the License at
   *
   *      http://www.apache.org/licenses/LICENSE-2.0
   *
   *  Unless required by applicable law or agreed to in writing, software
   *  distributed under the License is distributed on an "AS IS" BASIS,
   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   *  See the License for the specific language governing permissions and
   *  limitations under the License.
   */
  package org.joda.time;
  
  import java.io.IOException;
  import java.io.ObjectInputStream;
  import java.io.ObjectOutputStream;
  import java.io.Serializable;
  import java.util.Calendar;
  import java.util.Date;
  import java.util.GregorianCalendar;
  import java.util.HashSet;
  import java.util.Locale;
  import java.util.Set;
  import java.util.TimeZone;
  
  import org.joda.convert.FromString;
  import org.joda.convert.ToString;
  import org.joda.time.base.BaseLocal;
  import org.joda.time.chrono.ISOChronology;
  import org.joda.time.convert.ConverterManager;
  import org.joda.time.convert.PartialConverter;
  import org.joda.time.field.AbstractReadableInstantFieldProperty;
  import org.joda.time.field.FieldUtils;
  import org.joda.time.format.DateTimeFormat;
  import org.joda.time.format.DateTimeFormatter;
  import org.joda.time.format.ISODateTimeFormat;
  
  /**
   * LocalDate is an immutable datetime class representing a date
   * without a time zone.
   * <p>
   * LocalDate implements the {@link ReadablePartial} interface.
   * To do this, the interface methods focus on the key fields -
   * Year, MonthOfYear and DayOfMonth.
   * However, <b>all</b> date fields may in fact be queried.
   * <p>
   * LocalDate differs from DateMidnight in that this class does not
   * have a time zone and does not represent a single instant in time.
   * <p>
   * Calculations on LocalDate are performed using a {@link Chronology}.
   * This chronology will be set internally to be in the UTC time zone
   * for all calculations.
   *
   * <p>Each individual field can be queried in two ways:
   * <ul>
   * <li><code>getMonthOfYear()</code>
   * <li><code>monthOfYear().get()</code>
   * </ul>
   * The second technique also provides access to other useful methods on the
   * field:
   * <ul>
   * <li>numeric value
   * <li>text value
   * <li>short text value
   * <li>maximum/minimum values
   * <li>add/subtract
   * <li>set
   * <li>rounding
   * </ul>
   *
   * <p>
   * LocalDate 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
   * @since 1.3
   */
  public final class LocalDate
          extends BaseLocal
          implements ReadablePartial, Serializable {
  
      /** Serialization lock */
      private static final long serialVersionUID = -8775358157899L;
  
      /** The index of the year field in the field array */
      private static final int YEAR = 0;
      /** The index of the monthOfYear field in the field array */
      private static final int MONTH_OF_YEAR = 1;
      /** The index of the dayOfMonth field in the field array */
      private static final int DAY_OF_MONTH = 2;
      /** Set of known duration types. */
      private static final Set<DurationFieldType> DATE_DURATION_TYPES = new HashSet<DurationFieldType>();
      static {
          DATE_DURATION_TYPES.add(DurationFieldType.days());
          DATE_DURATION_TYPES.add(DurationFieldType.weeks());
          DATE_DURATION_TYPES.add(DurationFieldType.months());
          DATE_DURATION_TYPES.add(DurationFieldType.weekyears());
          DATE_DURATION_TYPES.add(DurationFieldType.years());
          DATE_DURATION_TYPES.add(DurationFieldType.centuries());
          // eras are supported, although the DurationField generally isn't
          DATE_DURATION_TYPES.add(DurationFieldType.eras());
      }
  
      /** The local millis from 1970-01-01T00:00:00 */
      private final long iLocalMillis;
      /** The chronology to use in UTC. */
      private final Chronology iChronology;
      /** The cached hash code. */
      private transient volatile int iHash;
  
      //-----------------------------------------------------------------------
      /**
       * Obtains a {@code LocalDate} set to the current system millisecond time
       * using <code>ISOChronology</code> in the default time zone.
       * 
       * @return the current date-time, not null
       * @since 2.0
       */
      public static LocalDate now() {
          return new LocalDate();
      }
  
      /**
       * Obtains a {@code LocalDate} set to the current system millisecond time
       * using <code>ISOChronology</code> in the specified time zone.
       *
       * @param zone  the time zone, not null
       * @return the current date-time, not null
       * @since 2.0
       */
      public static LocalDate now(DateTimeZone zone) {
          if (zone == null) {
              throw new NullPointerException("Zone must not be null");
          }
          return new LocalDate(zone);
      }
  
      /**
       * Obtains a {@code LocalDate} set to the current system millisecond time
       * using the specified chronology.
       *
       * @param chronology  the chronology, not null
       * @return the current date-time, not null
       * @since 2.0
       */
      public static LocalDate now(Chronology chronology) {
          if (chronology == null) {
              throw new NullPointerException("Chronology must not be null");
          }
          return new LocalDate(chronology);
      }
  
      //-----------------------------------------------------------------------
      /**
       * Parses a {@code LocalDate} from the specified string.
       * <p>
       * This uses {@link ISODateTimeFormat#localDateParser()}.
       * 
       * @param str  the string to parse, not null
       * @since 2.0
       */
      @FromString
      public static LocalDate parse(String str) {
          return parse(str, ISODateTimeFormat.localDateParser());
      }
  
      /**
       * Parses a {@code LocalDate} from the specified string using a formatter.
       * 
       * @param str  the string to parse, not null
       * @param formatter  the formatter to use, not null
       * @since 2.0
       */
      public static LocalDate parse(String str, DateTimeFormatter formatter) {
          return formatter.parseLocalDate(str);
      }
  
      //-----------------------------------------------------------------------
      /**
       * Constructs a LocalDate from a <code>java.util.Calendar</code>
       * using exactly the same field values.
       * <p>
       * Each field is queried from the Calendar and assigned to the LocalDate.
       * This is useful if you have been using the Calendar as a local date,
       * ignoring the zone.
       * <p>
       * One advantage of this method is that this method is unaffected if the
       * version of the time zone data differs between the JDK and Joda-Time.
       * That is because the local field values are transferred, calculated using
       * the JDK time zone data and without using the Joda-Time time zone data.
       * <p>
       * This factory method ignores the type of the calendar and always
       * creates a LocalDate with ISO chronology. It is expected that you
       * will only pass in instances of <code>GregorianCalendar</code> however
       * this is not validated.
       *
       * @param calendar  the Calendar to extract fields from, not null
       * @return the created local date, not null
       * @throws IllegalArgumentException if the calendar is null
       * @throws IllegalArgumentException if the date is invalid for the ISO chronology
       */
      public static LocalDate fromCalendarFields(Calendar calendar) {
          if (calendar == null) {
              throw new IllegalArgumentException("The calendar must not be null");
          }
          int era = calendar.get(Calendar.ERA);
          int yearOfEra = calendar.get(Calendar.YEAR);
          return new LocalDate(
              (era == GregorianCalendar.AD ? yearOfEra : 1 - yearOfEra),
              calendar.get(Calendar.MONTH) + 1,
              calendar.get(Calendar.DAY_OF_MONTH)
          );
      }
  
      /**
       * Constructs a LocalDate from a <code>java.util.Date</code>
       * using exactly the same field values.
       * <p>
       * Each field is queried from the Date and assigned to the LocalDate.
       * This is useful if you have been using the Date as a local date,
       * ignoring the zone.
       * <p>
       * One advantage of this method is that this method is unaffected if the
       * version of the time zone data differs between the JDK and Joda-Time.
       * That is because the local field values are transferred, calculated using
       * the JDK time zone data and without using the Joda-Time time zone data.
       * <p>
       * This factory method always creates a LocalDate with ISO chronology.
       *
       * @param date  the Date to extract fields from, not null
       * @return the created local date, not null
       * @throws IllegalArgumentException if the calendar is null
       * @throws IllegalArgumentException if the date is invalid for the ISO chronology
       */
      @SuppressWarnings("deprecation")
      public static LocalDate fromDateFields(Date date) {
          if (date == null) {
              throw new IllegalArgumentException("The date must not be null");
          }
          if (date.getTime() < 0) {
              // handle years in era BC
              GregorianCalendar cal = new GregorianCalendar();
              cal.setTime(date);
              return fromCalendarFields(cal);
          }
          return new LocalDate(
              date.getYear() + 1900,
              date.getMonth() + 1,
              date.getDate()
          );
      }
  
      //-----------------------------------------------------------------------
      /**
       * Constructs an instance set to the current local time evaluated using
       * ISO chronology in the default zone.
       * <p>
       * Once the constructor is completed, the zone is no longer used.
       * 
       * @see #now()
       */
      public LocalDate() {
          this(DateTimeUtils.currentTimeMillis(), ISOChronology.getInstance());
      }
  
      /**
       * Constructs an instance set to the current local time evaluated using
       * ISO chronology in the specified zone.
       * <p>
       * If the specified time zone is null, the default zone is used.
       * Once the constructor is completed, the zone is no longer used.
       *
       * @param zone  the time zone, null means default zone
       * @see #now(DateTimeZone)
       */
      public LocalDate(DateTimeZone zone) {
          this(DateTimeUtils.currentTimeMillis(), ISOChronology.getInstance(zone));
      }
  
      /**
       * Constructs an instance set to the current local time evaluated using
       * specified chronology.
       * <p>
       * If the chronology is null, ISO chronology in the default time zone is used.
       * Once the constructor is completed, the zone is no longer used.
       *
       * @param chronology  the chronology, null means ISOChronology in default zone
       * @see #now(Chronology)
       */
      public LocalDate(Chronology chronology) {
          this(DateTimeUtils.currentTimeMillis(), chronology);
      }
  
      //-----------------------------------------------------------------------
      /**
       * Constructs an instance set to the local time defined by the specified
       * instant evaluated using ISO chronology in the default zone.
       * <p>
       * Once the constructor is completed, the zone is no longer used.
       *
       * @param instant  the milliseconds from 1970-01-01T00:00:00Z
       */
      public LocalDate(long instant) {
          this(instant, ISOChronology.getInstance());
      }
  
      /**
       * Constructs an instance set to the local time defined by the specified
       * instant evaluated using ISO chronology in the specified zone.
       * <p>
       * If the specified time zone is null, the default zone is used.
       * Once the constructor is completed, the zone is no longer used.
       *
       * @param instant  the milliseconds from 1970-01-01T00:00:00Z
       * @param zone  the time zone, null means default zone
       */
      public LocalDate(long instant, DateTimeZone zone) {
          this(instant, ISOChronology.getInstance(zone));
      }
  
      /**
       * Constructs an instance set to the local time defined by the specified
       * instant evaluated using the specified chronology.
       * <p>
       * If the chronology is null, ISO chronology in the default zone is used.
       * Once the constructor is completed, the zone is no longer used.
       *
       * @param instant  the milliseconds from 1970-01-01T00:00:00Z
       * @param chronology  the chronology, null means ISOChronology in default zone
       */
      public LocalDate(long instant, Chronology chronology) {
          chronology = DateTimeUtils.getChronology(chronology);
          
          long localMillis = chronology.getZone().getMillisKeepLocal(DateTimeZone.UTC, instant);
          chronology = chronology.withUTC();
          iLocalMillis = chronology.dayOfMonth().roundFloor(localMillis);
          iChronology = chronology;
      }
  
      //-----------------------------------------------------------------------
      /**
       * Constructs an instance from an Object that represents a datetime.
       * The time zone will be retrieved from the object if possible,
       * otherwise the default time zone will be used.
       * <p>
       * If the object contains no chronology, <code>ISOChronology</code> is used.
       * Once the constructor is completed, the zone is no longer used.
       * <p>
       * The recognised object types are defined in
       * {@link org.joda.time.convert.ConverterManager ConverterManager} and
       * include ReadablePartial, ReadableInstant, String, Calendar and Date.
       * The String formats are described by {@link ISODateTimeFormat#localDateParser()}.
       * The default String converter ignores the zone and only parses the field values.
       *
       * @param instant  the datetime object
       * @throws IllegalArgumentException if the instant is invalid
       */
      public LocalDate(Object instant) {
          this(instant, (Chronology) null);
      }
  
      /**
       * Constructs an instance from an Object that represents a datetime,
       * forcing the time zone to that specified.
       * <p>
       * If the object contains no chronology, <code>ISOChronology</code> is used.
       * If the specified time zone is null, the default zone is used.
       * Once the constructor is completed, the zone is no longer used.
       * <p>
       * The recognised object types are defined in
       * {@link org.joda.time.convert.ConverterManager ConverterManager} and
       * include ReadablePartial, ReadableInstant, String, Calendar and Date.
       * The String formats are described by {@link ISODateTimeFormat#localDateParser()}.
       * The default String converter ignores the zone and only parses the field values.
       *
       * @param instant  the datetime object
       * @param zone  the time zone
       * @throws IllegalArgumentException if the instant is invalid
       */
      public LocalDate(Object instant, DateTimeZone zone) {
          PartialConverter converter = ConverterManager.getInstance().getPartialConverter(instant);
          Chronology chronology = converter.getChronology(instant, zone);
          chronology = DateTimeUtils.getChronology(chronology);
          iChronology = chronology.withUTC();
          int[] values = converter.getPartialValues(this, instant, chronology, ISODateTimeFormat.localDateParser());
          iLocalMillis = iChronology.getDateTimeMillis(values[0], values[1], values[2], 0);
      }
  
      /**
       * Constructs an instance from an Object that represents a datetime,
       * using the specified chronology.
       * <p>
       * If the chronology is null, ISO in the default time zone is used.
       * Once the constructor is completed, the zone is no longer used.
       * If the instant contains a chronology, it will be ignored.
       * For example, passing a {@code LocalDate} and a different chronology
       * will return a date with the year/month/day from the date applied
       * unaltered to the specified chronology.
       * <p>
       * The recognised object types are defined in
       * {@link org.joda.time.convert.ConverterManager ConverterManager} and
       * include ReadablePartial, ReadableInstant, String, Calendar and Date.
       * The String formats are described by {@link ISODateTimeFormat#localDateParser()}.
       * The default String converter ignores the zone and only parses the field values.
       *
       * @param instant  the datetime object
       * @param chronology  the chronology
       * @throws IllegalArgumentException if the instant is invalid
       */
      public LocalDate(Object instant, Chronology chronology) {
          PartialConverter converter = ConverterManager.getInstance().getPartialConverter(instant);
          chronology = converter.getChronology(instant, chronology);
          chronology = DateTimeUtils.getChronology(chronology);
          iChronology = chronology.withUTC();
          int[] values = converter.getPartialValues(this, instant, chronology, ISODateTimeFormat.localDateParser());
          iLocalMillis = iChronology.getDateTimeMillis(values[0], values[1], values[2], 0);
      }
  
      //-----------------------------------------------------------------------
      /**
       * Constructs an instance set to the specified date and time
       * using <code>ISOChronology</code>.
       *
       * @param year  the year
       * @param monthOfYear  the month of the year, from 1 to 12
       * @param dayOfMonth  the day of the month, from 1 to 31
       */
      public LocalDate(
              int year,
              int monthOfYear,
              int dayOfMonth) {
          this(year, monthOfYear, dayOfMonth, ISOChronology.getInstanceUTC());
      }
  
      /**
       * Constructs an instance set to the specified date and time
       * using the specified chronology, whose zone is ignored.
       * <p>
       * If the chronology is null, <code>ISOChronology</code> is used.
       *
       * @param year  the year, valid values defined by the chronology
       * @param monthOfYear  the month of the year, valid values defined by the chronology
       * @param dayOfMonth  the day of the month, valid values defined by the chronology
       * @param chronology  the chronology, null means ISOChronology in default zone
       */
      public LocalDate(
              int year,
              int monthOfYear,
              int dayOfMonth,
              Chronology chronology) {
          super();
          chronology = DateTimeUtils.getChronology(chronology).withUTC();
          long instant = chronology.getDateTimeMillis(year, monthOfYear, dayOfMonth, 0);
          iChronology = chronology;
          iLocalMillis = instant;
      }
  
      /**
       * Handle broken serialization from other tools.
       * @return the resolved object, not null
       */
      private Object readResolve() {
          if (iChronology == null) {
              return new LocalDate(iLocalMillis, ISOChronology.getInstanceUTC());
          }
          if (DateTimeZone.UTC.equals(iChronology.getZone()) == false) {
              return new LocalDate(iLocalMillis, iChronology.withUTC());
          }
          return this;
      }
  
      //-----------------------------------------------------------------------
      /**
       * Gets the number of fields in this partial, which is three.
       * The supported fields are Year, MonthOfYear and DayOfMonth.
       * Note that all fields from day and above may in fact be queried via
       * other methods.
       *
       * @return the field count, three
       */
      public int size() {
          return 3;
      }
  
      /**
       * 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 YEAR:
                  return chrono.year();
              case MONTH_OF_YEAR:
                  return chrono.monthOfYear();
              case DAY_OF_MONTH:
                  return chrono.dayOfMonth();
              default:
                  throw new IndexOutOfBoundsException("Invalid index: " + index);
          }
      }
  
      /**
       * Gets the value of the field at the specifed index.
       * <p>
       * This method is required to support the <code>ReadablePartial</code>
       * interface. The supported fields are Year, MonthOfYear and DayOfMonth.
       * Note that all fields from day and above may in fact be queried via
       * other methods.
       *
       * @param index  the index, zero to two
       * @return the value
       * @throws IndexOutOfBoundsException if the index is invalid
       */
      public int getValue(int index) {
          switch (index) {
              case YEAR:
                  return getChronology().year().get(getLocalMillis());
              case MONTH_OF_YEAR:
                  return getChronology().monthOfYear().get(getLocalMillis());
              case DAY_OF_MONTH:
                  return getChronology().dayOfMonth().get(getLocalMillis());
              default:
                  throw new IndexOutOfBoundsException("Invalid index: " + index);
          }
      }
  
      //-----------------------------------------------------------------------
      /**
       * Get the value of one of the fields of a datetime.
       * <p>
       * This method gets the value of the specified field.
       * For example:
       * <pre>
       * LocalDate dt = LocalDate.nowDefaultZone();
       * int year = dt.get(DateTimeFieldType.year());
       * </pre>
       *
       * @param fieldType  a field type, usually obtained from DateTimeFieldType, not null
       * @return the value of that field
       * @throws IllegalArgumentException if the field type is null or unsupported
       */
      public int get(DateTimeFieldType fieldType) {
          if (fieldType == null) {
              throw new IllegalArgumentException("The DateTimeFieldType must not be null");
          }
          if (isSupported(fieldType) == false) {
              throw new IllegalArgumentException("Field '" + fieldType + "' is not supported");
          }
          return fieldType.getField(getChronology()).get(getLocalMillis());
      }
  
      /**
       * Checks if the field type specified is supported by this
       * local date and chronology.
       * This can be used to avoid exceptions in {@link #get(DateTimeFieldType)}.
       *
       * @param type  a field type, usually obtained from DateTimeFieldType
       * @return true if the field type is supported
       */
      public boolean isSupported(DateTimeFieldType type) {
          if (type == null) {
              return false;
          }
          DurationFieldType durType = type.getDurationType();
          if (DATE_DURATION_TYPES.contains(durType) ||
                  durType.getField(getChronology()).getUnitMillis() >=
                      getChronology().days().getUnitMillis()) {
              return type.getField(getChronology()).isSupported();
          }
          return false;
      }
  
      /**
       * Checks if the duration type specified is supported by this
       * local date and chronology.
       *
       * @param type  a duration type, usually obtained from DurationFieldType
       * @return true if the field type is supported
       */
      public boolean isSupported(DurationFieldType type) {
          if (type == null) {
              return false;
          }
          DurationField field = type.getField(getChronology());
          if (DATE_DURATION_TYPES.contains(type) ||
              field.getUnitMillis() >= getChronology().days().getUnitMillis()) {
              return field.isSupported();
          }
          return false;
      }
  
      //-----------------------------------------------------------------------
      /**
       * Gets the local milliseconds from the Java epoch
       * of 1970-01-01T00:00:00 (not fixed to any specific time zone).
       * 
       * @return the number of milliseconds since 1970-01-01T00:00:00
       * @since 1.5 (previously private)
       */
      protected long getLocalMillis() {
          return iLocalMillis;
      }
  
      /**
       * Gets the chronology of the date.
       * 
       * @return the Chronology that the date is using
       */
      public Chronology getChronology() {
          return iChronology;
      }
  
      //-----------------------------------------------------------------------
      /**
       * Compares this ReadablePartial with another returning true if the chronology,
       * field types and values are equal.
       *
       * @param partial  an object to check against
       * @return true if fields and values are equal
       */
      public boolean equals(Object partial) {
          // override to perform faster
          if (this == partial) {
              return true;
          }
          if (partial instanceof LocalDate) {
              LocalDate other = (LocalDate) partial;
              if (iChronology.equals(other.iChronology)) {
                  return iLocalMillis == other.iLocalMillis;
              }
          }
          return super.equals(partial);
      }
  
      /**
       * Gets a hash code for the instant as defined in <code>ReadablePartial</code>.
       *
       * @return a suitable hash code
       */
      public int hashCode() {
          // override for performance
          int hash = iHash;
          if (hash == 0) {
              hash = iHash = super.hashCode();
          }
          return hash;
      }
  
      /**
       * Compares this partial with another returning an integer
       * indicating the order.
       * <p>
       * The fields are compared in order, from largest to smallest.
       * The first field that is non-equal is used to determine the result.
       * <p>
       * The specified object must be a partial instance whose field types
       * match those of this partial.
       *
       * @param partial  an object to check against
       * @return negative if this is less, zero if equal, positive if greater
       * @throws ClassCastException if the partial is the wrong class
       *  or if it has field types that don't match
       * @throws NullPointerException if the partial is null
       */
      public int compareTo(ReadablePartial partial) {
          // override to perform faster
          if (this == partial) {
              return 0;
          }
          if (partial instanceof LocalDate) {
              LocalDate other = (LocalDate) partial;
              if (iChronology.equals(other.iChronology)) {
                  return (iLocalMillis < other.iLocalMillis ? -1 :
                              (iLocalMillis == other.iLocalMillis ? 0 : 1));
  
              }
          }
          return super.compareTo(partial);
      }
  
      //-----------------------------------------------------------------------
      /**
       * Converts this LocalDate to a full datetime at the earliest valid time
       * for the date using the default time zone.
       * <p>
       * The time will normally be midnight, as that is the earliest time on
       * any given day. However, in some time zones when Daylight Savings Time
       * starts, there is no midnight because time jumps from 11:59 to 01:00.
       * This method handles that situation by returning 01:00 on that date.
       * <p>
       * This instance is immutable and unaffected by this method call.
       * 
       * @return this date as a datetime at the start of the day
       * @since 1.5
       */
      public DateTime toDateTimeAtStartOfDay() {
          return toDateTimeAtStartOfDay(null);
      }
  
      /**
       * Converts this LocalDate to a full datetime at the earliest valid time
       * for the date using the specified time zone.
       * <p>
       * The time will normally be midnight, as that is the earliest time on
       * any given day. However, in some time zones when Daylight Savings Time
       * starts, there is no midnight because time jumps from 11:59 to 01:00.
       * This method handles that situation by returning 01:00 on that date.
       * <p>
       * This method uses the chronology from this instance plus the time zone
       * specified.
       * <p>
       * This instance is immutable and unaffected by this method call.
       *
       * @param zone  the zone to use, null means default zone
       * @return this date as a datetime at the start of the day
       * @since 1.5
       */
      public DateTime toDateTimeAtStartOfDay(DateTimeZone zone) {
          zone = DateTimeUtils.getZone(zone);
  