001/*
002 *  Copyright 2001-2013 Stephen Colebourne
003 *
004 *  Licensed under the Apache License, Version 2.0 (the "License");
005 *  you may not use this file except in compliance with the License.
006 *  You may obtain a copy of the License at
007 *
008 *      http://www.apache.org/licenses/LICENSE-2.0
009 *
010 *  Unless required by applicable law or agreed to in writing, software
011 *  distributed under the License is distributed on an "AS IS" BASIS,
012 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 *  See the License for the specific language governing permissions and
014 *  limitations under the License.
015 */
016package org.joda.time;
017
018import java.io.IOException;
019import java.io.ObjectInputStream;
020import java.io.ObjectOutputStream;
021import java.io.Serializable;
022import java.util.Calendar;
023import java.util.Date;
024import java.util.GregorianCalendar;
025import java.util.Locale;
026import java.util.TimeZone;
027
028import org.joda.convert.FromString;
029import org.joda.convert.ToString;
030import org.joda.time.base.BaseLocal;
031import org.joda.time.chrono.ISOChronology;
032import org.joda.time.convert.ConverterManager;
033import org.joda.time.convert.PartialConverter;
034import org.joda.time.field.AbstractReadableInstantFieldProperty;
035import org.joda.time.format.DateTimeFormat;
036import org.joda.time.format.DateTimeFormatter;
037import org.joda.time.format.ISODateTimeFormat;
038
039/**
040 * LocalDateTime is an unmodifiable datetime class representing a
041 * datetime without a time zone.
042 * <p>
043 * LocalDateTime implements the {@link ReadablePartial} interface.
044 * To do this, certain methods focus on key fields Year, MonthOfYear,
045 * DayOfYear and MillisOfDay.
046 * However, <b>all</b> fields may in fact be queried.
047 * <p>
048 * Internally, LocalDateTime uses a single millisecond-based value to
049 * represent the local datetime. This value is only used internally and
050 * is not exposed to applications.
051 * <p>
052 * Calculations on LocalDateTime are performed using a {@link Chronology}.
053 * This chronology will be set internally to be in the UTC time zone
054 * for all calculations.
055 *
056 * <p>Each individual field can be queried in two ways:
057 * <ul>
058 * <li><code>getHourOfDay()</code>
059 * <li><code>hourOfDay().get()</code>
060 * </ul>
061 * The second technique also provides access to other useful methods on the
062 * field:
063 * <ul>
064 * <li>numeric value
065 * <li>text value
066 * <li>short text value
067 * <li>maximum/minimum values
068 * <li>add/subtract
069 * <li>set
070 * <li>rounding
071 * </ul>
072 *
073 * <p>
074 * LocalDateTime is thread-safe and immutable, provided that the Chronology is as well.
075 * All standard Chronology classes supplied are thread-safe and immutable.
076 *
077 * @author Stephen Colebourne
078 * @since 1.3
079 */
080public final class LocalDateTime
081        extends BaseLocal
082        implements ReadablePartial, Serializable {
083
084    /** Serialization lock */
085    private static final long serialVersionUID = -268716875315837168L;
086
087    /** The index of the year field in the field array */
088    private static final int YEAR = 0;
089    /** The index of the monthOfYear field in the field array */
090    private static final int MONTH_OF_YEAR = 1;
091    /** The index of the dayOfMonth field in the field array */
092    private static final int DAY_OF_MONTH = 2;
093    /** The index of the millis field in the field array */
094    private static final int MILLIS_OF_DAY = 3;
095
096    /** The local millis from 1970-01-01T00:00:00 */
097    private final long iLocalMillis;
098    /** The chronology to use in UTC */
099    private final Chronology iChronology;
100
101    //-----------------------------------------------------------------------
102    /**
103     * Obtains a {@code LocalDateTime} set to the current system millisecond time
104     * using <code>ISOChronology</code> in the default time zone.
105     * The resulting object does not use the zone.
106     * 
107     * @return the current date, not null
108     * @since 2.0
109     */
110    public static LocalDateTime now() {
111        return new LocalDateTime();
112    }
113
114    /**
115     * Obtains a {@code LocalDateTime} set to the current system millisecond time
116     * using <code>ISOChronology</code> in the specified time zone.
117     * The resulting object does not use the zone.
118     *
119     * @param zone  the time zone, not null
120     * @return the current date, not null
121     * @since 2.0
122     */
123    public static LocalDateTime now(DateTimeZone zone) {
124        if (zone == null) {
125            throw new NullPointerException("Zone must not be null");
126        }
127        return new LocalDateTime(zone);
128    }
129
130    /**
131     * Obtains a {@code LocalDateTime} set to the current system millisecond time
132     * using the specified chronology.
133     * The resulting object does not use the zone.
134     *
135     * @param chronology  the chronology, not null
136     * @return the current date, not null
137     * @since 2.0
138     */
139    public static LocalDateTime now(Chronology chronology) {
140        if (chronology == null) {
141            throw new NullPointerException("Chronology must not be null");
142        }
143        return new LocalDateTime(chronology);
144    }
145
146    //-----------------------------------------------------------------------
147    /**
148     * Parses a {@code LocalDateTime} from the specified string.
149     * <p>
150     * This uses {@link ISODateTimeFormat#localDateOptionalTimeParser()}.
151     * 
152     * @param str  the string to parse, not null
153     * @since 2.0
154     */
155    @FromString
156    public static LocalDateTime parse(String str) {
157        return parse(str, ISODateTimeFormat.localDateOptionalTimeParser());
158    }
159
160    /**
161     * Parses a {@code LocalDateTime} from the specified string using a formatter.
162     * 
163     * @param str  the string to parse, not null
164     * @param formatter  the formatter to use, not null
165     * @since 2.0
166     */
167    public static LocalDateTime parse(String str, DateTimeFormatter formatter) {
168        return formatter.parseLocalDateTime(str);
169    }
170
171    //-----------------------------------------------------------------------
172    /**
173     * Constructs a LocalDateTime from a <code>java.util.Calendar</code>
174     * using exactly the same field values.
175     * <p>
176     * Each field is queried from the Calendar and assigned to the LocalDateTime.
177     * This is useful if you have been using the Calendar as a local date,
178     * ignoring the zone.
179     * <p>
180     * One advantage of this method is that this method is unaffected if the
181     * version of the time zone data differs between the JDK and Joda-Time.
182     * That is because the local field values are transferred, calculated using
183     * the JDK time zone data and without using the Joda-Time time zone data.
184     * <p>
185     * This factory method ignores the type of the calendar and always
186     * creates a LocalDateTime with ISO chronology. It is expected that you
187     * will only pass in instances of <code>GregorianCalendar</code> however
188     * this is not validated.
189     *
190     * @param calendar  the Calendar to extract fields from, not null
191     * @return the created local date-time, not null
192     * @throws IllegalArgumentException if the calendar is null
193     * @throws IllegalArgumentException if the date is invalid for the ISO chronology
194     */
195    public static LocalDateTime fromCalendarFields(Calendar calendar) {
196        if (calendar == null) {
197            throw new IllegalArgumentException("The calendar must not be null");
198        }
199        int era = calendar.get(Calendar.ERA);
200        int yearOfEra = calendar.get(Calendar.YEAR);
201        return new LocalDateTime(
202            (era == GregorianCalendar.AD ? yearOfEra : 1 - yearOfEra),
203            calendar.get(Calendar.MONTH) + 1,
204            calendar.get(Calendar.DAY_OF_MONTH),
205            calendar.get(Calendar.HOUR_OF_DAY),
206            calendar.get(Calendar.MINUTE),
207            calendar.get(Calendar.SECOND),
208            calendar.get(Calendar.MILLISECOND)
209        );
210    }
211
212    /**
213     * Constructs a LocalDateTime from a <code>java.util.Date</code>
214     * using exactly the same field values.
215     * <p>
216     * Each field is queried from the Date and assigned to the LocalDateTime.
217     * This is useful if you have been using the Date as a local date,
218     * ignoring the zone.
219     * <p>
220     * One advantage of this method is that this method is unaffected if the
221     * version of the time zone data differs between the JDK and Joda-Time.
222     * That is because the local field values are transferred, calculated using
223     * the JDK time zone data and without using the Joda-Time time zone data.
224     * <p>
225     * This factory method always creates a LocalDateTime with ISO chronology.
226     *
227     * @param date  the Date to extract fields from, not null
228     * @return the created local date-time, not null
229     * @throws IllegalArgumentException if the calendar is null
230     * @throws IllegalArgumentException if the date is invalid for the ISO chronology
231     */
232    @SuppressWarnings("deprecation")
233    public static LocalDateTime fromDateFields(Date date) {
234        if (date == null) {
235            throw new IllegalArgumentException("The date must not be null");
236        }
237        if (date.getTime() < 0) {
238            // handle years in era BC
239            GregorianCalendar cal = new GregorianCalendar();
240            cal.setTime(date);
241            return fromCalendarFields(cal);
242        }
243        return new LocalDateTime(
244            date.getYear() + 1900,
245            date.getMonth() + 1,
246            date.getDate(),
247            date.getHours(),
248            date.getMinutes(),
249            date.getSeconds(),
250            (((int) (date.getTime() % 1000)) + 1000) % 1000
251        );
252    }
253
254    //-----------------------------------------------------------------------
255    /**
256     * Constructs an instance set to the current local time evaluated using
257     * ISO chronology in the default zone.
258     * <p>
259     * Once the constructor is completed, the zone is no longer used.
260     * 
261     * @see #now()
262     */
263    public LocalDateTime() {
264        this(DateTimeUtils.currentTimeMillis(), ISOChronology.getInstance());
265    }
266
267    /**
268     * Constructs an instance set to the current local time evaluated using
269     * ISO chronology in the specified zone.
270     * <p>
271     * If the specified time zone is null, the default zone is used.
272     * Once the constructor is completed, the zone is no longer used.
273     *
274     * @param zone  the time zone, null means default zone
275     * @see #now(DateTimeZone)
276     */
277    public LocalDateTime(DateTimeZone zone) {
278        this(DateTimeUtils.currentTimeMillis(), ISOChronology.getInstance(zone));
279    }
280
281    /**
282     * Constructs an instance set to the current local time evaluated using
283     * specified chronology.
284     * <p>
285     * If the chronology is null, ISO chronology in the default time zone is used.
286     * Once the constructor is completed, the zone is no longer used.
287     *
288     * @param chronology  the chronology, null means ISOChronology in default zone
289     * @see #now(Chronology)
290     */
291    public LocalDateTime(Chronology chronology) {
292        this(DateTimeUtils.currentTimeMillis(), chronology);
293    }
294
295    //-----------------------------------------------------------------------
296    /**
297     * Constructs an instance set to the local time defined by the specified
298     * instant evaluated using ISO chronology in the default zone.
299     * <p>
300     * Once the constructor is completed, the zone is no longer used.
301     *
302     * @param instant  the milliseconds from 1970-01-01T00:00:00Z
303     */
304    public LocalDateTime(long instant) {
305        this(instant, ISOChronology.getInstance());
306    }
307
308    /**
309     * Constructs an instance set to the local time defined by the specified
310     * instant evaluated using ISO chronology in the specified zone.
311     * <p>
312     * If the specified time zone is null, the default zone is used.
313     * Once the constructor is completed, the zone is no longer used.
314     *
315     * @param instant  the milliseconds from 1970-01-01T00:00:00Z
316     * @param zone  the time zone, null means default zone
317     */
318    public LocalDateTime(long instant, DateTimeZone zone) {
319        this(instant, ISOChronology.getInstance(zone));
320    }
321
322    /**
323     * Constructs an instance set to the local time defined by the specified
324     * instant evaluated using the specified chronology.
325     * <p>
326     * If the chronology is null, ISO chronology in the default zone is used.
327     * Once the constructor is completed, the zone is no longer used.
328     *
329     * @param instant  the milliseconds from 1970-01-01T00:00:00Z
330     * @param chronology  the chronology, null means ISOChronology in default zone
331     */
332    public LocalDateTime(long instant, Chronology chronology) {
333        chronology = DateTimeUtils.getChronology(chronology);
334        
335        long localMillis = chronology.getZone().getMillisKeepLocal(DateTimeZone.UTC, instant);
336        iLocalMillis = localMillis;
337        iChronology = chronology.withUTC();
338    }
339
340    //-----------------------------------------------------------------------
341    /**
342     * Constructs an instance from an Object that represents a datetime.
343     * <p>
344     * If the object contains no chronology, <code>ISOChronology</code> is used.
345     * If the object contains no time zone, the default zone is used.
346     * Once the constructor is completed, the zone is no longer used.
347     * <p>
348     * The recognised object types are defined in
349     * {@link org.joda.time.convert.ConverterManager ConverterManager} and
350     * include ReadablePartial, ReadableInstant, String, Calendar and Date.
351     * The String formats are described by {@link ISODateTimeFormat#localDateOptionalTimeParser()}.
352     * The default String converter ignores the zone and only parses the field values.
353     *
354     * @param instant  the datetime object
355     * @throws IllegalArgumentException if the instant is invalid
356     */
357    public LocalDateTime(Object instant) {
358        this(instant, (Chronology) null);
359    }
360
361    /**
362     * Constructs an instance from an Object that represents a datetime,
363     * forcing the time zone to that specified.
364     * <p>
365     * If the object contains no chronology, <code>ISOChronology</code> is used.
366     * If the specified time zone is null, the default zone is used.
367     * Once the constructor is completed, the zone is no longer used.
368     * <p>
369     * The recognised object types are defined in
370     * {@link org.joda.time.convert.ConverterManager ConverterManager} and
371     * include ReadablePartial, ReadableInstant, String, Calendar and Date.
372     * The String formats are described by {@link ISODateTimeFormat#localDateOptionalTimeParser()}.
373     * The default String converter ignores the zone and only parses the field values.
374     *
375     * @param instant  the datetime object
376     * @param zone  the time zone
377     * @throws IllegalArgumentException if the instant is invalid
378     */
379    public LocalDateTime(Object instant, DateTimeZone zone) {
380        PartialConverter converter = ConverterManager.getInstance().getPartialConverter(instant);
381        Chronology chronology = converter.getChronology(instant, zone);
382        chronology = DateTimeUtils.getChronology(chronology);
383        iChronology = chronology.withUTC();
384        int[] values = converter.getPartialValues(this, instant, chronology, ISODateTimeFormat.localDateOptionalTimeParser());
385        iLocalMillis = iChronology.getDateTimeMillis(values[0], values[1], values[2], values[3]);
386    }
387
388    /**
389     * Constructs an instance from an Object that represents a datetime,
390     * using the specified chronology.
391     * <p>
392     * If the chronology is null, ISO in the default time zone is used.
393     * Once the constructor is completed, the zone is no longer used.
394     * If the instant contains a chronology, it will be ignored.
395     * For example, passing a {@code LocalDate} and a different chronology
396     * will return a date with the year/month/day from the date applied
397     * unaltered to the specified chronology.
398     * <p>
399     * The recognised object types are defined in
400     * {@link org.joda.time.convert.ConverterManager ConverterManager} and
401     * include ReadablePartial, ReadableInstant, String, Calendar and Date.
402     * The String formats are described by {@link ISODateTimeFormat#localDateOptionalTimeParser()}.
403     * The default String converter ignores the zone and only parses the field values.
404     *
405     * @param instant  the datetime object
406     * @param chronology  the chronology
407     * @throws IllegalArgumentException if the instant is invalid
408     */
409    public LocalDateTime(Object instant, Chronology chronology) {
410        PartialConverter converter = ConverterManager.getInstance().getPartialConverter(instant);
411        chronology = converter.getChronology(instant, chronology);
412        chronology = DateTimeUtils.getChronology(chronology);
413        iChronology = chronology.withUTC();
414        int[] values = converter.getPartialValues(this, instant, chronology, ISODateTimeFormat.localDateOptionalTimeParser());
415        iLocalMillis = iChronology.getDateTimeMillis(values[0], values[1], values[2], values[3]);
416    }
417
418    //-----------------------------------------------------------------------
419    /**
420     * Constructs an instance set to the specified date and time
421     * using <code>ISOChronology</code>.
422     *
423     * @param year  the year
424     * @param monthOfYear  the month of the year, from 1 to 12
425     * @param dayOfMonth  the day of the month, from 1 to 31
426     * @param hourOfDay  the hour of the day, from 0 to 23
427     * @param minuteOfHour  the minute of the hour, from 0 to 59
428     */
429    public LocalDateTime(
430            int year,
431            int monthOfYear,
432            int dayOfMonth,
433            int hourOfDay,
434            int minuteOfHour) {
435        this(year, monthOfYear, dayOfMonth, hourOfDay,
436            minuteOfHour, 0, 0, ISOChronology.getInstanceUTC());
437    }
438
439    /**
440     * Constructs an instance set to the specified date and time
441     * using <code>ISOChronology</code>.
442     *
443     * @param year  the year
444     * @param monthOfYear  the month of the year, from 1 to 12
445     * @param dayOfMonth  the day of the month, from 1 to 31
446     * @param hourOfDay  the hour of the day, from 0 to 23
447     * @param minuteOfHour  the minute of the hour, from 0 to 59
448     * @param secondOfMinute  the second of the minute, from 0 to 59
449     */
450    public LocalDateTime(
451            int year,
452            int monthOfYear,
453            int dayOfMonth,
454            int hourOfDay,
455            int minuteOfHour,
456            int secondOfMinute) {
457        this(year, monthOfYear, dayOfMonth, hourOfDay,
458            minuteOfHour, secondOfMinute, 0, ISOChronology.getInstanceUTC());
459    }
460
461    /**
462     * Constructs an instance set to the specified date and time
463     * using <code>ISOChronology</code>.
464     *
465     * @param year  the year
466     * @param monthOfYear  the month of the year, from 1 to 12
467     * @param dayOfMonth  the day of the month, from 1 to 31
468     * @param hourOfDay  the hour of the day, from 0 to 23
469     * @param minuteOfHour  the minute of the hour, from 0 to 59
470     * @param secondOfMinute  the second of the minute, from 0 to 59
471     * @param millisOfSecond  the millisecond of the second, from 0 to 999
472     */
473    public LocalDateTime(
474            int year,
475            int monthOfYear,
476            int dayOfMonth,
477            int hourOfDay,
478            int minuteOfHour,
479            int secondOfMinute,
480            int millisOfSecond) {
481        this(year, monthOfYear, dayOfMonth, hourOfDay,
482            minuteOfHour, secondOfMinute, millisOfSecond, ISOChronology.getInstanceUTC());
483    }
484
485    /**
486     * Constructs an instance set to the specified date and time
487     * using the specified chronology, whose zone is ignored.
488     * <p>
489     * If the chronology is null, <code>ISOChronology</code> is used.
490     *
491     * @param year  the year, valid values defined by the chronology
492     * @param monthOfYear  the month of the year, valid values defined by the chronology
493     * @param dayOfMonth  the day of the month, valid values defined by the chronology
494     * @param hourOfDay  the hour of the day, valid values defined by the chronology
495     * @param minuteOfHour  the minute of the hour, valid values defined by the chronology
496     * @param secondOfMinute  the second of the minute, valid values defined by the chronology
497     * @param millisOfSecond  the millisecond of the second, valid values defined by the chronology
498     * @param chronology  the chronology, null means ISOChronology in default zone
499     */
500    public LocalDateTime(
501            int year,
502            int monthOfYear,
503            int dayOfMonth,
504            int hourOfDay,
505            int minuteOfHour,
506            int secondOfMinute,
507            int millisOfSecond,
508            Chronology chronology) {
509        super();
510        chronology = DateTimeUtils.getChronology(chronology).withUTC();
511        long instant = chronology.getDateTimeMillis(year, monthOfYear, dayOfMonth,
512            hourOfDay, minuteOfHour, secondOfMinute, millisOfSecond);
513        iChronology = chronology;
514        iLocalMillis = instant;
515    }
516
517    /**
518     * Handle broken serialization from other tools.
519     * @return the resolved object, not null
520     */
521    private Object readResolve() {
522        if (iChronology == null) {
523            return new LocalDateTime(iLocalMillis, ISOChronology.getInstanceUTC());
524        }
525        if (DateTimeZone.UTC.equals(iChronology.getZone()) == false) {
526            return new LocalDateTime(iLocalMillis, iChronology.withUTC());
527        }
528        return this;
529    }
530
531    //-----------------------------------------------------------------------
532    /**
533     * Gets the number of fields in this partial, which is four.
534     * The supported fields are Year, MonthOfDay, DayOfMonth and MillisOfDay.
535     *
536     * @return the field count, four
537     */
538    public int size() {
539        return 4;
540    }
541
542    /**
543     * Gets the field for a specific index in the chronology specified.
544     * <p>
545     * This method must not use any instance variables.
546     *
547     * @param index  the index to retrieve
548     * @param chrono  the chronology to use
549     * @return the field
550     */
551    protected DateTimeField getField(int index, Chronology chrono) {
552        switch (index) {
553            case YEAR:
554                return chrono.year();
555            case MONTH_OF_YEAR:
556                return chrono.monthOfYear();
557            case DAY_OF_MONTH:
558                return chrono.dayOfMonth();
559            case MILLIS_OF_DAY:
560                return chrono.millisOfDay();
561            default:
562                throw new IndexOutOfBoundsException("Invalid index: " + index);
563        }
564    }
565
566    /**
567     * Gets the value of the field at the specifed index.
568     * <p>
569     * This method is required to support the <code>ReadablePartial</code>
570     * interface. The supported fields are Year, MonthOfDay, DayOfMonth and MillisOfDay.
571     *
572     * @param index  the index, zero to two
573     * @return the value
574     * @throws IndexOutOfBoundsException if the index is invalid
575     */
576    public int getValue(int index) {
577        switch (index) {
578            case YEAR:
579                return getChronology().year().get(getLocalMillis());
580            case MONTH_OF_YEAR:
581                return getChronology().monthOfYear().get(getLocalMillis());
582            case DAY_OF_MONTH:
583                return getChronology().dayOfMonth().get(getLocalMillis());
584            case MILLIS_OF_DAY:
585                return getChronology().millisOfDay().get(getLocalMillis());
586            default:
587                throw new IndexOutOfBoundsException("Invalid index: " + index);
588        }
589    }
590
591    //-----------------------------------------------------------------------
592    /**
593     * Get the value of one of the fields of a datetime.
594     * <p>
595     * This method gets the value of the specified field.
596     * For example:
597     * <pre>
598     * DateTime dt = new DateTime();
599     * int year = dt.get(DateTimeFieldType.year());
600     * </pre>
601     *
602     * @param type  a field type, usually obtained from DateTimeFieldType, not null
603     * @return the value of that field
604     * @throws IllegalArgumentException if the field type is null
605     */
606    public int get(DateTimeFieldType type) {
607        if (type == null) {
608            throw new IllegalArgumentException("The DateTimeFieldType must not be null");
609        }
610        return type.getField(getChronology()).get(getLocalMillis());
611    }
612
613    /**
614     * Checks if the field type specified is supported by this
615     * local datetime and chronology.
616     * This can be used to avoid exceptions in {@link #get(DateTimeFieldType)}.
617     *
618     * @param type  a field type, usually obtained from DateTimeFieldType
619     * @return true if the field type is supported
620     */
621    public boolean isSupported(DateTimeFieldType type) {
622        if (type == null) {
623            return false;
624        }
625        return type.getField(getChronology()).isSupported();
626    }
627
628    /**
629     * Checks if the duration type specified is supported by this
630     * local datetime and chronology.
631     *
632     * @param type  a duration type, usually obtained from DurationFieldType
633     * @return true if the field type is supported
634     */
635    public boolean isSupported(DurationFieldType type) {
636        if (type == null) {
637            return false;
638        }
639        return type.getField(getChronology()).isSupported();
640    }
641
642    //-----------------------------------------------------------------------
643    /**
644     * Gets the milliseconds of the datetime instant from the Java epoch
645     * of 1970-01-01T00:00:00 (not fixed to any specific time zone).
646     *
647     * @return the number of milliseconds since 1970-01-01T00:00:00
648     * @since 1.5 (previously private)
649     */
650    protected long getLocalMillis() {
651        return iLocalMillis;
652    }
653
654    /**
655     * Gets the chronology of the datetime.
656     *
657     * @return the Chronology that the datetime is using
658     */
659    public Chronology getChronology() {
660        return iChronology;
661    }
662
663    //-----------------------------------------------------------------------
664    /**
665     * Compares this ReadablePartial with another returning true if the chronology,
666     * field types and values are equal.
667     *
668     * @param partial  an object to check against
669     * @return true if fields and values are equal
670     */
671    public boolean equals(Object partial) {
672        // override to perform faster
673        if (this == partial) {
674            return true;
675        }
676        if (partial instanceof LocalDateTime) {
677            LocalDateTime other = (LocalDateTime) partial;
678            if (iChronology.equals(other.iChronology)) {
679                return iLocalMillis == other.iLocalMillis;
680            }
681        }
682        return super.equals(partial);
683    }
684
685    /**
686     * Compares this partial with another returning an integer
687     * indicating the order.
688     * <p>
689     * The fields are compared in order, from largest to smallest.
690     * The first field that is non-equal is used to determine the result.
691     * <p>
692     * The specified object must be a partial instance whose field types
693     * match those of this partial.
694     *
695     * @param partial  an object to check against
696     * @return negative if this is less, zero if equal, positive if greater
697     * @throws ClassCastException if the partial is the wrong class
698     *  or if it has field types that don't match
699     * @throws NullPointerException if the partial is null
700     */
701    public int compareTo(ReadablePartial partial) {
702        // override to perform faster
703        if (this == partial) {
704            return 0;
705        }
706        if (partial instanceof LocalDateTime) {
707            LocalDateTime other = (LocalDateTime) partial;
708            if (iChronology.equals(other.iChronology)) {
709                return (iLocalMillis < other.iLocalMillis ? -1 :
710                            (iLocalMillis == other.iLocalMillis ? 0 : 1));
711
712            }
713        }
714        return super.compareTo(partial);
715    }
716
717    //-----------------------------------------------------------------------
718    /**
719     * Converts this object to a DateTime using the default zone.
720     * <p>
721     * This method will throw an exception if the datetime that would be
722     * created does not exist when the time zone is taken into account.
723     * 
724     * @return <code>this</code>
725     */
726    public DateTime toDateTime() {
727        return toDateTime((DateTimeZone) null);
728    }
729
730    /**
731     * Converts this object to a DateTime using the specified zone.
732     * <p>
733     * This method will throw an exception if the datetime that would be
734     * created does not exist when the time zone is taken into account.
735     * 
736     * @param zone time zone to apply, or default if null
737     * @return a DateTime using the same millis
738     */
739    public DateTime toDateTime(DateTimeZone zone) {
740        zone = DateTimeUtils.getZone(zone);
741        Chronology chrono = iChronology.withZone(zone);
742        return new DateTime(
743                getYear(), getMonthOfYear(), getDayOfMonth(),
744                getHourOfDay(), getMinuteOfHour(),
745                getSecondOfMinute(), getMillisOfSecond(), chrono);
746    }
747
748    //-----------------------------------------------------------------------
749    /**
750     * Converts this object to a LocalDate with the same date and chronology.
751     *
752     * @return a LocalDate with the same date and chronology
753     */
754    public LocalDate toLocalDate() {
755        return new LocalDate(getLocalMillis(), getChronology());
756    }
757
758    /**
759     * Converts this object to a LocalTime with the same time and chronology.
760     *
761     * @return a LocalTime with the same time and chronology
762     */
763    public LocalTime toLocalTime() {
764        return new LocalTime(getLocalMillis(), getChronology());
765    }
766
767    //-----------------------------------------------------------------------
768    /**
769     * Get the date time as a <code>java.util.Date</code>.
770     * <p>
771     * The <code>Date</code> object created has exactly the same fields as this
772     * date-time, except when the time would be invalid due to a daylight savings
773     * gap. In that case, the time will be set to the earliest valid time after the gap.
774     * <p>
775     * In the case of a daylight savings overlap, the earlier instant is selected.
776     * <p>
777     * Converting to a JDK Date is full of complications as the JDK Date constructor
778     * doesn't behave as you might expect around DST transitions. This method works
779     * by taking a first guess and then adjusting. This also handles the situation
780     * where the JDK time zone data differs from the Joda-Time time zone data.
781     *
782     * @return a Date initialised with this date-time, never null
783     * @since 2.0
784     */
785    @SuppressWarnings("deprecation")
786    public Date toDate() {
787        int dom = getDayOfMonth();
788        Date date = new Date(getYear() - 1900, getMonthOfYear() - 1, dom,
789                        getHourOfDay(), getMinuteOfHour(), getSecondOfMinute());
790        date.setTime(date.getTime() + getMillisOfSecond());
791        LocalDateTime check = LocalDateTime.fromDateFields(date);
792        if (check.isBefore(this)) {
793            // DST gap
794            // move forward in units of one minute until equal/after
795            while (check.isBefore(this)) {
796                date.setTime(date.getTime() + 60000);
797                check = LocalDateTime.fromDateFields(date);
798            }
799            // move back in units of one second until date wrong
800            while (check.isBefore(this) == false) {
801                date.setTime(date.getTime() - 1000);
802                check = LocalDateTime.fromDateFields(date);
803            }
804            date.setTime(date.getTime() + 1000);
805        } else if (check.equals(this)) {
806            // check for DST overlap
807            Date earlier = new Date(date.getTime() - TimeZone.getDefault().getDSTSavings());
808            check = LocalDateTime.fromDateFields(earlier);
809            if (check.equals(this)) {
810                date = earlier;
811            }
812        }
813        return date;
814    }
815
816    //-----------------------------------------------------------------------
817    /**
818     * Returns a copy of this datetime with different local millis.
819     * <p>
820     * The returned object will be a new instance of the same type.
821     * Only the millis will change, the chronology is kept.
822     * The returned object will be either be a new instance or <code>this</code>.
823     *
824     * @param newMillis  the new millis, from 1970-01-01T00:00:00
825     * @return a copy of this datetime with different millis
826     */
827    LocalDateTime withLocalMillis(long newMillis) {
828        return (newMillis == getLocalMillis() ? this : new LocalDateTime(newMillis, getChronology()));
829    }
830
831    //-----------------------------------------------------------------------
832    /**
833     * Returns a copy of this datetime with the specified date,
834     * retaining the time fields.
835     * <p>
836     * If the date is already the date passed in, then <code>this</code> is returned.
837     * <p>
838     * To set a single field use the properties, for example:
839     * <pre>
840     * DateTime set = dt.monthOfYear().setCopy(6);
841     * </pre>
842     *
843     * @param year  the new year value
844     * @param monthOfYear  the new monthOfYear value
845     * @param dayOfMonth  the new dayOfMonth value
846     * @return a copy of this datetime with a different date
847     * @throws IllegalArgumentException if any value if invalid
848     */
849    public LocalDateTime withDate(int year, int monthOfYear, int dayOfMonth) {
850        Chronology chrono = getChronology();
851        long instant = getLocalMillis();
852        instant = chrono.year().set(instant, year);
853        instant = chrono.monthOfYear().set(instant, monthOfYear);
854        instant = chrono.dayOfMonth().set(instant, dayOfMonth);
855        return withLocalMillis(instant);
856    }
857
858    /**
859     * Returns a copy of this datetime with the specified time,
860     * retaining the date fields.
861     * <p>
862     * If the time is already the time passed in, then <code>this</code> is returned.
863     * <p>
864     * To set a single field use the properties, for example:
865     * <pre>
866     * LocalDateTime set = dt.hourOfDay().setCopy(6);
867     * </pre>
868     *
869     * @param hourOfDay  the hour of the day
870     * @param minuteOfHour  the minute of the hour
871     * @param secondOfMinute  the second of the minute
872     * @param millisOfSecond  the millisecond of the second
873     * @return a copy of this datetime with a different time
874     * @throws IllegalArgumentException if any value if invalid
875     */
876    public LocalDateTime withTime(int hourOfDay, int minuteOfHour, int secondOfMinute, int millisOfSecond) {
877        Chronology chrono = getChronology();
878        long instant = getLocalMillis();
879        instant = chrono.hourOfDay().set(instant, hourOfDay);
880        instant = chrono.minuteOfHour().set(instant, minuteOfHour);
881        instant = chrono.secondOfMinute().set(instant, secondOfMinute);
882        instant = chrono.millisOfSecond().set(instant, millisOfSecond);
883        return withLocalMillis(instant);
884    }
885
886    //-----------------------------------------------------------------------
887    /**
888     * Returns a copy of this datetime with the partial set of fields
889     * replacing those from this instance.
890     * <p>
891     * For example, if the partial is a <code>TimeOfDay</code> then the time fields
892     * would be changed in the returned instance.
893     * If the partial is null, then <code>this</code> is returned.
894     *
895     * @param partial  the partial set of fields to apply to this datetime, null ignored
896     * @return a copy of this datetime with a different set of fields
897     * @throws IllegalArgumentException if any value is invalid
898     */
899    public LocalDateTime withFields(ReadablePartial partial) {
900        if (partial == null) {
901            return this;
902        }
903        return withLocalMillis(getChronology().set(partial, getLocalMillis()));
904    }
905
906    /**
907     * Returns a copy of this datetime with the specified field set to a new value.
908     * <p>
909     * For example, if the field type is <code>hourOfDay</code> then the hour of day
910     * field would be changed in the returned instance.
911     * If the field type is null, then <code>this</code> is returned.
912     * <p>
913     * These three lines are equivalent:
914     * <pre>
915     * LocalDateTime updated = dt.withField(DateTimeFieldType.dayOfMonth(), 6);
916     * LocalDateTime updated = dt.dayOfMonth().setCopy(6);
917     * LocalDateTime updated = dt.property(DateTimeFieldType.dayOfMonth()).setCopy(6);
918     * </pre>
919     *
920     * @param fieldType  the field type to set, not null
921     * @param value  the value to set
922     * @return a copy of this datetime with the field set
923     * @throws IllegalArgumentException if the value is null or invalid
924     */
925    public LocalDateTime withField(DateTimeFieldType fieldType, int value) {
926        if (fieldType == null) {
927            throw new IllegalArgumentException("Field must not be null");
928        }
929        long instant = fieldType.getField(getChronology()).set(getLocalMillis(), value);
930        return withLocalMillis(instant);
931    }
932
933    /**
934     * Returns a copy of this datetime with the value of the specified
935     * field increased.
936     * <p>
937     * If the addition is zero or the field is null, then <code>this</code> is returned.
938     * <p>
939     * These three lines are equivalent:
940     * <pre>
941     * LocalDateTime added = dt.withFieldAdded(DurationFieldType.years(), 6);
942     * LocalDateTime added = dt.plusYears(6);
943     * LocalDateTime added = dt.plus(Period.years(6));
944     * </pre>
945     *
946     * @param fieldType  the field type to add to, not null
947     * @param amount  the amount to add
948     * @return a copy of this datetime with the field updated
949     * @throws IllegalArgumentException if the value is null or invalid
950     * @throws ArithmeticException if the result exceeds the internal capacity
951     */
952    public LocalDateTime withFieldAdded(DurationFieldType fieldType, int amount) {
953        if (fieldType == null) {
954            throw new IllegalArgumentException("Field must not be null");
955        }
956        if (amount == 0) {
957            return this;
958        }
959        long instant = fieldType.getField(getChronology()).add(getLocalMillis(), amount);
960        return withLocalMillis(instant);
961    }
962
963    //-----------------------------------------------------------------------
964    /**
965     * Returns a copy of this datetime with the specified duration added.
966     * <p>
967     * If the addition is zero, then <code>this</code> is returned.
968     *
969     * @param durationToAdd  the duration to add to this one, null means zero
970     * @param scalar  the amount of times to add, such as -1 to subtract once
971     * @return a copy of this datetime with the duration added
972     * @throws ArithmeticException if the result exceeds the internal capacity
973     */
974    public LocalDateTime withDurationAdded(ReadableDuration durationToAdd, int scalar) {
975        if (durationToAdd == null || scalar == 0) {
976            return this;
977        }
978        long instant = getChronology().add(getLocalMillis(), durationToAdd.getMillis(), scalar);
979        return withLocalMillis(instant);
980    }
981
982    /**
983     * Returns a copy of this datetime with the specified period added.
984     * <p>
985     * If the addition is zero, then <code>this</code> is returned.
986     * <p>
987     * This method is typically used to add multiple copies of complex
988     * period instances. Adding one field is best achieved using methods
989     * like {@link #withFieldAdded(DurationFieldType, int)}
990     * or {@link #plusYears(int)}.
991     *
992     * @param period  the period to add to this one, null means zero
993     * @param scalar  the amount of times to add, such as -1 to subtract once
994     * @return a copy of this datetime with the period added
995     * @throws ArithmeticException if the result exceeds the internal capacity
996     */
997    public LocalDateTime withPeriodAdded(ReadablePeriod period, int scalar) {
998        if (period == null || scalar == 0) {
999            return this;
1000        }
1001        long instant = getChronology().add(period, getLocalMillis(), scalar);
1002        return withLocalMillis(instant);
1003    }
1004
1005    //-----------------------------------------------------------------------
1006    /**
1007     * Returns a copy of this datetime with the specified duration added.
1008     * <p>
1009     * If the amount is zero or null, then <code>this</code> is returned.
1010     *
1011     * @param duration  the duration to add to this one, null means zero
1012     * @return a copy of this datetime with the duration added
1013     * @throws ArithmeticException if the result exceeds the internal capacity
1014     */
1015    public LocalDateTime plus(ReadableDuration duration) {
1016        return withDurationAdded(duration, 1);
1017    }
1018
1019    /**
1020     * Returns a copy of this datetime with the specified period added.
1021     * <p>
1022     * If the amount is zero or null, then <code>this</code> is returned.
1023     * <p>
1024     * This method is typically used to add complex period instances.
1025     * Adding one field is best achieved using methods
1026     * like {@link #plusYears(int)}.
1027     *
1028     * @param period  the period to add to this one, null means zero
1029     * @return a copy of this datetime with the period added
1030     * @throws ArithmeticException if the result exceeds the internal capacity
1031     */
1032    public LocalDateTime plus(ReadablePeriod period) {
1033        return withPeriodAdded(period, 1);
1034    }
1035
1036    //-----------------------------------------------------------------------
1037    /**
1038     * Returns a copy of this datetime plus the specified number of years.
1039     * <p>
1040     * This LocalDateTime instance is immutable and unaffected by this method call.
1041     * <p>
1042     * The following three lines are identical in effect:
1043     * <pre>
1044     * LocalDateTime added = dt.plusYears(6);
1045     * LocalDateTime added = dt.plus(Period.years(6));
1046     * LocalDateTime added = dt.withFieldAdded(DurationFieldType.years(), 6);
1047     * </pre>
1048     *
1049     * @param years  the amount of years to add, may be negative
1050     * @return the new LocalDateTime plus the increased years
1051     */
1052    public LocalDateTime plusYears(int years) {
1053        if (years == 0) {
1054            return this;
1055        }
1056        long instant = getChronology().years().add(getLocalMillis(), years);
1057        return withLocalMillis(instant);
1058    }
1059
1060    /**
1061     * Returns a copy of this datetime plus the specified number of months.
1062     * <p>
1063     * This LocalDateTime instance is immutable and unaffected by this method call.
1064     * <p>
1065     * The following three lines are identical in effect:
1066     * <pre>
1067     * LocalDateTime added = dt.plusMonths(6);
1068     * LocalDateTime added = dt.plus(Period.months(6));
1069     * LocalDateTime added = dt.withFieldAdded(DurationFieldType.months(), 6);
1070     * </pre>
1071     *
1072     * @param months  the amount of months to add, may be negative
1073     * @return the new LocalDateTime plus the increased months
1074     */
1075    public LocalDateTime plusMonths(int months) {
1076        if (months == 0) {
1077            return this;
1078        }
1079        long instant = getChronology().months().add(getLocalMillis(), months);
1080        return withLocalMillis(instant);
1081    }
1082
1083    /**
1084     * Returns a copy of this datetime plus the specified number of weeks.
1085     * <p>
1086     * This LocalDateTime instance is immutable and unaffected by this method call.
1087     * <p>
1088     * The following three lines are identical in effect:
1089     * <pre>
1090     * LocalDateTime added = dt.plusWeeks(6);
1091     * LocalDateTime added = dt.plus(Period.weeks(6));
1092     * LocalDateTime added = dt.withFieldAdded(DurationFieldType.weeks(), 6);
1093     * </pre>
1094     *
1095     * @param weeks  the amount of weeks to add, may be negative
1096     * @return the new LocalDateTime plus the increased weeks
1097     */
1098    public LocalDateTime plusWeeks(int weeks) {
1099        if (weeks == 0) {
1100            return this;
1101        }
1102        long instant = getChronology().weeks().add(getLocalMillis(), weeks);
1103        return withLocalMillis(instant);
1104    }
1105
1106    /**
1107     * Returns a copy of this datetime plus the specified number of days.
1108     * <p>
1109     * This LocalDateTime instance is immutable and unaffected by this method call.
1110     * <p>
1111     * The following three lines are identical in effect:
1112     * <pre>
1113     * LocalDateTime added = dt.plusDays(6);
1114     * LocalDateTime added = dt.plus(Period.days(6));
1115     * LocalDateTime added = dt.withFieldAdded(DurationFieldType.days(), 6);
1116     * </pre>
1117     *
1118     * @param days  the amount of days to add, may be negative
1119     * @return the new LocalDateTime plus the increased days
1120     */
1121    public LocalDateTime plusDays(int days) {
1122        if (days == 0) {
1123            return this;
1124        }
1125        long instant = getChronology().days().add(getLocalMillis(), days);
1126        return withLocalMillis(instant);
1127    }
1128
1129    //-----------------------------------------------------------------------
1130    /**
1131     * Returns a copy of this datetime plus the specified number of hours.
1132     * <p>
1133     * This LocalDateTime instance is immutable and unaffected by this method call.
1134     * <p>
1135     * The following three lines are identical in effect:
1136     * <pre>
1137     * LocalDateTime added = dt.plusHours(6);
1138     * LocalDateTime added = dt.plus(Period.hours(6));
1139     * LocalDateTime added = dt.withFieldAdded(DurationFieldType.hours(), 6);
1140     * </pre>
1141     *
1142     * @param hours  the amount of hours to add, may be negative
1143     * @return the new LocalDateTime plus the increased hours
1144     */
1145    public LocalDateTime plusHours(int hours) {
1146        if (hours == 0) {
1147            return this;
1148        }
1149        long instant = getChronology().hours().add(getLocalMillis(), hours);
1150        return withLocalMillis(instant);
1151    }
1152
1153    /**
1154     * Returns a copy of this datetime plus the specified number of minutes.
1155     * <p>
1156     * This LocalDateTime instance is immutable and unaffected by this method call.
1157     * <p>
1158     * The following three lines are identical in effect:
1159     * <pre>
1160     * LocalDateTime added = dt.plusMinutes(6);
1161     * LocalDateTime added = dt.plus(Period.minutes(6));
1162     * LocalDateTime added = dt.withFieldAdded(DurationFieldType.minutes(), 6);
1163     * </pre>
1164     *
1165     * @param minutes  the amount of minutes to add, may be negative
1166     * @return the new LocalDateTime plus the increased minutes
1167     */
1168    public LocalDateTime plusMinutes(int minutes) {
1169        if (minutes == 0) {
1170            return this;
1171        }
1172        long instant = getChronology().minutes().add(getLocalMillis(), minutes);
1173        return withLocalMillis(instant);
1174    }
1175
1176    /**
1177     * Returns a copy of this datetime plus the specified number of seconds.
1178     * <p>
1179     * This LocalDateTime instance is immutable and unaffected by this method call.
1180     * <p>
1181     * The following three lines are identical in effect:
1182     * <pre>
1183     * LocalDateTime added = dt.plusSeconds(6);
1184     * LocalDateTime added = dt.plus(Period.seconds(6));
1185     * LocalDateTime added = dt.withFieldAdded(DurationFieldType.seconds(), 6);
1186     * </pre>
1187     *
1188     * @param seconds  the amount of seconds to add, may be negative
1189     * @return the new LocalDateTime plus the increased seconds
1190     */
1191    public LocalDateTime plusSeconds(int seconds) {
1192        if (seconds == 0) {
1193            return this;
1194        }
1195        long instant = getChronology().seconds().add(getLocalMillis(), seconds);
1196        return withLocalMillis(instant);
1197    }
1198
1199    /**
1200     * Returns a copy of this datetime plus the specified number of millis.
1201     * <p>
1202     * This LocalDateTime instance is immutable and unaffected by this method call.
1203     * <p>
1204     * The following three lines are identical in effect:
1205     * <pre>
1206     * LocalDateTime added = dt.plusMillis(6);
1207     * LocalDateTime added = dt.plus(Period.millis(6));
1208     * LocalDateTime added = dt.withFieldAdded(DurationFieldType.millis(), 6);
1209     * </pre>
1210     *
1211     * @param millis  the amount of millis to add, may be negative
1212     * @return the new LocalDateTime plus the increased millis
1213     */
1214    public LocalDateTime plusMillis(int millis) {
1215        if (millis == 0) {
1216            return this;
1217        }
1218        long instant = getChronology().millis().add(getLocalMillis(), millis);
1219        return withLocalMillis(instant);
1220    }
1221
1222    //-----------------------------------------------------------------------
1223    /**
1224     * Returns a copy of this datetime with the specified duration taken away.
1225     * <p>
1226     * If the amount is zero or null, then <code>this</code> is returned.
1227     *
1228     * @param duration  the duration to reduce this instant by
1229     * @return a copy of this datetime with the duration taken away
1230     * @throws ArithmeticException if the result exceeds the internal capacity
1231     */
1232    public LocalDateTime minus(ReadableDuration duration) {
1233        return withDurationAdded(duration, -1);
1234    }
1235
1236    /**
1237     * Returns a copy of this datetime with the specified period taken away.
1238     * <p>
1239     * If the amount is zero or null, then <code>this</code> is returned.
1240     * <p>
1241     * This method is typically used to subtract complex period instances.
1242     * Subtracting one field is best achieved using methods
1243     * like {@link #minusYears(int)}.
1244     *
1245     * @param period  the period to reduce this instant by
1246     * @return a copy of this datetime with the period taken away
1247     * @throws ArithmeticException if the result exceeds the internal capacity
1248     */
1249    public LocalDateTime minus(ReadablePeriod period) {
1250        return withPeriodAdded(period, -1);
1251    }
1252
1253    //-----------------------------------------------------------------------
1254    /**
1255     * Returns a copy of this datetime minus the specified number of years.
1256     * <p>
1257     * This LocalDateTime instance is immutable and unaffected by this method call.
1258     * <p>
1259     * The following three lines are identical in effect:
1260     * <pre>
1261     * LocalDateTime subtracted = dt.minusYears(6);
1262     * LocalDateTime subtracted = dt.minus(Period.years(6));
1263     * LocalDateTime subtracted = dt.withFieldAdded(DurationFieldType.years(), -6);
1264     * </pre>
1265     *
1266     * @param years  the amount of years to subtract, may be negative
1267     * @return the new LocalDateTime minus the increased years
1268     */
1269    public LocalDateTime minusYears(int years) {
1270        if (years == 0) {
1271            return this;
1272        }
1273        long instant = getChronology().years().subtract(getLocalMillis(), years);
1274        return withLocalMillis(instant);
1275    }
1276
1277    /**
1278     * Returns a copy of this datetime minus the specified number of months.
1279     * <p>
1280     * This LocalDateTime instance is immutable and unaffected by this method call.
1281     * <p>
1282     * The following three lines are identical in effect:
1283     * <pre>
1284     * LocalDateTime subtracted = dt.minusMonths(6);
1285     * LocalDateTime subtracted = dt.minus(Period.months(6));
1286     * LocalDateTime subtracted = dt.withFieldAdded(DurationFieldType.months(), -6);
1287     * </pre>
1288     *
1289     * @param months  the amount of months to subtract, may be negative
1290     * @return the new LocalDateTime minus the increased months
1291     */
1292    public LocalDateTime minusMonths(int months) {
1293        if (months == 0) {
1294            return this;
1295        }
1296        long instant = getChronology().months().subtract(getLocalMillis(), months);
1297        return withLocalMillis(instant);
1298    }
1299
1300    /**
1301     * Returns a copy of this datetime minus the specified number of weeks.
1302     * <p>
1303     * This LocalDateTime instance is immutable and unaffected by this method call.
1304     * <p>
1305     * The following three lines are identical in effect:
1306     * <pre>
1307     * LocalDateTime subtracted = dt.minusWeeks(6);
1308     * LocalDateTime subtracted = dt.minus(Period.weeks(6));
1309     * LocalDateTime subtracted = dt.withFieldAdded(DurationFieldType.weeks(), -6);
1310     * </pre>
1311     *
1312     * @param weeks  the amount of weeks to subtract, may be negative
1313     * @return the new LocalDateTime minus the increased weeks
1314     */
1315    public LocalDateTime minusWeeks(int weeks) {
1316        if (weeks == 0) {
1317            return this;
1318        }
1319        long instant = getChronology().weeks().subtract(getLocalMillis(), weeks);
1320        return withLocalMillis(instant);
1321    }
1322
1323    /**
1324     * Returns a copy of this datetime minus the specified number of days.
1325     * <p>
1326     * This LocalDateTime instance is immutable and unaffected by this method call.
1327     * <p>
1328     * The following three lines are identical in effect:
1329     * <pre>
1330     * LocalDateTime subtracted = dt.minusDays(6);
1331     * LocalDateTime subtracted = dt.minus(Period.days(6));
1332     * LocalDateTime subtracted = dt.withFieldAdded(DurationFieldType.days(), -6);
1333     * </pre>
1334     *
1335     * @param days  the amount of days to subtract, may be negative
1336     * @return the new LocalDateTime minus the increased days
1337     */
1338    public LocalDateTime minusDays(int days) {
1339        if (days == 0) {
1340            return this;
1341        }
1342        long instant = getChronology().days().subtract(getLocalMillis(), days);
1343        return withLocalMillis(instant);
1344    }
1345
1346    //-----------------------------------------------------------------------
1347    /**
1348     * Returns a copy of this datetime minus the specified number of hours.
1349     * <p>
1350     * This LocalDateTime instance is immutable and unaffected by this method call.
1351     * <p>
1352     * The following three lines are identical in effect:
1353     * <pre>
1354     * LocalDateTime subtracted = dt.minusHours(6);
1355     * LocalDateTime subtracted = dt.minus(Period.hours(6));
1356     * LocalDateTime subtracted = dt.withFieldAdded(DurationFieldType.hours(), -6);
1357     * </pre>
1358     *
1359     * @param hours  the amount of hours to subtract, may be negative
1360     * @return the new LocalDateTime minus the increased hours
1361     */
1362    public LocalDateTime minusHours(int hours) {
1363        if (hours == 0) {
1364            return this;
1365        }
1366        long instant = getChronology().hours().subtract(getLocalMillis(), hours);
1367        return withLocalMillis(instant);
1368    }
1369
1370    /**
1371     * Returns a copy of this datetime minus the specified number of minutes.
1372     * <p>
1373     * This LocalDateTime instance is immutable and unaffected by this method call.
1374     * <p>
1375     * The following three lines are identical in effect:
1376     * <pre>
1377     * LocalDateTime subtracted = dt.minusMinutes(6);
1378     * LocalDateTime subtracted = dt.minus(Period.minutes(6));
1379     * LocalDateTime subtracted = dt.withFieldAdded(DurationFieldType.minutes(), -6);
1380     * </pre>
1381     *
1382     * @param minutes  the amount of minutes to subtract, may be negative
1383     * @return the new LocalDateTime minus the increased minutes
1384     */
1385    public LocalDateTime minusMinutes(int minutes) {
1386        if (minutes == 0) {
1387            return this;
1388        }
1389        long instant = getChronology().minutes().subtract(getLocalMillis(), minutes);
1390        return withLocalMillis(instant);
1391    }
1392
1393    /**
1394     * Returns a copy of this datetime minus the specified number of seconds.
1395     * <p>
1396     * This LocalDateTime instance is immutable and unaffected by this method call.
1397     * <p>
1398     * The following three lines are identical in effect:
1399     * <pre>
1400     * LocalDateTime subtracted = dt.minusSeconds(6);
1401     * LocalDateTime subtracted = dt.minus(Period.seconds(6));
1402     * LocalDateTime subtracted = dt.withFieldAdded(DurationFieldType.seconds(), -6);
1403     * </pre>
1404     *
1405     * @param seconds  the amount of seconds to subtract, may be negative
1406     * @return the new LocalDateTime minus the increased seconds
1407     */
1408    public LocalDateTime minusSeconds(int seconds) {
1409        if (seconds == 0) {
1410            return this;
1411        }
1412        long instant = getChronology().seconds().subtract(getLocalMillis(), seconds);
1413        return withLocalMillis(instant);
1414    }
1415
1416    /**
1417     * Returns a copy of this datetime minus the specified number of millis.
1418     * <p>
1419     * This LocalDateTime instance is immutable and unaffected by this method call.
1420     * <p>
1421     * The following three lines are identical in effect:
1422     * <pre>
1423     * LocalDateTime subtracted = dt.minusMillis(6);
1424     * LocalDateTime subtracted = dt.minus(Period.millis(6));
1425     * LocalDateTime subtracted = dt.withFieldAdded(DurationFieldType.millis(), -6);
1426     * </pre>
1427     *
1428     * @param millis  the amount of millis to subtract, may be negative
1429     * @return the new LocalDateTime minus the increased millis
1430     */
1431    public LocalDateTime minusMillis(int millis) {
1432        if (millis == 0) {
1433            return this;
1434        }
1435        long instant = getChronology().millis().subtract(getLocalMillis(), millis);
1436        return withLocalMillis(instant);
1437    }
1438
1439    //-----------------------------------------------------------------------
1440    /**
1441     * Gets the property object for the specified type, which contains many
1442     * useful methods.
1443     *
1444     * @param fieldType  the field type to get the chronology for
1445     * @return the property object
1446     * @throws IllegalArgumentException if the field is null or unsupported
1447     */
1448    public Property property(DateTimeFieldType fieldType) {
1449        if (fieldType == null) {
1450            throw new IllegalArgumentException("The DateTimeFieldType must not be null");
1451        }
1452        if (isSupported(fieldType) == false) {
1453            throw new IllegalArgumentException("Field '" + fieldType + "' is not supported");
1454        }
1455        return new Property(this, fieldType.getField(getChronology()));
1456    }
1457
1458    //-----------------------------------------------------------------------
1459    /**
1460     * Get the era field value.
1461     *
1462     * @return the era
1463     */
1464    public int getEra() {
1465        return getChronology().era().get(getLocalMillis());
1466    }
1467
1468    /**
1469     * Get the year of era field value.
1470     *
1471     * @return the year of era
1472     */
1473    public int getCenturyOfEra() {
1474        return getChronology().centuryOfEra().get(getLocalMillis());
1475    }
1476
1477    /**
1478     * Get the year of era field value.
1479     *
1480     * @return the year of era
1481     */
1482    public int getYearOfEra() {
1483        return getChronology().yearOfEra().get(getLocalMillis());
1484    }
1485
1486    /**
1487     * Get the year of century field value.
1488     *
1489     * @return the year of century
1490     */
1491    public int getYearOfCentury() {
1492        return getChronology().yearOfCentury().get(getLocalMillis());
1493    }
1494
1495    /**
1496     * Get the year field value.
1497     *
1498     * @return the year
1499     */
1500    public int getYear() {
1501        return getChronology().year().get(getLocalMillis());
1502    }
1503
1504    /**
1505     * Get the weekyear field value.
1506     * <p>
1507     * The weekyear is the year that matches with the weekOfWeekyear field.
1508     * In the standard ISO8601 week algorithm, the first week of the year
1509     * is that in which at least 4 days are in the year. As a result of this
1510     * definition, day 1 of the first week may be in the previous year.
1511     * The weekyear allows you to query the effective year for that day.
1512     *
1513     * @return the weekyear
1514     */
1515    public int getWeekyear() {
1516        return getChronology().weekyear().get(getLocalMillis());
1517    }
1518
1519    /**
1520     * Get the month of year field value.
1521     *
1522     * @return the month of year
1523     */
1524    public int getMonthOfYear() {
1525        return getChronology().monthOfYear().get(getLocalMillis());
1526    }
1527
1528    /**
1529     * Get the week of weekyear field value.
1530     * <p>
1531     * This field is associated with the "weekyear" via {@link #getWeekyear()}.
1532     * In the standard ISO8601 week algorithm, the first week of the year
1533     * is that in which at least 4 days are in the year. As a result of this
1534     * definition, day 1 of the first week may be in the previous year.
1535     *
1536     * @return the week of a week based year
1537     */
1538    public int getWeekOfWeekyear() {
1539        return getChronology().weekOfWeekyear().get(getLocalMillis());
1540    }
1541
1542    /**
1543     * Get the day of year field value.
1544     *
1545     * @return the day of year
1546     */
1547    public int getDayOfYear() {
1548        return getChronology().dayOfYear().get(getLocalMillis());
1549    }
1550
1551    /**
1552     * Get the day of month field value.
1553     * <p>
1554     * The values for the day of month are defined in {@link org.joda.time.DateTimeConstants}.
1555     *
1556     * @return the day of month
1557     */
1558    public int getDayOfMonth() {
1559        return getChronology().dayOfMonth().get(getLocalMillis());
1560    }
1561
1562    /**
1563     * Get the day of week field value.
1564     * <p>
1565     * The values for the day of week are defined in {@link org.joda.time.DateTimeConstants}.
1566     *
1567     * @return the day of week
1568     */
1569    public int getDayOfWeek() {
1570        return getChronology().dayOfWeek().get(getLocalMillis());
1571    }
1572
1573    //-----------------------------------------------------------------------
1574    /**
1575     * Get the hour of day field value.
1576     *
1577     * @return the hour of day
1578     */
1579    public int getHourOfDay() {
1580        return getChronology().hourOfDay().get(getLocalMillis());
1581    }
1582
1583    /**
1584     * Get the minute of hour field value.
1585     *
1586     * @return the minute of hour
1587     */
1588    public int getMinuteOfHour() {
1589        return getChronology().minuteOfHour().get(getLocalMillis());
1590    }
1591
1592    /**
1593     * Get the second of minute field value.
1594     *
1595     * @return the second of minute
1596     */
1597    public int getSecondOfMinute() {
1598        return getChronology().secondOfMinute().get(getLocalMillis());
1599    }
1600
1601    /**
1602     * Get the millis of second field value.
1603     *
1604     * @return the millis of second
1605     */
1606    public int getMillisOfSecond() {
1607        return getChronology().millisOfSecond().get(getLocalMillis());
1608    }
1609
1610    /**
1611     * Get the millis of day field value.
1612     *
1613     * @return the millis of day
1614     */
1615    public int getMillisOfDay() {
1616        return getChronology().millisOfDay().get(getLocalMillis());
1617    }
1618
1619    //-----------------------------------------------------------------------
1620    /**
1621     * Returns a copy of this datetime with the era field updated.
1622     * <p>
1623     * LocalDateTime is immutable, so there are no set methods.
1624     * Instead, this method returns a new instance with the value of
1625     * era changed.
1626     *
1627     * @param era  the era to set
1628     * @return a copy of this object with the field set
1629     * @throws IllegalArgumentException if the value is invalid
1630     */
1631    public LocalDateTime withEra(int era) {
1632        return withLocalMillis(getChronology().era().set(getLocalMillis(), era));
1633    }
1634
1635    /**
1636     * Returns a copy of this datetime with the century of era field updated.
1637     * <p>
1638     * LocalDateTime is immutable, so there are no set methods.
1639     * Instead, this method returns a new instance with the value of
1640     * century of era changed.
1641     *
1642     * @param centuryOfEra  the centurey of era to set
1643     * @return a copy of this object with the field set
1644     * @throws IllegalArgumentException if the value is invalid
1645     */
1646    public LocalDateTime withCenturyOfEra(int centuryOfEra) {
1647        return withLocalMillis(getChronology().centuryOfEra().set(getLocalMillis(), centuryOfEra));
1648    }
1649
1650    /**
1651     * Returns a copy of this datetime with the year of era field updated.
1652     * <p>
1653     * LocalDateTime is immutable, so there are no set methods.
1654     * Instead, this method returns a new instance with the value of
1655     * year of era changed.
1656     *
1657     * @param yearOfEra  the year of era to set
1658     * @return a copy of this object with the field set
1659     * @throws IllegalArgumentException if the value is invalid
1660     */
1661    public LocalDateTime withYearOfEra(int yearOfEra) {
1662        return withLocalMillis(getChronology().yearOfEra().set(getLocalMillis(), yearOfEra));
1663    }
1664
1665    /**
1666     * Returns a copy of this datetime with the year of century field updated.
1667     * <p>
1668     * LocalDateTime is immutable, so there are no set methods.
1669     * Instead, this method returns a new instance with the value of
1670     * year of century changed.
1671     *
1672     * @param yearOfCentury  the year of century to set
1673     * @return a copy of this object with the field set
1674     * @throws IllegalArgumentException if the value is invalid
1675     */
1676    public LocalDateTime withYearOfCentury(int yearOfCentury) {
1677        return withLocalMillis(getChronology().yearOfCentury().set(getLocalMillis(), yearOfCentury));
1678    }
1679
1680    /**
1681     * Returns a copy of this datetime with the year field updated.
1682     * <p>
1683     * LocalDateTime is immutable, so there are no set methods.
1684     * Instead, this method returns a new instance with the value of
1685     * year changed.
1686     *
1687     * @param year  the year to set
1688     * @return a copy of this object with the field set
1689     * @throws IllegalArgumentException if the value is invalid
1690     */
1691    public LocalDateTime withYear(int year) {
1692        return withLocalMillis(getChronology().year().set(getLocalMillis(), year));
1693    }
1694
1695    /**
1696     * Returns a copy of this datetime with the weekyear field updated.
1697     * <p>
1698     * The weekyear is the year that matches with the weekOfWeekyear field.
1699     * In the standard ISO8601 week algorithm, the first week of the year
1700     * is that in which at least 4 days are in the year. As a result of this
1701     * definition, day 1 of the first week may be in the previous year.
1702     * The weekyear allows you to query the effective year for that day.
1703     * <p>
1704     * LocalDateTime is immutable, so there are no set methods.
1705     * Instead, this method returns a new instance with the value of
1706     * weekyear changed.
1707     *
1708     * @param weekyear  the weekyear to set
1709     * @return a copy of this object with the field set
1710     * @throws IllegalArgumentException if the value is invalid
1711     */
1712    public LocalDateTime withWeekyear(int weekyear) {
1713        return withLocalMillis(getChronology().weekyear().set(getLocalMillis(), weekyear));
1714    }
1715
1716    /**
1717     * Returns a copy of this datetime with the month of year field updated.
1718     * <p>
1719     * LocalDateTime is immutable, so there are no set methods.
1720     * Instead, this method returns a new instance with the value of
1721     * month of year changed.
1722     *
1723     * @param monthOfYear  the month of year to set
1724     * @return a copy of this object with the field set
1725     * @throws IllegalArgumentException if the value is invalid
1726     */
1727    public LocalDateTime withMonthOfYear(int monthOfYear) {
1728        return withLocalMillis(getChronology().monthOfYear().set(getLocalMillis(), monthOfYear));
1729    }
1730
1731    /**
1732     * Returns a copy of this datetime with the week of weekyear field updated.
1733     * <p>
1734     * This field is associated with the "weekyear" via {@link #withWeekyear(int)}.
1735     * In the standard ISO8601 week algorithm, the first week of the year
1736     * is that in which at least 4 days are in the year. As a result of this
1737     * definition, day 1 of the first week may be in the previous year.
1738     * <p>
1739     * LocalDateTime is immutable, so there are no set methods.
1740     * Instead, this method returns a new instance with the value of
1741     * week of weekyear changed.
1742     *
1743     * @param weekOfWeekyear  the week of weekyear to set
1744     * @return a copy of this object with the field set
1745     * @throws IllegalArgumentException if the value is invalid
1746     */
1747    public LocalDateTime withWeekOfWeekyear(int weekOfWeekyear) {
1748        return withLocalMillis(getChronology().weekOfWeekyear().set(getLocalMillis(), weekOfWeekyear));
1749    }
1750
1751    /**
1752     * Returns a copy of this datetime with the day of year field updated.
1753     * <p>
1754     * LocalDateTime is immutable, so there are no set methods.
1755     * Instead, this method returns a new instance with the value of
1756     * day of year changed.
1757     *
1758     * @param dayOfYear  the day of year to set
1759     * @return a copy of this object with the field set
1760     * @throws IllegalArgumentException if the value is invalid
1761     */
1762    public LocalDateTime withDayOfYear(int dayOfYear) {
1763        return withLocalMillis(getChronology().dayOfYear().set(getLocalMillis(), dayOfYear));
1764    }
1765
1766    /**
1767     * Returns a copy of this datetime with the day of month field updated.
1768     * <p>
1769     * LocalDateTime is immutable, so there are no set methods.
1770     * Instead, this method returns a new instance with the value of
1771     * day of month changed.
1772     *
1773     * @param dayOfMonth  the day of month to set
1774     * @return a copy of this object with the field set
1775     * @throws IllegalArgumentException if the value is invalid
1776     */
1777    public LocalDateTime withDayOfMonth(int dayOfMonth) {
1778        return withLocalMillis(getChronology().dayOfMonth().set(getLocalMillis(), dayOfMonth));
1779    }
1780
1781    /**
1782     * Returns a copy of this datetime with the day of week field updated.
1783     * <p>
1784     * LocalDateTime is immutable, so there are no set methods.
1785     * Instead, this method returns a new instance with the value of
1786     * day of week changed.
1787     *
1788     * @param dayOfWeek  the day of week to set
1789     * @return a copy of this object with the field set
1790     * @throws IllegalArgumentException if the value is invalid
1791     */
1792    public LocalDateTime withDayOfWeek(int dayOfWeek) {
1793        return withLocalMillis(getChronology().dayOfWeek().set(getLocalMillis(), dayOfWeek));
1794    }
1795
1796    //-----------------------------------------------------------------------
1797    /**
1798     * Returns a copy of this datetime with the hour of day field updated.
1799     * <p>
1800     * LocalDateTime is immutable, so there are no set methods.
1801     * Instead, this method returns a new instance with the value of
1802     * hour of day changed.
1803     *
1804     * @param hour  the hour of day to set
1805     * @return a copy of this object with the field set
1806     * @throws IllegalArgumentException if the value is invalid
1807     */
1808    public LocalDateTime withHourOfDay(int hour) {
1809        return withLocalMillis(getChronology().hourOfDay().set(getLocalMillis(), hour));
1810    }
1811
1812    /**
1813     * Returns a copy of this datetime with the minute of hour field updated.
1814     * <p>
1815     * LocalDateTime is immutable, so there are no set methods.
1816     * Instead, this method returns a new instance with the value of
1817     * minute of hour changed.
1818     *
1819     * @param minute  the minute of hour to set
1820     * @return a copy of this object with the field set
1821     * @throws IllegalArgumentException if the value is invalid
1822     */
1823    public LocalDateTime withMinuteOfHour(int minute) {
1824        return withLocalMillis(getChronology().minuteOfHour().set(getLocalMillis(), minute));
1825    }
1826
1827    /**
1828     * Returns a copy of this datetime with the second of minute field updated.
1829     * <p>
1830     * LocalDateTime is immutable, so there are no set methods.
1831     * Instead, this method returns a new instance with the value of
1832     * second of minute changed.
1833     *
1834     * @param second  the second of minute to set
1835     * @return a copy of this object with the field set
1836     * @throws IllegalArgumentException if the value is invalid
1837     */
1838    public LocalDateTime withSecondOfMinute(int second) {
1839        return withLocalMillis(getChronology().secondOfMinute().set(getLocalMillis(), second));
1840    }
1841
1842    /**
1843     * Returns a copy of this datetime with the millis of second field updated.
1844     * <p>
1845     * LocalDateTime is immutable, so there are no set methods.
1846     * Instead, this method returns a new instance with the value of
1847     * millis of second changed.
1848     *
1849     * @param millis  the millis of second to set
1850     * @return a copy of this object with the field set
1851     * @throws IllegalArgumentException if the value is invalid
1852     */
1853    public LocalDateTime withMillisOfSecond(int millis) {
1854        return withLocalMillis(getChronology().millisOfSecond().set(getLocalMillis(), millis));
1855    }
1856
1857    /**
1858     * Returns a copy of this datetime with the millis of day field updated.
1859     * <p>
1860     * LocalDateTime is immutable, so there are no set methods.
1861     * Instead, this method returns a new instance with the value of
1862     * millis of day changed.
1863     *
1864     * @param millis  the millis of day to set
1865     * @return a copy of this object with the field set
1866     * @throws IllegalArgumentException if the value is invalid
1867     */
1868    public LocalDateTime withMillisOfDay(int millis) {
1869        return withLocalMillis(getChronology().millisOfDay().set(getLocalMillis(), millis));
1870    }
1871
1872    //-----------------------------------------------------------------------
1873    /**
1874     * Get the era property which provides access to advanced functionality.
1875     *
1876     * @return the era property
1877     */
1878    public Property era() {
1879        return new Property(this, getChronology().era());
1880    }
1881
1882    /**
1883     * Get the century of era property which provides access to advanced functionality.
1884     *
1885     * @return the year of era property
1886     */
1887    public Property centuryOfEra() {
1888        return new Property(this, getChronology().centuryOfEra());
1889    }
1890
1891    /**
1892     * Get the year of century property which provides access to advanced functionality.
1893     *
1894     * @return the year of era property
1895     */
1896    public Property yearOfCentury() {
1897        return new Property(this, getChronology().yearOfCentury());
1898    }
1899
1900    /**
1901     * Get the year of era property which provides access to advanced functionality.
1902     *
1903     * @return the year of era property
1904     */
1905    public Property yearOfEra() {
1906        return new Property(this, getChronology().yearOfEra());
1907    }
1908
1909    /**
1910     * Get the year property which provides access to advanced functionality.
1911     *
1912     * @return the year property
1913     */
1914    public Property year() {
1915        return new Property(this, getChronology().year());
1916    }
1917
1918    /**
1919     * Get the weekyear property which provides access to advanced functionality.
1920     *
1921     * @return the weekyear property
1922     */
1923    public Property weekyear() {
1924        return new Property(this, getChronology().weekyear());
1925    }
1926
1927    /**
1928     * Get the month of year property which provides access to advanced functionality.
1929     *
1930     * @return the month of year property
1931     */
1932    public Property monthOfYear() {
1933        return new Property(this, getChronology().monthOfYear());
1934    }
1935
1936    /**
1937     * Get the week of a week based year property which provides access to advanced functionality.
1938     *
1939     * @return the week of a week based year property
1940     */
1941    public Property weekOfWeekyear() {
1942        return new Property(this, getChronology().weekOfWeekyear());
1943    }
1944
1945    /**
1946     * Get the day of year property which provides access to advanced functionality.
1947     *
1948     * @return the day of year property
1949     */
1950    public Property dayOfYear() {
1951        return new Property(this, getChronology().dayOfYear());
1952    }
1953
1954    /**
1955     * Get the day of month property which provides access to advanced functionality.
1956     *
1957     * @return the day of month property
1958     */
1959    public Property dayOfMonth() {
1960        return new Property(this, getChronology().dayOfMonth());
1961    }
1962
1963    /**
1964     * Get the day of week property which provides access to advanced functionality.
1965     *
1966     * @return the day of week property
1967     */
1968    public Property dayOfWeek() {
1969        return new Property(this, getChronology().dayOfWeek());
1970    }
1971
1972    //-----------------------------------------------------------------------
1973    /**
1974     * Get the hour of day field property which provides access to advanced functionality.
1975     * 
1976     * @return the hour of day property
1977     */
1978    public Property hourOfDay() {
1979        return new Property(this, getChronology().hourOfDay());
1980    }
1981
1982    /**
1983     * Get the minute of hour field property which provides access to advanced functionality.
1984     * 
1985     * @return the minute of hour property
1986     */
1987    public Property minuteOfHour() {
1988        return new Property(this, getChronology().minuteOfHour());
1989    }
1990
1991    /**
1992     * Get the second of minute field property which provides access to advanced functionality.
1993     * 
1994     * @return the second of minute property
1995     */
1996    public Property secondOfMinute() {
1997        return new Property(this, getChronology().secondOfMinute());
1998    }
1999
2000    /**
2001     * Get the millis of second property which provides access to advanced functionality.
2002     * 
2003     * @return the millis of second property
2004     */
2005    public Property millisOfSecond() {
2006        return new Property(this, getChronology().millisOfSecond());
2007    }
2008
2009    /**
2010     * Get the millis of day property which provides access to advanced functionality.
2011     * 
2012     * @return the millis of day property
2013     */
2014    public Property millisOfDay() {
2015        return new Property(this, getChronology().millisOfDay());
2016    }
2017
2018    //-----------------------------------------------------------------------
2019    /**
2020     * Output the date time in ISO8601 format (yyyy-MM-ddTHH:mm:ss.SSS).
2021     * 
2022     * @return ISO8601 time formatted string.
2023     */
2024    @ToString
2025    public String toString() {
2026        return ISODateTimeFormat.dateTime().print(this);
2027    }
2028
2029    /**
2030     * Output the date using the specified format pattern.
2031     *
2032     * @param pattern  the pattern specification, null means use <code>toString</code>
2033     * @see org.joda.time.format.DateTimeFormat
2034     */
2035    public String toString(String pattern) {
2036        if (pattern == null) {
2037            return toString();
2038        }
2039        return DateTimeFormat.forPattern(pattern).print(this);
2040    }
2041
2042    /**
2043     * Output the date using the specified format pattern.
2044     *
2045     * @param pattern  the pattern specification, null means use <code>toString</code>
2046     * @param locale  Locale to use, null means default
2047     * @see org.joda.time.format.DateTimeFormat
2048     */
2049    public String toString(String pattern, Locale locale) throws IllegalArgumentException {
2050        if (pattern == null) {
2051            return toString();
2052        }
2053        return DateTimeFormat.forPattern(pattern).withLocale(locale).print(this);
2054    }
2055
2056    //-----------------------------------------------------------------------
2057    /**
2058     * LocalDateTime.Property binds a LocalDateTime to a DateTimeField allowing
2059     * powerful datetime functionality to be easily accessed.
2060     * <p>
2061     * The simplest use of this class is as an alternative get method, here used to
2062     * get the year '1972' (as an int) and the month 'December' (as a String).
2063     * <pre>
2064     * LocalDateTime dt = new LocalDateTime(1972, 12, 3, 0, 0);
2065     * int year = dt.year().get();
2066     * String monthStr = dt.month().getAsText();
2067     * </pre>
2068     * <p>
2069     * Methods are also provided that allow date modification. These return
2070     * new instances of LocalDateTime - they do not modify the original.
2071     * The example below yields two independent immutable date objects
2072     * 20 years apart.
2073     * <pre>
2074     * LocalDateTime dt = new LocalDateTime(1972, 12, 3, 0, 0);
2075     * LocalDateTime dt1920 = dt.year().setCopy(1920);
2076     * </pre>
2077     * <p>
2078     * LocalDateTime.Property itself is thread-safe and immutable, as well as the
2079     * LocalDateTime being operated on.
2080     *
2081     * @author Stephen Colebourne
2082     * @author Brian S O'Neill
2083     * @since 1.3
2084     */
2085    public static final class Property extends AbstractReadableInstantFieldProperty {
2086        
2087        /** Serialization version */
2088        private static final long serialVersionUID = -358138762846288L;
2089        
2090        /** The instant this property is working against */
2091        private transient LocalDateTime iInstant;
2092        /** The field this property is working against */
2093        private transient DateTimeField iField;
2094        
2095        /**
2096         * Constructor.
2097         * 
2098         * @param instant  the instant to set
2099         * @param field  the field to use
2100         */
2101        Property(LocalDateTime instant, DateTimeField field) {
2102            super();
2103            iInstant = instant;
2104            iField = field;
2105        }
2106        
2107        /**
2108         * Writes the property in a safe serialization format.
2109         */
2110        private void writeObject(ObjectOutputStream oos) throws IOException {
2111            oos.writeObject(iInstant);
2112            oos.writeObject(iField.getType());
2113        }
2114
2115        /**
2116         * Reads the property from a safe serialization format.
2117         */
2118        private void readObject(ObjectInputStream oos) throws IOException, ClassNotFoundException {
2119            iInstant = (LocalDateTime) oos.readObject();
2120            DateTimeFieldType type = (DateTimeFieldType) oos.readObject();
2121            iField = type.getField(iInstant.getChronology());
2122        }
2123
2124        //-----------------------------------------------------------------------
2125        /**
2126         * Gets the field being used.
2127         * 
2128         * @return the field
2129         */
2130        public DateTimeField getField() {
2131            return iField;
2132        }
2133        
2134        /**
2135         * Gets the milliseconds of the datetime that this property is linked to.
2136         * 
2137         * @return the milliseconds
2138         */
2139        protected long getMillis() {
2140            return iInstant.getLocalMillis();
2141        }
2142        
2143        /**
2144         * Gets the chronology of the datetime that this property is linked to.
2145         * 
2146         * @return the chronology
2147         * @since 1.4
2148         */
2149        protected Chronology getChronology() {
2150            return iInstant.getChronology();
2151        }
2152        
2153        /**
2154         * Gets the LocalDateTime object linked to this property.
2155         * 
2156         * @return the linked LocalDateTime
2157         */
2158        public LocalDateTime getLocalDateTime() {
2159            return iInstant;
2160        }
2161        
2162        //-----------------------------------------------------------------------
2163        /**
2164         * Adds to this field in a copy of this LocalDateTime.
2165         * <p>
2166         * The LocalDateTime attached to this property is unchanged by this call.
2167         *
2168         * @param value  the value to add to the field in the copy
2169         * @return a copy of the LocalDateTime with the field value changed
2170         * @throws IllegalArgumentException if the value isn't valid
2171         */
2172        public LocalDateTime addToCopy(int value) {
2173            return iInstant.withLocalMillis(iField.add(iInstant.getLocalMillis(), value));
2174        }
2175        
2176        /**
2177         * Adds to this field in a copy of this LocalDateTime.
2178         * <p>
2179         * The LocalDateTime attached to this property is unchanged by this call.
2180         *
2181         * @param value  the value to add to the field in the copy
2182         * @return a copy of the LocalDateTime with the field value changed
2183         * @throws IllegalArgumentException if the value isn't valid
2184         */
2185        public LocalDateTime addToCopy(long value) {
2186            return iInstant.withLocalMillis(iField.add(iInstant.getLocalMillis(), value));
2187        }
2188        
2189        /**
2190         * Adds to this field, possibly wrapped, in a copy of this LocalDateTime.
2191         * A field wrapped operation only changes this field.
2192         * Thus 31st January addWrapField one day goes to the 1st January.
2193         * <p>
2194         * The LocalDateTime attached to this property is unchanged by this call.
2195         *
2196         * @param value  the value to add to the field in the copy
2197         * @return a copy of the LocalDateTime with the field value changed
2198         * @throws IllegalArgumentException if the value isn't valid
2199         */
2200        public LocalDateTime addWrapFieldToCopy(int value) {
2201            return iInstant.withLocalMillis(iField.addWrapField(iInstant.getLocalMillis(), value));
2202        }
2203        
2204        //-----------------------------------------------------------------------
2205        /**
2206         * Sets this field in a copy of the LocalDateTime.
2207         * <p>
2208         * The LocalDateTime attached to this property is unchanged by this call.
2209         *
2210         * @param value  the value to set the field in the copy to
2211         * @return a copy of the LocalDateTime with the field value changed
2212         * @throws IllegalArgumentException if the value isn't valid
2213         */
2214        public LocalDateTime setCopy(int value) {
2215            return iInstant.withLocalMillis(iField.set(iInstant.getLocalMillis(), value));
2216        }
2217        
2218        /**
2219         * Sets this field in a copy of the LocalDateTime to a parsed text value.
2220         * <p>
2221         * The LocalDateTime attached to this property is unchanged by this call.
2222         *
2223         * @param text  the text value to set
2224         * @param locale  optional locale to use for selecting a text symbol
2225         * @return a copy of the LocalDateTime with the field value changed
2226         * @throws IllegalArgumentException if the text value isn't valid
2227         */
2228        public LocalDateTime setCopy(String text, Locale locale) {
2229            return iInstant.withLocalMillis(iField.set(iInstant.getLocalMillis(), text, locale));
2230        }
2231        
2232        /**
2233         * Sets this field in a copy of the LocalDateTime to a parsed text value.
2234         * <p>
2235         * The LocalDateTime attached to this property is unchanged by this call.
2236         *
2237         * @param text  the text value to set
2238         * @return a copy of the LocalDateTime with the field value changed
2239         * @throws IllegalArgumentException if the text value isn't valid
2240         */
2241        public LocalDateTime setCopy(String text) {
2242            return setCopy(text, null);
2243        }
2244        
2245        //-----------------------------------------------------------------------
2246        /**
2247         * Returns a new LocalDateTime with this field set to the maximum value
2248         * for this field.
2249         * <p>
2250         * This operation is useful for obtaining a LocalDateTime on the last day
2251         * of the month, as month lengths vary.
2252         * <pre>
2253         * LocalDateTime lastDayOfMonth = dt.dayOfMonth().withMaximumValue();
2254         * </pre>
2255         * <p>
2256         * The LocalDateTime attached to this property is unchanged by this call.
2257         *
2258         * @return a copy of the LocalDateTime with this field set to its maximum
2259         */
2260        public LocalDateTime withMaximumValue() {
2261            return setCopy(getMaximumValue());
2262        }
2263        
2264        /**
2265         * Returns a new LocalDateTime with this field set to the minimum value
2266         * for this field.
2267         * <p>
2268         * The LocalDateTime attached to this property is unchanged by this call.
2269         *
2270         * @return a copy of the LocalDateTime with this field set to its minimum
2271         */
2272        public LocalDateTime withMinimumValue() {
2273            return setCopy(getMinimumValue());
2274        }
2275        
2276        //-----------------------------------------------------------------------
2277        /**
2278         * Rounds to the lowest whole unit of this field on a copy of this
2279         * LocalDateTime.
2280         * <p>
2281         * For example, rounding floor on the hourOfDay field of a LocalDateTime
2282         * where the time is 10:30 would result in new LocalDateTime with the
2283         * time of 10:00.
2284         *
2285         * @return a copy of the LocalDateTime with the field value changed
2286         */
2287        public LocalDateTime roundFloorCopy() {
2288            return iInstant.withLocalMillis(iField.roundFloor(iInstant.getLocalMillis()));
2289        }
2290        
2291        /**
2292         * Rounds to the highest whole unit of this field on a copy of this
2293         * LocalDateTime.
2294         * <p>
2295         * For example, rounding floor on the hourOfDay field of a LocalDateTime
2296         * where the time is 10:30 would result in new LocalDateTime with the
2297         * time of 11:00.
2298         *
2299         * @return a copy of the LocalDateTime with the field value changed
2300         */
2301        public LocalDateTime roundCeilingCopy() {
2302            return iInstant.withLocalMillis(iField.roundCeiling(iInstant.getLocalMillis()));
2303        }
2304        
2305        /**
2306         * Rounds to the nearest whole unit of this field on a copy of this
2307         * LocalDateTime, favoring the floor if halfway.
2308         *
2309         * @return a copy of the LocalDateTime with the field value changed
2310         */
2311        public LocalDateTime roundHalfFloorCopy() {
2312            return iInstant.withLocalMillis(iField.roundHalfFloor(iInstant.getLocalMillis()));
2313        }
2314        
2315        /**
2316         * Rounds to the nearest whole unit of this field on a copy of this
2317         * LocalDateTime, favoring the ceiling if halfway.
2318         *
2319         * @return a copy of the LocalDateTime with the field value changed
2320         */
2321        public LocalDateTime roundHalfCeilingCopy() {
2322            return iInstant.withLocalMillis(iField.roundHalfCeiling(iInstant.getLocalMillis()));
2323        }
2324        
2325        /**
2326         * Rounds to the nearest whole unit of this field on a copy of this
2327         * LocalDateTime.  If halfway, the ceiling is favored over the floor
2328         * only if it makes this field's value even.
2329         *
2330         * @return a copy of the LocalDateTime with the field value changed
2331         */
2332        public LocalDateTime roundHalfEvenCopy() {
2333            return iInstant.withLocalMillis(iField.roundHalfEven(iInstant.getLocalMillis()));
2334        }
2335    }
2336
2337}