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