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