001 /*
002 * Copyright 2001-2006 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.Locale;
023
024 import org.joda.time.base.BaseDateTime;
025 import org.joda.time.field.AbstractReadableInstantFieldProperty;
026 import org.joda.time.format.ISODateTimeFormat;
027
028 /**
029 * DateMidnight defines a date where the time component is fixed at midnight.
030 * The class uses a time zone, thus midnight is local unless a UTC time zone is used.
031 * <p>
032 * It is important to emphasise that this class represents the time of midnight on
033 * any given day.
034 * Note that midnight is defined as 00:00, which is at the very start of a day.
035 * <p>
036 * This class does not represent a day, but the millisecond instant at midnight.
037 * If you need a class that represents the whole day, then an {@link Interval} or
038 * a {@link LocalDate} may be more suitable.
039 * <p>
040 * This class uses a Chronology internally. The Chronology determines how the
041 * millisecond instant value is converted into the date time fields.
042 * The default Chronology is <code>ISOChronology</code> which is the agreed
043 * international standard and compatable with the modern Gregorian calendar.
044 *
045 * <p>Each individual field can be queried in two ways:
046 * <ul>
047 * <li><code>getDayOfMonth()</code>
048 * <li><code>dayOfMonth().get()</code>
049 * </ul>
050 * The second technique also provides access to other useful methods on the
051 * field:
052 * <ul>
053 * <li>numeric value
054 * <li>text value
055 * <li>short text value
056 * <li>maximum/minimum values
057 * <li>add/subtract
058 * <li>set
059 * <li>rounding
060 * </ul>
061 *
062 * <p>
063 * DateMidnight is thread-safe and immutable, provided that the Chronology is as well.
064 * All standard Chronology classes supplied are thread-safe and immutable.
065 *
066 * @author Stephen Colebourne
067 * @since 1.0
068 */
069 public final class DateMidnight
070 extends BaseDateTime
071 implements ReadableDateTime, Serializable {
072
073 /** Serialization lock */
074 private static final long serialVersionUID = 156371964018738L;
075
076 // Constructors
077 //-----------------------------------------------------------------------
078 /**
079 * Constructs an instance set to the current system millisecond time
080 * using <code>ISOChronology</code> in the default time zone.
081 * The constructed object will have a local time of midnight.
082 */
083 public DateMidnight() {
084 super();
085 }
086
087 /**
088 * Constructs an instance set to the current system millisecond time
089 * using <code>ISOChronology</code> in the specified time zone.
090 * The constructed object will have a local time of midnight.
091 * <p>
092 * If the specified time zone is null, the default zone is used.
093 *
094 * @param zone the time zone, null means default zone
095 */
096 public DateMidnight(DateTimeZone zone) {
097 super(zone);
098 }
099
100 /**
101 * Constructs an instance set to the current system millisecond time
102 * using the specified chronology.
103 * The constructed object will have a local time of midnight.
104 * <p>
105 * If the chronology is null, <code>ISOChronology</code>
106 * in the default time zone is used.
107 *
108 * @param chronology the chronology, null means ISOChronology in default zone
109 */
110 public DateMidnight(Chronology chronology) {
111 super(chronology);
112 }
113
114 //-----------------------------------------------------------------------
115 /**
116 * Constructs an instance set to the milliseconds from 1970-01-01T00:00:00Z
117 * using <code>ISOChronology</code> in the default time zone.
118 * The constructed object will have a local time of midnight.
119 *
120 * @param instant the milliseconds from 1970-01-01T00:00:00Z
121 */
122 public DateMidnight(long instant) {
123 super(instant);
124 }
125
126 /**
127 * Constructs an instance set to the milliseconds from 1970-01-01T00:00:00Z
128 * using <code>ISOChronology</code> in the specified time zone.
129 * The constructed object will have a local time of midnight.
130 * <p>
131 * If the specified time zone is null, the default zone is used.
132 *
133 * @param instant the milliseconds from 1970-01-01T00:00:00Z
134 * @param zone the time zone, null means default zone
135 */
136 public DateMidnight(long instant, DateTimeZone zone) {
137 super(instant, zone);
138 }
139
140 /**
141 * Constructs an instance set to the milliseconds from 1970-01-01T00:00:00Z
142 * using the specified chronology.
143 * The constructed object will have a local time of midnight.
144 * <p>
145 * If the chronology is null, <code>ISOChronology</code>
146 * in the default time zone is used.
147 *
148 * @param instant the milliseconds from 1970-01-01T00:00:00Z
149 * @param chronology the chronology, null means ISOChronology in default zone
150 */
151 public DateMidnight(long instant, Chronology chronology) {
152 super(instant, chronology);
153 }
154
155 //-----------------------------------------------------------------------
156 /**
157 * Constructs an instance from an Object that represents a datetime.
158 * The constructed object will have a local time of midnight.
159 * <p>
160 * If the object implies a chronology (such as GregorianCalendar does),
161 * then that chronology will be used. Otherwise, ISO default is used.
162 * Thus if a GregorianCalendar is passed in, the chronology used will
163 * be GJ, but if a Date is passed in the chronology will be ISO.
164 * <p>
165 * The recognised object types are defined in
166 * {@link org.joda.time.convert.ConverterManager ConverterManager} and
167 * include ReadableInstant, String, Calendar and Date.
168 * The String formats are described by {@link ISODateTimeFormat#dateTimeParser()}.
169 *
170 * @param instant the datetime object, null means now
171 * @throws IllegalArgumentException if the instant is invalid
172 */
173 public DateMidnight(Object instant) {
174 super(instant, (Chronology) null);
175 }
176
177 /**
178 * Constructs an instance from an Object that represents a datetime,
179 * forcing the time zone to that specified.
180 * The constructed object will have a local time of midnight.
181 * <p>
182 * If the object implies a chronology (such as GregorianCalendar does),
183 * then that chronology will be used, but with the time zone adjusted.
184 * Otherwise, ISO is used in the specified time zone.
185 * If the specified time zone is null, the default zone is used.
186 * Thus if a GregorianCalendar is passed in, the chronology used will
187 * be GJ, but if a Date is passed in the chronology will be ISO.
188 * <p>
189 * The recognised object types are defined in
190 * {@link org.joda.time.convert.ConverterManager ConverterManager} and
191 * include ReadableInstant, String, Calendar and Date.
192 * The String formats are described by {@link ISODateTimeFormat#dateTimeParser()}.
193 *
194 * @param instant the datetime object, null means now
195 * @param zone the time zone, null means default time zone
196 * @throws IllegalArgumentException if the instant is invalid
197 */
198 public DateMidnight(Object instant, DateTimeZone zone) {
199 super(instant, zone);
200 }
201
202 /**
203 * Constructs an instance from an Object that represents a datetime,
204 * using the specified chronology.
205 * The constructed object will have a local time of midnight.
206 * <p>
207 * If the chronology is null, ISO in the default time zone is used.
208 * Any chronology implied by the object (such as GregorianCalendar does)
209 * is ignored.
210 * <p>
211 * The recognised object types are defined in
212 * {@link org.joda.time.convert.ConverterManager ConverterManager} and
213 * include ReadableInstant, String, Calendar and Date.
214 * The String formats are described by {@link ISODateTimeFormat#dateTimeParser()}.
215 *
216 * @param instant the datetime object, null means now
217 * @param chronology the chronology, null means ISOChronology in default zone
218 * @throws IllegalArgumentException if the instant is invalid
219 */
220 public DateMidnight(Object instant, Chronology chronology) {
221 super(instant, DateTimeUtils.getChronology(chronology));
222 }
223
224 //-----------------------------------------------------------------------
225 /**
226 * Constructs an instance from datetime field values
227 * using <code>ISOChronology</code> in the default time zone.
228 * The constructed object will have a local time of midnight.
229 *
230 * @param year the year
231 * @param monthOfYear the month of the year
232 * @param dayOfMonth the day of the month
233 */
234 public DateMidnight(int year, int monthOfYear, int dayOfMonth) {
235 super(year, monthOfYear, dayOfMonth, 0, 0, 0, 0);
236 }
237
238 /**
239 * Constructs an instance from datetime field values
240 * using <code>ISOChronology</code> in the specified time zone.
241 * The constructed object will have a local time of midnight.
242 * <p>
243 * If the specified time zone is null, the default zone is used.
244 *
245 * @param year the year
246 * @param monthOfYear the month of the year
247 * @param dayOfMonth the day of the month
248 * @param zone the time zone, null means default time zone
249 */
250 public DateMidnight(int year, int monthOfYear, int dayOfMonth, DateTimeZone zone) {
251 super(year, monthOfYear, dayOfMonth, 0, 0, 0, 0, zone);
252 }
253
254 /**
255 * Constructs an instance from datetime field values
256 * using the specified chronology.
257 * The constructed object will have a local time of midnight.
258 * <p>
259 * If the chronology is null, <code>ISOChronology</code>
260 * in the default time zone is used.
261 *
262 * @param year the year
263 * @param monthOfYear the month of the year
264 * @param dayOfMonth the day of the month
265 * @param chronology the chronology, null means ISOChronology in default zone
266 */
267 public DateMidnight(int year, int monthOfYear, int dayOfMonth, Chronology chronology) {
268 super(year, monthOfYear, dayOfMonth, 0, 0, 0, 0, chronology);
269 }
270
271 /**
272 * Rounds the specified instant to midnight.
273 *
274 * @param instant the milliseconds from 1970-01-01T00:00:00Z to round
275 * @param chronology the chronology to use, not null
276 * @return the updated instant, rounded to midnight
277 */
278 protected long checkInstant(long instant, Chronology chronology) {
279 return chronology.dayOfMonth().roundFloor(instant);
280 }
281
282 //-----------------------------------------------------------------------
283 /**
284 * Returns a copy of this date with a different millisecond instant.
285 * The returned object will have a local time of midnight.
286 * <p>
287 * Only the millis will change, the chronology and time zone are kept.
288 * The returned object will be either be a new instance or <code>this</code>.
289 *
290 * @param newMillis the new millis, from 1970-01-01T00:00:00Z
291 * @return a copy of this instant with different millis
292 */
293 public DateMidnight withMillis(long newMillis) {
294 Chronology chrono = getChronology();
295 newMillis = checkInstant(newMillis, chrono);
296 return (newMillis == getMillis() ? this : new DateMidnight(newMillis, chrono));
297 }
298
299 /**
300 * Returns a copy of this date with a different chronology, potentially
301 * changing the day in unexpected ways.
302 * <p>
303 * This method creates a new DateMidnight using the midnight millisecond value
304 * and the new chronology. If the same or similar chronology is specified, but
305 * with a different time zone, the day may change. This occurs because the new
306 * DateMidnight rounds down the millisecond value to get to midnight, and the
307 * time zone change may result in a rounding down to a different day.
308 * <p>
309 * For example, changing time zone from London (+00:00) to Paris (+01:00) will
310 * retain the same day, but changing from Paris to London will change the day.
311 * (When its midnight in London its the same day in Paris, but when its midnight
312 * in Paris its still the previous day in London)
313 * <p>
314 * To avoid these unusual effects, use {@link #withZoneRetainFields(DateTimeZone)}
315 * to change time zones.
316 *
317 * @param newChronology the new chronology
318 * @return a copy of this instant with a different chronology
319 */
320 public DateMidnight withChronology(Chronology newChronology) {
321 return (newChronology == getChronology() ? this : new DateMidnight(getMillis(), newChronology));
322 }
323
324 /**
325 * Returns a copy of this date with a different time zone, preserving the day
326 * The returned object will have a local time of midnight in the new zone on
327 * the same day as the original instant.
328 *
329 * @param newZone the new time zone, null means default
330 * @return a copy of this instant with a different time zone
331 */
332 public DateMidnight withZoneRetainFields(DateTimeZone newZone) {
333 newZone = DateTimeUtils.getZone(newZone);
334 DateTimeZone originalZone = DateTimeUtils.getZone(getZone());
335 if (newZone == originalZone) {
336 return this;
337 }
338
339 long millis = originalZone.getMillisKeepLocal(newZone, getMillis());
340 return new DateMidnight(millis, getChronology().withZone(newZone));
341 }
342
343 //-----------------------------------------------------------------------
344 /**
345 * Returns a copy of this date with the partial set of fields replacing those
346 * from this instance.
347 * <p>
348 * For example, if the partial is a <code>LocalDate</code> then the date fields
349 * would be changed in the returned instance.
350 * If the partial is null, then <code>this</code> is returned.
351 *
352 * @param partial the partial set of fields to apply to this datetime, null ignored
353 * @return a copy of this datetime with a different set of fields
354 * @throws IllegalArgumentException if any value is invalid
355 */
356 public DateMidnight withFields(ReadablePartial partial) {
357 if (partial == null) {
358 return this;
359 }
360 return withMillis(getChronology().set(partial, getMillis()));
361 }
362
363 /**
364 * Returns a copy of this date with the specified field set to a new value.
365 * <p>
366 * For example, if the field type is <code>dayOfMonth</code> then the day of month
367 * field would be changed in the returned instance.
368 * If the field type is null, then <code>this</code> is returned.
369 * <p>
370 * These three lines are equivalent:
371 * <pre>
372 * DateTime updated = dt.withField(DateTimeFieldType.dayOfMonth(), 6);
373 * DateTime updated = dt.dayOfMonth().setCopy(6);
374 * DateTime updated = dt.property(DateTimeFieldType.dayOfMonth()).setCopy(6);
375 * </pre>
376 *
377 * @param fieldType the field type to set, not null
378 * @param value the value to set
379 * @return a copy of this datetime with the field set
380 * @throws IllegalArgumentException if the value is null or invalid
381 */
382 public DateMidnight withField(DateTimeFieldType fieldType, int value) {
383 if (fieldType == null) {
384 throw new IllegalArgumentException("Field must not be null");
385 }
386 long instant = fieldType.getField(getChronology()).set(getMillis(), value);
387 return withMillis(instant);
388 }
389
390 /**
391 * Returns a copy of this date with the value of the specified field increased.
392 * <p>
393 * If the addition is zero or the field is null, then <code>this</code> is returned.
394 * <p>
395 * These three lines are equivalent:
396 * <pre>
397 * DateMidnight added = dt.withFieldAdded(DateTimeFieldType.year(), 6);
398 * DateMidnight added = dt.plusYears(6);
399 * DateMidnight added = dt.year().addToCopy(6);
400 * </pre>
401 *
402 * @param fieldType the field type to add to, not null
403 * @param amount the amount to add
404 * @return a copy of this datetime with the field updated
405 * @throws IllegalArgumentException if the value is null or invalid
406 * @throws ArithmeticException if the new datetime exceeds the capacity of a long
407 */
408 public DateMidnight withFieldAdded(DurationFieldType fieldType, int amount) {
409 if (fieldType == null) {
410 throw new IllegalArgumentException("Field must not be null");
411 }
412 if (amount == 0) {
413 return this;
414 }
415 long instant = fieldType.getField(getChronology()).add(getMillis(), amount);
416 return withMillis(instant);
417 }
418
419 //-----------------------------------------------------------------------
420 /**
421 * Returns a copy of this date with the specified duration added.
422 * <p>
423 * If the addition is zero, then <code>this</code> is returned.
424 *
425 * @param durationToAdd the duration to add to this one
426 * @param scalar the amount of times to add, such as -1 to subtract once
427 * @return a copy of this datetime with the duration added
428 * @throws ArithmeticException if the new datetime exceeds the capacity of a long
429 */
430 public DateMidnight withDurationAdded(long durationToAdd, int scalar) {
431 if (durationToAdd == 0 || scalar == 0) {
432 return this;
433 }
434 long instant = getChronology().add(getMillis(), durationToAdd, scalar);
435 return withMillis(instant);
436 }
437
438 /**
439 * Returns a copy of this date with the specified duration added.
440 * <p>
441 * If the addition is zero, then <code>this</code> is returned.
442 *
443 * @param durationToAdd the duration to add to this one, null means zero
444 * @param scalar the amount of times to add, such as -1 to subtract once
445 * @return a copy of this datetime with the duration added
446 * @throws ArithmeticException if the new datetime exceeds the capacity of a long
447 */
448 public DateMidnight withDurationAdded(ReadableDuration durationToAdd, int scalar) {
449 if (durationToAdd == null || scalar == 0) {
450 return this;
451 }
452 return withDurationAdded(durationToAdd.getMillis(), scalar);
453 }
454
455 /**
456 * Returns a copy of this date with the specified period added.
457 * <p>
458 * If the addition is zero, then <code>this</code> is returned.
459 * <p>
460 * This method is typically used to add multiple copies of complex
461 * period instances. Adding one field is best achieved using methods
462 * like {@link #withFieldAdded(DurationFieldType, int)}
463 * or {@link #plusYears(int)}.
464 *
465 * @param period the period to add to this one, null means zero
466 * @param scalar the amount of times to add, such as -1 to subtract once
467 * @return a copy of this datetime with the period added
468 * @throws ArithmeticException if the new datetime exceeds the capacity of a long
469 */
470 public DateMidnight withPeriodAdded(ReadablePeriod period, int scalar) {
471 if (period == null || scalar == 0) {
472 return this;
473 }
474 long instant = getChronology().add(period, getMillis(), scalar);
475 return withMillis(instant);
476 }
477
478 //-----------------------------------------------------------------------
479 /**
480 * Returns a copy of this date with the specified duration added.
481 * <p>
482 * If the amount is zero, then <code>this</code> is returned.
483 *
484 * @param duration the duration, in millis, to add to this one
485 * @return a copy of this datetime with the duration added
486 * @throws ArithmeticException if the new datetime exceeds the capacity of a long
487 */
488 public DateMidnight plus(long duration) {
489 return withDurationAdded(duration, 1);
490 }
491
492 /**
493 * Returns a copy of this date with the specified duration added.
494 * <p>
495 * If the amount is zero or null, then <code>this</code> is returned.
496 *
497 * @param duration the duration to add to this one, null means zero
498 * @return a copy of this datetime with the duration added
499 * @throws ArithmeticException if the new datetime exceeds the capacity of a long
500 */
501 public DateMidnight plus(ReadableDuration duration) {
502 return withDurationAdded(duration, 1);
503 }
504
505 /**
506 * Returns a copy of this date with the specified period added.
507 * <p>
508 * If the amount is zero or null, then <code>this</code> is returned.
509 * <p>
510 * This method is typically used to add complex period instances.
511 * Adding one field is best achieved using methods
512 * like {@link #plusYears(int)}.
513 *
514 * @param period the duration to add to this one, null means zero
515 * @return a copy of this datetime with the period added
516 * @throws ArithmeticException if the new datetime exceeds the capacity of a long
517 */
518 public DateMidnight plus(ReadablePeriod period) {
519 return withPeriodAdded(period, 1);
520 }
521
522 //-----------------------------------------------------------------------
523 /**
524 * Returns a copy of this date plus the specified number of years.
525 * <p>
526 * This datetime instance is immutable and unaffected by this method call.
527 * <p>
528 * The following three lines are identical in effect:
529 * <pre>
530 * DateMidnight added = dt.plusYears(6);
531 * DateMidnight added = dt.plus(Period.years(6));
532 * DateMidnight added = dt.withFieldAdded(DurationFieldType.years(), 6);
533 * </pre>
534 *
535 * @param years the amount of years to add, may be negative
536 * @return the new datetime plus the increased years
537 * @since 1.1
538 */
539 public DateMidnight plusYears(int years) {
540 if (years == 0) {
541 return this;
542 }
543 long instant = getChronology().years().add(getMillis(), years);
544 return withMillis(instant);
545 }
546
547 /**
548 * Returns a copy of this date plus the specified number of months.
549 * <p>
550 * This datetime instance is immutable and unaffected by this method call.
551 * <p>
552 * The following three lines are identical in effect:
553 * <pre>
554 * DateMidnight added = dt.plusMonths(6);
555 * DateMidnight added = dt.plus(Period.months(6));
556 * DateMidnight added = dt.withFieldAdded(DurationFieldType.months(), 6);
557 * </pre>
558 *
559 * @param months the amount of months to add, may be negative
560 * @return the new datetime plus the increased months
561 * @since 1.1
562 */
563 public DateMidnight plusMonths(int months) {
564 if (months == 0) {
565 return this;
566 }
567 long instant = getChronology().months().add(getMillis(), months);
568 return withMillis(instant);
569 }
570
571 /**
572 * Returns a copy of this date plus the specified number of weeks.
573 * <p>
574 * This datetime instance is immutable and unaffected by this method call.
575 * <p>
576 * The following three lines are identical in effect:
577 * <pre>
578 * DateMidnight added = dt.plusWeeks(6);
579 * DateMidnight added = dt.plus(Period.weeks(6));
580 * DateMidnight added = dt.withFieldAdded(DurationFieldType.weeks(), 6);
581 * </pre>
582 *
583 * @param weeks the amount of weeks to add, may be negative
584 * @return the new datetime plus the increased weeks
585 * @since 1.1
586 */
587 public DateMidnight plusWeeks(int weeks) {
588 if (weeks == 0) {
589 return this;
590 }
591 long instant = getChronology().weeks().add(getMillis(), weeks);
592 return withMillis(instant);
593 }
594
595 /**
596 * Returns a copy of this date plus the specified number of days.
597 * <p>
598 * This datetime instance is immutable and unaffected by this method call.
599 * <p>
600 * The following three lines are identical in effect:
601 * <pre>
602 * DateMidnight added = dt.plusDays(6);
603 * DateMidnight added = dt.plus(Period.days(6));
604 * DateMidnight added = dt.withFieldAdded(DurationFieldType.days(), 6);
605 * </pre>
606 *
607 * @param days the amount of days to add, may be negative
608 * @return the new datetime plus the increased days
609 * @since 1.1
610 */
611 public DateMidnight plusDays(int days) {
612 if (days == 0) {
613 return this;
614 }
615 long instant = getChronology().days().add(getMillis(), days);
616 return withMillis(instant);
617 }
618
619 //-----------------------------------------------------------------------
620 /**
621 * Returns a copy of this date with the specified duration taken away.
622 * <p>
623 * If the amount is zero or null, then <code>this</code> is returned.
624 *
625 * @param duration the duration, in millis, to reduce this instant by
626 * @return a copy of this datetime with the duration taken away
627 * @throws ArithmeticException if the new datetime exceeds the capacity of a long
628 */
629 public DateMidnight minus(long duration) {
630 return withDurationAdded(duration, -1);
631 }
632
633 /**
634 * Returns a copy of this date with the specified duration taken away.
635 * <p>
636 * If the amount is zero or null, then <code>this</code> is returned.
637 *
638 * @param duration the duration to reduce this instant by
639 * @return a copy of this datetime with the duration taken away
640 * @throws ArithmeticException if the new datetime exceeds the capacity of a long
641 */
642 public DateMidnight minus(ReadableDuration duration) {
643 return withDurationAdded(duration, -1);
644 }
645
646 /**
647 * Returns a copy of this date with the specified period taken away.
648 * <p>
649 * If the amount is zero or null, then <code>this</code> is returned.
650 * <p>
651 * This method is typically used to subtract complex period instances.
652 * Subtracting one field is best achieved using methods
653 * like {@link #minusYears(int)}.
654 *
655 * @param period the period to reduce this instant by
656 * @return a copy of this datetime with the period taken away
657 * @throws ArithmeticException if the new datetime exceeds the capacity of a long
658 */
659 public DateMidnight minus(ReadablePeriod period) {
660 return withPeriodAdded(period, -1);
661 }
662
663 //-----------------------------------------------------------------------
664 /**
665 * Returns a copy of this date minus the specified number of years.
666 * <p>
667 * This datetime instance is immutable and unaffected by this method call.
668 * <p>
669 * The following three lines are identical in effect:
670 * <pre>
671 * DateTime subtracted = dt.minusYears(6);
672 * DateTime subtracted = dt.minus(Period.years(6));
673 * DateTime subtracted = dt.withFieldAdded(DurationFieldType.years(), -6);
674 * </pre>
675 *
676 * @param years the amount of years to subtract, may be negative
677 * @return the new datetime minus the increased years
678 * @since 1.1
679 */
680 public DateMidnight minusYears(int years) {
681 if (years == 0) {
682 return this;
683 }
684 long instant = getChronology().years().subtract(getMillis(), years);
685 return withMillis(instant);
686 }
687
688 /**
689 * Returns a copy of this date minus the specified number of months.
690 * <p>
691 * This datetime instance is immutable and unaffected by this method call.
692 * <p>
693 * The following three lines are identical in effect:
694 * <pre>
695 * DateMidnight subtracted = dt.minusMonths(6);
696 * DateMidnight subtracted = dt.minus(Period.months(6));
697 * DateMidnight subtracted = dt.withFieldAdded(DurationFieldType.months(), -6);
698 * </pre>
699 *
700 * @param months the amount of months to subtract, may be negative
701 * @return the new datetime minus the increased months
702 * @since 1.1
703 */
704 public DateMidnight minusMonths(int months) {
705 if (months == 0) {
706 return this;
707 }
708 long instant = getChronology().months().subtract(getMillis(), months);
709 return withMillis(instant);
710 }
711
712 /**
713 * Returns a copy of this date minus the specified number of weeks.
714 * <p>
715 * This datetime instance is immutable and unaffected by this method call.
716 * <p>
717 * The following three lines are identical in effect:
718 * <pre>
719 * DateMidnight subtracted = dt.minusWeeks(6);
720 * DateMidnight subtracted = dt.minus(Period.weeks(6));
721 * DateMidnight subtracted = dt.withFieldAdded(DurationFieldType.weeks(), -6);
722 * </pre>
723 *
724 * @param weeks the amount of weeks to subtract, may be negative
725 * @return the new datetime minus the increased weeks
726 * @since 1.1
727 */
728 public DateMidnight minusWeeks(int weeks) {
729 if (weeks == 0) {
730 return this;
731 }
732 long instant = getChronology().weeks().subtract(getMillis(), weeks);
733 return withMillis(instant);
734 }
735
736 /**
737 * Returns a copy of this date minus the specified number of days.
738 * <p>
739 * This datetime instance is immutable and unaffected by this method call.
740 * <p>
741 * The following three lines are identical in effect:
742 * <pre>
743 * DateMidnight subtracted = dt.minusDays(6);
744 * DateMidnight subtracted = dt.minus(Period.days(6));
745 * DateMidnight subtracted = dt.withFieldAdded(DurationFieldType.days(), -6);
746 * </pre>
747 *
748 * @param days the amount of days to subtract, may be negative
749 * @return the new datetime minus the increased days
750 * @since 1.1
751 */
752 public DateMidnight minusDays(int days) {
753 if (days == 0) {
754 return this;
755 }
756 long instant = getChronology().days().subtract(getMillis(), days);
757 return withMillis(instant);
758 }
759
760 //-----------------------------------------------------------------------
761 /**
762 * Gets the property object for the specified type, which contains many useful methods.
763 *
764 * @param type the field type to get the chronology for
765 * @return the property object
766 * @throws IllegalArgumentException if the field is null or unsupported
767 */
768 public Property property(DateTimeFieldType type) {
769 if (type == null) {
770 throw new IllegalArgumentException("The DateTimeFieldType must not be null");
771 }
772 DateTimeField field = type.getField(getChronology());
773 if (field.isSupported() == false) {
774 throw new IllegalArgumentException("Field '" + type + "' is not supported");
775 }
776 return new Property(this, field);
777 }
778
779 //-----------------------------------------------------------------------
780 /**
781 * Converts this object to a <code>YearMonthDay</code> using the
782 * same date and chronology.
783 *
784 * @return a YearMonthDay using the same millis and chronology
785 * @deprecated Use LocalDate instead of YearMonthDay
786 */
787 public YearMonthDay toYearMonthDay() {
788 return new YearMonthDay(getMillis(), getChronology());
789 }
790
791 /**
792 * Converts this object to a <code>LocalDate</code> with the
793 * same date and chronology.
794 *
795 * @return a LocalDate with the same date and chronology
796 * @since 1.3
797 */
798 public LocalDate toLocalDate() {
799 return new LocalDate(getMillis(), getChronology());
800 }
801
802 /**
803 * Converts this object to an <code>Interval</code> encompassing
804 * the whole of this day.
805 * <p>
806 * The interval starts at midnight 00:00 and ends at 00:00 the following day,
807 * (which is not included in the interval, as intervals are half-open).
808 *
809 * @return an interval over the day
810 */
811 public Interval toInterval() {
812 Chronology chrono = getChronology();
813 long start = getMillis();
814 long end = DurationFieldType.days().getField(chrono).add(start, 1);
815 return new Interval(start, end, chrono);
816 }
817
818 //-----------------------------------------------------------------------
819 /**
820 * Returns a copy of this date with the era field updated.
821 * <p>
822 * DateMidnight is immutable, so there are no set methods.
823 * Instead, this method returns a new instance with the value of
824 * era changed.
825 *
826 * @param era the era to set
827 * @return a copy of this object with the field set
828 * @throws IllegalArgumentException if the value is invalid
829 * @since 1.3
830 */
831 public DateMidnight withEra(int era) {
832 return withMillis(getChronology().era().set(getMillis(), era));
833 }
834
835 /**
836 * Returns a copy of this date with the century of era field updated.
837 * <p>
838 * DateMidnight is immutable, so there are no set methods.
839 * Instead, this method returns a new instance with the value of
840 * century of era changed.
841 *
842 * @param centuryOfEra the centurey of era to set
843 * @return a copy of this object with the field set
844 * @throws IllegalArgumentException if the value is invalid
845 * @since 1.3
846 */
847 public DateMidnight withCenturyOfEra(int centuryOfEra) {
848 return withMillis(getChronology().centuryOfEra().set(getMillis(), centuryOfEra));
849 }
850
851 /**
852 * Returns a copy of this date with the year of era field updated.
853 * <p>
854 * DateMidnight is immutable, so there are no set methods.
855 * Instead, this method returns a new instance with the value of
856 * year of era changed.
857 *
858 * @param yearOfEra the year of era to set
859 * @return a copy of this object with the field set
860 * @throws IllegalArgumentException if the value is invalid
861 * @since 1.3
862 */
863 public DateMidnight withYearOfEra(int yearOfEra) {
864 return withMillis(getChronology().yearOfEra().set(getMillis(), yearOfEra));
865 }
866
867 /**
868 * Returns a copy of this date with the year of century field updated.
869 * <p>
870 * DateMidnight is immutable, so there are no set methods.
871 * Instead, this method returns a new instance with the value of
872 * year of century changed.
873 *
874 * @param yearOfCentury the year of century to set
875 * @return a copy of this object with the field set
876 * @throws IllegalArgumentException if the value is invalid
877 * @since 1.3
878 */
879 public DateMidnight withYearOfCentury(int yearOfCentury) {
880 return withMillis(getChronology().yearOfCentury().set(getMillis(), yearOfCentury));
881 }
882
883 /**
884 * Returns a copy of this date with the year field updated.
885 * <p>
886 * DateMidnight is immutable, so there are no set methods.
887 * Instead, this method returns a new instance with the value of
888 * year changed.
889 *
890 * @param year the year to set
891 * @return a copy of this object with the field set
892 * @throws IllegalArgumentException if the value is invalid
893 * @since 1.3
894 */
895 public DateMidnight withYear(int year) {
896 return withMillis(getChronology().year().set(getMillis(), year));
897 }
898
899 /**
900 * Returns a copy of this date with the weekyear field updated.
901 * <p>
902 * DateMidnight is immutable, so there are no set methods.
903 * Instead, this method returns a new instance with the value of
904 * weekyear changed.
905 *
906 * @param weekyear the weekyear to set
907 * @return a copy of this object with the field set
908 * @throws IllegalArgumentException if the value is invalid
909 * @since 1.3
910 */
911 public DateMidnight withWeekyear(int weekyear) {
912 return withMillis(getChronology().weekyear().set(getMillis(), weekyear));
913 }
914
915 /**
916 * Returns a copy of this date with the month of year field updated.
917 * <p>
918 * DateMidnight is immutable, so there are no set methods.
919 * Instead, this method returns a new instance with the value of
920 * month of year changed.
921 *
922 * @param monthOfYear the month of year to set
923 * @return a copy of this object with the field set
924 * @throws IllegalArgumentException if the value is invalid
925 * @since 1.3
926 */
927 public DateMidnight withMonthOfYear(int monthOfYear) {
928 return withMillis(getChronology().monthOfYear().set(getMillis(), monthOfYear));
929 }
930
931 /**
932 * Returns a copy of this date with the week of weekyear field updated.
933 * <p>
934 * DateMidnight is immutable, so there are no set methods.
935 * Instead, this method returns a new instance with the value of
936 * week of weekyear changed.
937 *
938 * @param weekOfWeekyear the week of weekyear to set
939 * @return a copy of this object with the field set
940 * @throws IllegalArgumentException if the value is invalid
941 * @since 1.3
942 */
943 public DateMidnight withWeekOfWeekyear(int weekOfWeekyear) {
944 return withMillis(getChronology().weekOfWeekyear().set(getMillis(), weekOfWeekyear));
945 }
946
947 /**
948 * Returns a copy of this date with the day of year field updated.
949 * <p>
950 * DateMidnight is immutable, so there are no set methods.
951 * Instead, this method returns a new instance with the value of
952 * day of year changed.
953 *
954 * @param dayOfYear the day of year to set
955 * @return a copy of this object with the field set
956 * @throws IllegalArgumentException if the value is invalid
957 * @since 1.3
958 */
959 public DateMidnight withDayOfYear(int dayOfYear) {
960 return withMillis(getChronology().dayOfYear().set(getMillis(), dayOfYear));
961 }
962
963 /**
964 * Returns a copy of this date with the day of month field updated.
965 * <p>
966 * DateMidnight is immutable, so there are no set methods.
967 * Instead, this method returns a new instance with the value of
968 * day of month changed.
969 *
970 * @param dayOfMonth the day of month to set
971 * @return a copy of this object with the field set
972 * @throws IllegalArgumentException if the value is invalid
973 * @since 1.3
974 */
975 public DateMidnight withDayOfMonth(int dayOfMonth) {
976 return withMillis(getChronology().dayOfMonth().set(getMillis(), dayOfMonth));
977 }
978
979 /**
980 * Returns a copy of this date with the day of week field updated.
981 * <p>
982 * DateMidnight is immutable, so there are no set methods.
983 * Instead, this method returns a new instance with the value of
984 * day of week changed.
985 *
986 * @param dayOfWeek the day of week to set
987 * @return a copy of this object with the field set
988 * @throws IllegalArgumentException if the value is invalid
989 * @since 1.3
990 */
991 public DateMidnight withDayOfWeek(int dayOfWeek) {
992 return withMillis(getChronology().dayOfWeek().set(getMillis(), dayOfWeek));
993 }
994
995 // Date properties
996 //-----------------------------------------------------------------------
997 /**
998 * Get the era property which provides access to advanced functionality.
999 *
1000 * @return the era property
1001 */
1002 public Property era() {
1003 return new Property(this, getChronology().era());
1004 }
1005
1006 /**
1007 * Get the century of era property which provides access to advanced functionality.
1008 *
1009 * @return the year of era property
1010 */
1011 public Property centuryOfEra() {
1012 return new Property(this, getChronology().centuryOfEra());
1013 }
1014
1015 /**
1016 * Get the year of century property which provides access to advanced functionality.
1017 *
1018 * @return the year of era property
1019 */
1020 public Property yearOfCentury() {
1021 return new Property(this, getChronology().yearOfCentury());
1022 }
1023
1024 /**
1025 * Get the year of era property which provides access to advanced functionality.
1026 *
1027 * @return the year of era property
1028 */
1029 public Property yearOfEra() {
1030 return new Property(this, getChronology().yearOfEra());
1031 }
1032
1033 /**
1034 * Get the year property which provides access to advanced functionality.
1035 *
1036 * @return the year property
1037 */
1038 public Property year() {
1039 return new Property(this, getChronology().year());
1040 }
1041
1042 /**
1043 * Get the year of a week based year property which provides access to advanced functionality.
1044 *
1045 * @return the year of a week based year property
1046 */
1047 public Property weekyear() {
1048 return new Property(this, getChronology().weekyear());
1049 }
1050
1051 /**
1052 * Get the month of year property which provides access to advanced functionality.
1053 *
1054 * @return the month of year property
1055 */
1056 public Property monthOfYear() {
1057 return new Property(this, getChronology().monthOfYear());
1058 }
1059
1060 /**
1061 * Get the week of a week based year property which provides access to advanced functionality.
1062 *
1063 * @return the week of a week based year property
1064 */
1065 public Property weekOfWeekyear() {
1066 return new Property(this, getChronology().weekOfWeekyear());
1067 }
1068
1069 /**
1070 * Get the day of year property which provides access to advanced functionality.
1071 *
1072 * @return the day of year property
1073 */
1074 public Property dayOfYear() {
1075 return new Property(this, getChronology().dayOfYear());
1076 }
1077
1078 /**
1079 * Get the day of month property which provides access to advanced functionality.
1080 *
1081 * @return the day of month property
1082 */
1083 public Property dayOfMonth() {
1084 return new Property(this, getChronology().dayOfMonth());
1085 }
1086
1087 /**
1088 * Get the day of week property which provides access to advanced functionality.
1089 *
1090 * @return the day of week property
1091 */
1092 public Property dayOfWeek() {
1093 return new Property(this, getChronology().dayOfWeek());
1094 }
1095
1096 //-----------------------------------------------------------------------
1097 /**
1098 * DateMidnight.Property binds a DateMidnight to a DateTimeField allowing powerful
1099 * datetime functionality to be easily accessed.
1100 * <p>
1101 * The simplest use of this class is as an alternative get method, here used to
1102 * get the year '1972' (as an int) and the month 'December' (as a String).
1103 * <pre>
1104 * DateMidnight dt = new DateMidnight(1972, 12, 3);
1105 * int year = dt.year().get();
1106 * String monthStr = dt.monthOfYear().getAsText();
1107 * </pre>
1108 * <p>
1109 * Methods are also provided that allow date modification. These return new instances
1110 * of DateMidnight - they do not modify the original. The example below yields two
1111 * independent immutable date objects 20 years apart.
1112 * <pre>
1113 * DateMidnight dt = new DateMidnight(1972, 12, 3);
1114 * DateMidnight dt20 = dt.year().addToCopy(20);
1115 * </pre>
1116 * Serious modification of dates (ie. more than just changing one or two fields)
1117 * should use the {@link org.joda.time.MutableDateTime MutableDateTime} class.
1118 * <p>
1119 * DateMidnight.Property itself is thread-safe and immutable.
1120 *
1121 * @author Stephen Colebourne
1122 * @author Brian S O'Neill
1123 * @since 1.0
1124 */
1125 public static final class Property extends AbstractReadableInstantFieldProperty {
1126
1127 /** Serialization lock */
1128 private static final long serialVersionUID = 257629620L;
1129
1130 /** The instant this property is working against */
1131 private DateMidnight iInstant;
1132 /** The field this property is working against */
1133 private DateTimeField iField;
1134
1135 /**
1136 * Constructor.
1137 *
1138 * @param instant the instant to set
1139 * @param field the field to use
1140 */
1141 Property(DateMidnight instant, DateTimeField field) {
1142 super();
1143 iInstant = instant;
1144 iField = field;
1145 }
1146
1147 /**
1148 * Writes the property in a safe serialization format.
1149 */
1150 private void writeObject(ObjectOutputStream oos) throws IOException {
1151 oos.writeObject(iInstant);
1152 oos.writeObject(iField.getType());
1153 }
1154
1155 /**
1156 * Reads the property from a safe serialization format.
1157 */
1158 private void readObject(ObjectInputStream oos) throws IOException, ClassNotFoundException {
1159 iInstant = (DateMidnight) oos.readObject();
1160 DateTimeFieldType type = (DateTimeFieldType) oos.readObject();
1161 iField = type.getField(iInstant.getChronology());
1162 }
1163
1164 //-----------------------------------------------------------------------
1165 /**
1166 * Gets the field being used.
1167 *
1168 * @return the field
1169 */
1170 public DateTimeField getField() {
1171 return iField;
1172 }
1173
1174 /**
1175 * Gets the milliseconds of the datetime that this property is linked to.
1176 *
1177 * @return the milliseconds
1178 */
1179 protected long getMillis() {
1180 return iInstant.getMillis();
1181 }
1182
1183 /**
1184 * Gets the chronology of the datetime that this property is linked to.
1185 *
1186 * @return the chronology
1187 * @since 1.4
1188 */
1189 protected Chronology getChronology() {
1190 return iInstant.getChronology();
1191 }
1192
1193 /**
1194 * Gets the datetime being used.
1195 *
1196 * @return the datetime
1197 */
1198 public DateMidnight getDateMidnight() {
1199 return iInstant;
1200 }
1201
1202 //-----------------------------------------------------------------------
1203 /**
1204 * Adds to this field in a copy of this DateMidnight.
1205 * <p>
1206 * The DateMidnight attached to this property is unchanged by this call.
1207 * This operation is faster than converting a DateMidnight to a MutableDateTime
1208 * and back again when setting one field. When setting multiple fields,
1209 * it is generally quicker to make the conversion to MutableDateTime.
1210 *
1211 * @param value the value to add to the field in the copy
1212 * @return a copy of the DateMidnight with the field value changed
1213 * @throws IllegalArgumentException if the value isn't valid
1214 */
1215 public DateMidnight addToCopy(int value) {
1216 return iInstant.withMillis(iField.add(iInstant.getMillis(), value));
1217 }
1218
1219 /**
1220 * Adds to this field in a copy of this DateMidnight.
1221 * <p>
1222 * The DateMidnight attached to this property is unchanged by this call.
1223 * This operation is faster than converting a DateMidnight to a MutableDateTime
1224 * and back again when setting one field. When setting multiple fields,
1225 * it is generally quicker to make the conversion to MutableDateTime.
1226 *
1227 * @param value the value to add to the field in the copy
1228 * @return a copy of the DateMidnight with the field value changed
1229 * @throws IllegalArgumentException if the value isn't valid
1230 */
1231 public DateMidnight addToCopy(long value) {
1232 return iInstant.withMillis(iField.add(iInstant.getMillis(), value));
1233 }
1234
1235 /**
1236 * Adds to this field, possibly wrapped, in a copy of this DateMidnight.
1237 * A wrapped operation only changes this field.
1238 * Thus 31st January addWrapField one day goes to the 1st January.
1239 * <p>
1240 * The DateMidnight attached to this property is unchanged by this call.
1241 * This operation is faster than converting a DateMidnight to a MutableDateTime
1242 * and back again when setting one field. When setting multiple fields,
1243 * it is generally quicker to make the conversion to MutableDateTime.
1244 *
1245 * @param value the value to add to the field in the copy
1246 * @return a copy of the DateMidnight with the field value changed
1247 * @throws IllegalArgumentException if the value isn't valid
1248 */
1249 public DateMidnight addWrapFieldToCopy(int value) {
1250 return iInstant.withMillis(iField.addWrapField(iInstant.getMillis(), value));
1251 }
1252
1253 //-----------------------------------------------------------------------
1254 /**
1255 * Sets this field in a copy of the DateMidnight.
1256 * <p>
1257 * The DateMidnight attached to this property is unchanged by this call.
1258 * This operation is faster than converting a DateMidnight to a MutableDateTime
1259 * and back again when setting one field. When setting multiple fields,
1260 * it is generally quicker to make the conversion to MutableDateTime.
1261 *
1262 * @param value the value to set the field in the copy to
1263 * @return a copy of the DateMidnight with the field value changed
1264 * @throws IllegalArgumentException if the value isn't valid
1265 */
1266 public DateMidnight setCopy(int value) {
1267 return iInstant.withMillis(iField.set(iInstant.getMillis(), value));
1268 }
1269
1270 /**
1271 * Sets this field in a copy of the DateMidnight to a parsed text value.
1272 * <p>
1273 * The DateMidnight attached to this property is unchanged by this call.
1274 * This operation is faster than converting a DateMidnight to a MutableDateTime
1275 * and back again when setting one field. When setting multiple fields,
1276 * it is generally quicker to make the conversion to MutableDateTime.
1277 *
1278 * @param text the text value to set
1279 * @param locale optional locale to use for selecting a text symbol
1280 * @return a copy of the DateMidnight with the field value changed
1281 * @throws IllegalArgumentException if the text value isn't valid
1282 */
1283 public DateMidnight setCopy(String text, Locale locale) {
1284 return iInstant.withMillis(iField.set(iInstant.getMillis(), text, locale));
1285 }
1286
1287 /**
1288 * Sets this field in a copy of the DateMidnight to a parsed text value.
1289 * <p>
1290 * The DateMidnight attached to this property is unchanged by this call.
1291 * This operation is faster than converting a DateMidnight to a MutableDateTime
1292 * and back again when setting one field. When setting multiple fields,
1293 * it is generally quicker to make the conversion to MutableDateTime.
1294 *
1295 * @param text the text value to set
1296 * @return a copy of the DateMidnight with the field value changed
1297 * @throws IllegalArgumentException if the text value isn't valid
1298 */
1299 public DateMidnight setCopy(String text) {
1300 return setCopy(text, null);
1301 }
1302
1303 //-----------------------------------------------------------------------
1304 /**
1305 * Returns a new DateMidnight with this field set to the maximum value
1306 * for this field.
1307 * <p>
1308 * This operation is useful for obtaining a DateTime on the last day
1309 * of the month, as month lengths vary.
1310 * <pre>
1311 * DateMidnight lastDayOfMonth = dt.dayOfMonth().withMaximumValue();
1312 * </pre>
1313 * <p>
1314 * The DateMidnight attached to this property is unchanged by this call.
1315 *
1316 * @return a copy of the DateMidnight with this field set to its maximum
1317 * @since 1.2
1318 */
1319 public DateMidnight withMaximumValue() {
1320 return setCopy(getMaximumValue());
1321 }
1322
1323 /**
1324 * Returns a new DateMidnight with this field set to the minimum value
1325 * for this field.
1326 * <p>
1327 * The DateMidnight attached to this property is unchanged by this call.
1328 *
1329 * @return a copy of the DateMidnight with this field set to its minimum
1330 * @since 1.2
1331 */
1332 public DateMidnight withMinimumValue() {
1333 return setCopy(getMinimumValue());
1334 }
1335
1336 //-----------------------------------------------------------------------
1337 /**
1338 * Rounds to the lowest whole unit of this field on a copy of this DateMidnight.
1339 *
1340 * @return a copy of the DateMidnight with the field value changed
1341 */
1342 public DateMidnight roundFloorCopy() {
1343 return iInstant.withMillis(iField.roundFloor(iInstant.getMillis()));
1344 }
1345
1346 /**
1347 * Rounds to the highest whole unit of this field on a copy of this DateMidnight.
1348 *
1349 * @return a copy of the DateMidnight with the field value changed
1350 */
1351 public DateMidnight roundCeilingCopy() {
1352 return iInstant.withMillis(iField.roundCeiling(iInstant.getMillis()));
1353 }
1354
1355 /**
1356 * Rounds to the nearest whole unit of this field on a copy of this DateMidnight,
1357 * favoring the floor if halfway.
1358 *
1359 * @return a copy of the DateMidnight with the field value changed
1360 */
1361 public DateMidnight roundHalfFloorCopy() {
1362 return iInstant.withMillis(iField.roundHalfFloor(iInstant.getMillis()));
1363 }
1364
1365 /**
1366 * Rounds to the nearest whole unit of this field on a copy of this DateMidnight,
1367 * favoring the ceiling if halfway.
1368 *
1369 * @return a copy of the DateMidnight with the field value changed
1370 */
1371 public DateMidnight roundHalfCeilingCopy() {
1372 return iInstant.withMillis(iField.roundHalfCeiling(iInstant.getMillis()));
1373 }
1374
1375 /**
1376 * Rounds to the nearest whole unit of this field on a copy of this DateMidnight.
1377 * If halfway, the ceiling is favored over the floor only if it makes this field's value even.
1378 *
1379 * @return a copy of the DateMidnight with the field value changed
1380 */
1381 public DateMidnight roundHalfEvenCopy() {
1382 return iInstant.withMillis(iField.roundHalfEven(iInstant.getMillis()));
1383 }
1384
1385 }
1386 }