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