Subversion Repository Public Repository

litesoft

Diff Revisions 850 vs 851 for /trunk/Java/core/Anywhere/src/org/litesoft/core/simpletypes/temporal/SimpleDate.java

Diff revisions: vs.
  @@ -5,6 +5,8 @@
5 5
6 6 import org.litesoft.core.*;
7 7 import org.litesoft.core.simpletypes.temporal.nonpublic.*;
8 + import org.litesoft.core.typeutils.*;
9 + import org.litesoft.core.typeutils.gregorian.*;
8 10
9 11 /**
10 12 * A Simple date that acts as a proxy for a java.util.Date (burying the deprecated method use) providing
  @@ -21,387 +23,298 @@
21 23 * dd produces 2 digit day of month numbers.
22 24 * </pre>
23 25 */
24 - public final class SimpleDate extends DateFormatControl<SimpleDate> implements YMDaccessor,
25 - TemporalSimpleType,
26 - SQLdateable
26 + public final class SimpleDate extends CalendarSupport<SimpleDate> implements YearMonthDayAccessor,
27 + TemporalSimpleType,
28 + CalendarConstants,
29 + SQLdateable
27 30 {
28 - private static final long serialVersionUID = 1L;
31 + private static final long serialVersionUID = 2L;
29 32
30 - private int mYear, mMonth, mDay;
33 + private final DateFormat mFormat;
34 + private final int mYear, mMonth, mDay;
31 35
32 - /**
33 - * @deprecated - for Serialization
34 - */
35 - @SuppressWarnings("deprecation")
36 + @SuppressWarnings({"deprecation", "UnusedDeclaration"}) @Deprecated /** for Serialization */
36 37 protected SimpleDate()
37 38 {
39 + this( 0, 0, 0, null );
38 40 }
39 41
40 - private SimpleDate( String pFormat )
42 + public static SimpleDate today()
41 43 {
42 - super( pFormat );
44 + return new SimpleDate( new Date() );
43 45 }
44 46
45 - public SimpleDate( String pFormat, int pYear )
46 - throws IllegalArgumentException
47 + private SimpleDate( int pYear, int pMonth, int pDay, DateFormat pFormat )
47 48 {
48 - this( pFormat );
49 - noMonthProvided();
50 - noDayProvided();
51 - setYear( pYear );
49 + mFormat = pFormat;
50 + mYear = pYear;
51 + mMonth = pMonth;
52 + mDay = pDay;
52 53 }
53 54
54 - public SimpleDate( String pFormat, int pYear, int pMonth )
55 + private SimpleDate( YearMonthDayAccessor pDate, DateFormat pFormat )
55 56 throws IllegalArgumentException
56 57 {
57 - this( pFormat );
58 - noDayProvided();
59 - setYearAndMonth( pYear, pMonth );
58 + mFormat = pFormat;
59 + mYear = pDate.getYear();
60 + mMonth = isValidToMonth() ? mFormat.monthProvided( mYear, pDate.getMonth() ) : 0;
61 + mDay = isValidToDay() ? mFormat.dayProvided( mYear, mMonth, pDate.getDay() ) : 0;
60 62 }
61 63
62 - public SimpleDate( String pFormat, int pYear, int pMonth, int pDay )
64 + public SimpleDate( DateFormat pFormat, int pYear )
63 65 throws IllegalArgumentException
64 66 {
65 - this( pFormat );
66 - setDate( pYear, pMonth, pDay );
67 + this( pYear, 0, 0, YearFormatAccessor.deNull( pFormat ) );
68 + mFormat.noMonthProvided();
67 69 }
68 70
69 - public SimpleDate( int pYear, int pMonth, int pDay )
71 + public SimpleDate( int pYear )
70 72 throws IllegalArgumentException
71 73 {
72 - this( DEFAULT_DATE_FORMAT, pYear, pMonth, pDay );
74 + this( null, pYear );
73 75 }
74 76
75 - public SimpleDate( String pFormat, Date pDate )
77 + public SimpleDate( DateFormat pFormat, int pYear, int pMonth )
76 78 throws IllegalArgumentException
77 79 {
78 - this( pFormat );
79 - setDate( pDate );
80 + this( pYear, pMonth, 0, YearMonthFormatAccessor.deNull( pFormat ) );
81 + mFormat.monthProvided( pYear, pMonth );
82 + mFormat.noDayProvided();
80 83 }
81 84
82 - public SimpleDate( Date pDate )
85 + public SimpleDate( int pYear, int pMonth )
83 86 throws IllegalArgumentException
84 87 {
85 - this( DEFAULT_DATE_FORMAT, pDate );
88 + this( null, pYear, pMonth );
86 89 }
87 90
88 - public SimpleDate( String pFormat, SimpleDate pDate )
91 + public SimpleDate( DateFormat pFormat, int pYear, int pMonth, int pDay )
89 92 throws IllegalArgumentException
90 93 {
91 - this( pFormat );
92 - setDate( pDate );
94 + this( pYear, pMonth, pDay, YearMonthDayFormatAccessor.deNull( pFormat ) );
95 + mFormat.dayProvided( pYear, pMonth, pDay );
93 96 }
94 97
95 - public SimpleDate( String pFormat, UtilDateAdaptor pDate )
98 + public SimpleDate( int pYear, int pMonth, int pDay )
96 99 throws IllegalArgumentException
97 100 {
98 - this( pFormat );
99 - setDate( pDate );
101 + this( null, pYear, pMonth, pDay );
100 102 }
101 103
102 - public SimpleDate copy()
103 - {
104 - return new SimpleDate( getFormat(), this );
105 - }
106 -
107 - @Override
108 - public boolean isValidToMonth()
104 + public SimpleDate( DateFormat pFormat, UtilDateAdaptor pDate )
105 + throws IllegalArgumentException
109 106 {
110 - return getDateRes().isValidToMonth();
107 + this( pDate, YearMonthDayFormatAccessor.deNull( pFormat ) );
111 108 }
112 109
113 - @Override
114 - public boolean isValidToDay()
110 + public SimpleDate( UtilDateAdaptor pDate )
111 + throws IllegalArgumentException
115 112 {
116 - return getDateRes().isValidToDay();
113 + this( null, pDate );
117 114 }
118 115
119 - @Override
120 - public int getYear()
116 + public SimpleDate( DateFormat pFormat, Date pDate )
117 + throws IllegalArgumentException
121 118 {
122 - return mYear;
119 + this( pFormat, new UtilDateAdaptor( pDate ) );
123 120 }
124 121
125 - /**
126 - * @return 0 if not ValidToMonth, otherwise 1-12
127 - */
128 - @Override
129 - public int getMonth()
122 + public SimpleDate( Date pDate )
123 + throws IllegalArgumentException
130 124 {
131 - return mMonth;
125 + this( null, pDate );
132 126 }
133 127
134 128 /**
135 - * @return 0 if not ValidToDay, otherwise 1-31
129 + * Return a SimpleDate (based on this) with the updated format (Resolution reduction supported)
130 + *
131 + * @param pFormat !null
132 + *
133 + * @throws IllegalArgumentException if <code>pFormat</code> is null, or the Resolution is attempting to be increased
136 134 */
137 - @Override
138 - public int getDay()
139 - {
140 - return mDay;
141 - }
142 -
143 - public UtilDateAdaptor getUtilDateAdaptor()
144 - {
145 - return new UtilDateAdaptor( mYear, mMonth, mDay );
146 - }
147 -
148 - public Date getDate()
149 - {
150 - return getUtilDateAdaptor().getDate();
151 - }
152 -
153 - public void setDate( UtilDateAdaptor pDate )
135 + public SimpleDate changeFormat( DateFormat pFormat )
136 + throws IllegalArgumentException
154 137 {
155 - if ( pDate == null )
138 + Objects.assertNotNull( "DateFormat", pFormat );
139 + if ( mFormat.equals( pFormat ) )
156 140 {
157 - throw new IllegalArgumentException( "Date was null" );
141 + return this;
158 142 }
159 - setDateToResolution( pDate, getDateRes() );
160 - }
161 -
162 - public void setDate( Date pDate )
163 - {
164 - if ( pDate == null )
143 + if ( mFormat.getDateRes().getIndex() < pFormat.getDateRes().getIndex() )
165 144 {
166 - throw new IllegalArgumentException( "Date was null" );
145 + throw new IllegalArgumentException( "May not add Resolution" );
167 146 }
168 - setDateToResolution( new UtilDateAdaptor( pDate, 0 ), DateRes.ToDAY );
147 + return new SimpleDate( pFormat, toUtilDateAdaptor() );
169 148 }
170 149
171 - public void setDate( SimpleDate pDate )
150 + /**
151 + * Return a SimpleDate with the day set to the 1st day of the current month, this will always set the 'Day' field to 1.
152 + *
153 + * @throws IllegalArgumentException if the Resolution does not extend to Day.
154 + */
155 + public SimpleDate forceFirstOfMonth()
172 156 throws IllegalArgumentException
173 157 {
174 - if ( pDate == null )
175 - {
176 - throw new IllegalArgumentException( "Date was null" );
177 - }
178 - setDateToResolution( pDate, pDate.getDateRes() );
158 + return minusDays( mDay - 1 );
179 159 }
180 160
181 - private void setDateToResolution( YMDaccessor pDate, DateRes pDateRes )
161 + /**
162 + * Return a SimpleDate with the day set to the last day of the current month (either 28, 29, 30, or 31).
163 + *
164 + * @throws IllegalArgumentException if the Resolution does not extend to Day.
165 + */
166 + public SimpleDate forceEndOfMonth()
182 167 throws IllegalArgumentException
183 168 {
184 - int dYear = pDate.getYear();
185 - int dMonth = mMonth;
186 - int dDay = mDay;
187 - switch ( pDateRes.getIndex() )
188 - {
189 - case DateRes.DAYindex:
190 - dDay = pDate.getDay();
191 - // Fall thru
192 - case DateRes.MONTHindex:
193 - dMonth = pDate.getMonth();
194 - // Fall thru
195 - default:
196 - break;
197 - }
198 - if ( isValidToDay() )
199 - {
200 - setDate( dYear, dMonth, dDay );
201 - }
202 - else if ( isValidToMonth() )
203 - {
204 - setYearAndMonth( dYear, dMonth );
205 - }
206 - else
207 - {
208 - setYear( dYear );
209 - }
169 + return addDays( Month.daysIn( getYear(), getMonth() ) - mDay );
210 170 }
211 171
212 - public void setDate( int pYear, int pMonth, int pDay )
213 - throws IllegalArgumentException
172 + /**
173 + * Return a SimpleDate who's <code>getWeekDay()</code> will be <code>pWeekday</code>, where the resulting date will <b>NOT</b> be in the Future relative to
174 + * <code>this</code>.
175 + *
176 + * @param pWeekDay !null
177 + */
178 + public SimpleDate notFuture( WeekDay pWeekDay )
214 179 {
215 - monthProvided( pMonth );
216 - dayProvided( pDay );
217 - validate( pYear, pMonth, pDay );
218 - mYear = pYear;
219 - mMonth = pMonth;
220 - mDay = pDay;
180 + return minusDays( getWeekDay().deltaTillBackward( pWeekDay ) );
221 181 }
222 182
223 - public void setYearAndMonth( int pYear, int pMonth )
224 - throws IllegalArgumentException
183 + /**
184 + * Return a SimpleDate with the Year set to the parameter, this is accomplished by utilizing addYears or minusYears as is appropriate (with their day
185 + * adjusting logic).
186 + */
187 + public SimpleDate year( int pYear )
225 188 {
226 - monthProvided( pMonth );
227 - validate( pYear, pMonth, mDay );
228 - mYear = pYear;
229 - mMonth = pMonth;
189 + return (mYear == pYear) ? this : (pYear > mYear) ? addYears( pYear - mYear ) : minusYears( mYear - pYear );
230 190 }
231 191
232 - public void setMonthAndDay( int pMonth, int pDay )
233 - throws IllegalArgumentException
192 + /**
193 + * if after add pYears if was LeapDay and can not be LeapDay will be 1Mar.
194 + */
195 + public SimpleDate addYears( int pYears )
234 196 {
235 - monthProvided( pMonth );
236 - dayProvided( pDay );
237 - validate( mYear, pMonth, pDay );
238 - mMonth = pMonth;
239 - mDay = pDay;
197 + return LLsetYear( mYear + pYears, true );
240 198 }
241 199
242 - public void setYear( int pYear )
243 - throws IllegalArgumentException
200 + /**
201 + * if after minus pYears if was LeapDay and can not be LeapDay will be 28Feb.
202 + */
203 + public SimpleDate minusYears( int pYears )
244 204 {
245 - validate( pYear, mMonth, mDay );
246 - mYear = pYear;
205 + return LLsetYear( mYear - pYears, false );
247 206 }
248 207
249 - public void setMonth( int pMonth )
208 + /**
209 + * Return a SimpleDate with the Month set to the parameter, this is accomplished by utilizing addMonths or minusMonths as is appropriate (with their day
210 + * adjusting logic).
211 + *
212 + * @throws IllegalArgumentException if month is not between 1 & 12 inclusive, OR if the Resolution does not extend to Month.
213 + */
214 + public SimpleDate month( int pMonth )
250 215 throws IllegalArgumentException
251 216 {
252 - monthProvided( pMonth );
253 - validate( mYear, pMonth, mDay );
254 - mMonth = pMonth;
217 + LLcheckMonth( mYear, pMonth );
218 + return (mMonth == pMonth) ? this : (pMonth > mMonth) ? addMonths( pMonth - mMonth ) : minusMonths( mMonth - pMonth );
255 219 }
256 220
257 - public void setDay( int pDay )
221 + /**
222 + * if after add pMonth there are insufficent days in the new month, the date will be set to the 1st of the next month.
223 + *
224 + * @throws IllegalArgumentException if the Resolution does not extend to Month.
225 + */
226 + public SimpleDate addMonths( int pMonths )
258 227 throws IllegalArgumentException
259 228 {
260 - dayProvided( pDay );
261 - validate( mYear, mMonth, pDay );
262 - mDay = pDay;
229 + return LLsetMonth( mMonth + pMonths, true );
263 230 }
264 231
265 232 /**
266 - * if after add pYears if was LeapDay and can not be LeapDay will be 1Mar.
233 + * if after minus pMonth there are insufficent days in the new month, the date will be set to the last day of the target month
234 + *
235 + * @throws IllegalArgumentException if the Resolution does not extend to Month.
267 236 */
268 - public void addYears( int pYears )
237 + public SimpleDate minusMonths( int pMonths )
238 + throws IllegalArgumentException
269 239 {
270 - if ( pYears != 0 )
271 - {
272 - LLadjustYears( mYear + pYears, true );
273 - }
240 + return LLsetMonth( mMonth - pMonths, false );
274 241 }
275 242
276 243 /**
277 - * if after minus pYears if was LeapDay and can not be LeapDay will be 28Feb.
244 + * Return a SimpleDate with the 'Day' field set to the parameter.
245 + *
246 + * @param pDay Must be between 1 and the max days in the <code>this</code>'s month
247 + *
248 + * @throws IllegalArgumentException if the <code>pDay</code> is invalid, OR the Resolution does not extend to Day.
278 249 */
279 - public void minusYears( int pYears )
280 - {
281 - if ( pYears != 0 )
282 - {
283 - LLadjustYears( mYear - pYears, false );
284 - }
285 - }
286 -
287 - private void LLadjustYears( int pNewYear, boolean pAdjustForward )
250 + public SimpleDate day( int pDay )
251 + throws IllegalArgumentException
288 252 {
289 - mYear = pNewYear;
290 - LLadjust( pAdjustForward );
253 + mFormat.validateDayAdjustable();
254 + LLcheckDay( mYear, mMonth, pDay );
255 + return new SimpleDate( mYear, mMonth, pDay, mFormat );
291 256 }
292 257
293 258 /**
294 - * if after add pMonth there are insufficent days in the new month, the date will be set to the 1st of the next month.
259 + * Return a SimpleDate adjusted forward by the <code>pDays</code> indicated.
260 + *
261 + * @throws IllegalArgumentException if the Resolution does not extend to Day.
295 262 */
296 - public void addMonths( int pMonths )
263 + public SimpleDate addDays( int pDays )
297 264 throws IllegalArgumentException
298 265 {
299 - validateMonthAdjustable();
300 - if ( pMonths != 0 )
301 - {
302 - LLadjustMonths( mMonth + pMonths, true );
303 - }
266 + return LLsetDay( mDay + pDays );
304 267 }
305 268
306 269 /**
307 - * if after minus pMonth there are insufficent days in the new month, the date will be set to the last day of the target month
270 + * Return a SimpleDate adjusted backward by the <code>pDays</code> indicated.
271 + *
272 + * @throws IllegalArgumentException if the Resolution does not extend to Day.
308 273 */
309 - public void minusMonths( int pMonths )
274 + public SimpleDate minusDays( int pDays )
310 275 throws IllegalArgumentException
311 276 {
312 - validateMonthAdjustable();
313 - if ( pMonths != 0 )
314 - {
315 - LLadjustMonths( mMonth - pMonths, false );
316 - }
277 + return LLsetDay( mDay - pDays );
317 278 }
318 279
319 - private void LLadjustMonths( int pNewMonth, boolean pAdjustForward )
280 + public boolean isValidToMonth()
320 281 {
321 - mMonth = pNewMonth;
322 - while ( mMonth > 12 )
323 - {
324 - mYear++;
325 - mMonth -= 12;
326 - }
327 - while ( mMonth < 1 )
328 - {
329 - mYear--;
330 - mMonth += 12;
331 - }
332 - LLadjust( pAdjustForward );
282 + return mFormat.getDateRes().isValidToMonth();
333 283 }
334 284
335 - private void LLadjust( boolean pAdjustForward )
285 + public boolean isValidToDay()
336 286 {
337 - if ( isValidToDay() ) // if Not, then any year works with any month
338 - {
339 - int maxDaysInMonth = daysInMonth( mYear, mMonth );
340 - if ( maxDaysInMonth < mDay )
341 - {
342 - mDay = maxDaysInMonth;
343 - if ( pAdjustForward )
344 - {
345 - LLaddDays( 1 );
346 - }
347 - }
348 - }
287 + return mFormat.getDateRes().isValidToDay();
349 288 }
350 289
351 - public void addDays( int pDays )
352 - throws IllegalArgumentException
290 + @Override
291 + public int getYear()
353 292 {
354 - validateDayAdjustable();
355 - if ( pDays < 0 )
356 - {
357 - LLminusDays( -pDays );
358 - }
359 - else if ( pDays > 0 )
360 - {
361 - LLaddDays( pDays );
362 - }
293 + return mYear;
363 294 }
364 295
365 - public void minusDays( int pDays )
366 - throws IllegalArgumentException
296 + /**
297 + * @return 0 if not ValidToMonth, otherwise 1-12
298 + */
299 + @Override
300 + public int getMonth()
367 301 {
368 - validateDayAdjustable();
369 - if ( pDays < 0 )
370 - {
371 - LLaddDays( -pDays );
372 - }
373 - else if ( pDays > 0 )
374 - {
375 - LLminusDays( pDays );
376 - }
302 + return mMonth;
377 303 }
378 304
379 - private void LLaddDays( int pDays )
305 + /**
306 + * @return 0 if not ValidToDay, otherwise 1-31
307 + */
308 + @Override
309 + public int getDay()
380 310 {
381 - mDay += pDays;
382 - for ( int maxDaysInMonth; (maxDaysInMonth = daysInMonth( mYear, mMonth )) < mDay; )
383 - {
384 - mDay -= maxDaysInMonth;
385 - if ( ++mMonth > 12 )
386 - {
387 - mMonth = 1;
388 - mYear++;
389 - }
390 - }
311 + return mDay;
391 312 }
392 313
393 - private void LLminusDays( int pDays )
314 + public WeekDay getWeekDay()
394 315 {
395 - mDay -= pDays;
396 - while ( mDay < 1 )
397 - {
398 - if ( --mMonth < 1 )
399 - {
400 - mMonth = 12;
401 - mYear--;
402 - }
403 - mDay += daysInMonth( mYear, mMonth );
404 - }
316 + mFormat.validateValidToDay( "getWeekDay" );
317 + return WeekDay.valueOf( UtilDateAdaptor.dayOfWeek( toUtilDateAdaptor().getWallDate() ) );
405 318 }
406 319
407 320 /**
  @@ -457,21 +370,6 @@
457 370 return LLbeforeOrAfter( pThem, "after", 1 );
458 371 }
459 372
460 - private boolean LLbeforeOrAfter( SimpleDate pThem, String pWhat, int pCompareRetValue )
461 - throws IllegalArgumentException
462 - {
463 - undefinedResultIfNull( pWhat, pThem );
464 - if ( (this.mYear == pThem.mYear) && this.isValidToMonth() && pThem.isValidToMonth() )
465 - {
466 - if ( (this.mMonth == pThem.mMonth) && this.isValidToDay() && pThem.isValidToDay() )
467 - {
468 - return pCompareRetValue == compare( this.mDay, pThem.mDay );
469 - }
470 - return pCompareRetValue == compare( this.mMonth, pThem.mMonth );
471 - }
472 - return pCompareRetValue == compare( this.mYear, pThem.mYear );
473 - }
474 -
475 373 /**
476 374 * Number of days from this to pThem (could be negative).
477 375 * <p/>
  @@ -485,7 +383,7 @@
485 383 throws IllegalArgumentException
486 384 {
487 385 undefinedResultIfNull( "daysTill", pThem );
488 - return daysTill( new SimpleDate( getFormat(), pThem ) );
386 + return daysTill( new SimpleDate( mFormat, pThem ) );
489 387 }
490 388
491 389 /**
  @@ -501,7 +399,7 @@
501 399 throws IllegalArgumentException
502 400 {
503 401 undefinedResultIfNull( "after", pThem );
504 - return after( new SimpleDate( getFormat(), pThem ) );
402 + return after( new SimpleDate( mFormat, pThem ) );
505 403 }
506 404
507 405 /**
  @@ -517,7 +415,7 @@
517 415 throws IllegalArgumentException
518 416 {
519 417 undefinedResultIfNull( "before", pThem );
520 - return before( new SimpleDate( getFormat(), pThem ) );
418 + return before( new SimpleDate( mFormat, pThem ) );
521 419 }
522 420
523 421 @Override
  @@ -529,7 +427,7 @@
529 427
530 428 public boolean equals( Date pDate )
531 429 {
532 - return (pDate != null) && equals( new SimpleDate( getFormat(), pDate ) );
430 + return (pDate != null) && equals( new SimpleDate( mFormat, pDate ) );
533 431 }
534 432
535 433 public boolean equals( SimpleDate them )
  @@ -558,48 +456,58 @@
558 456 compare( this.mDay, them.mDay ) );
559 457 }
560 458
561 - public String toString( SimpleDate pDate )
459 + public UtilDateAdaptor toUtilDateAdaptor()
562 460 {
563 - return (pDate != null) ? pDate.toString() : null;
461 + if ( isValidToDay() )
462 + {
463 + return new UtilDateAdaptor( mYear, mMonth, mDay );
464 + }
465 + if ( isValidToMonth() )
466 + {
467 + return new UtilDateAdaptor( mYear, mMonth, 1 );
468 + }
469 + return new UtilDateAdaptor( mYear, 1, 1 );
470 + }
471 +
472 + public Date toUtilDate()
473 + {
474 + return toUtilDateAdaptor().getWallDate();
564 475 }
565 476
566 477 @Override
567 478 public String toString()
568 479 {
569 - StringBuilder sb = new StringBuilder();
570 - Chunk[] chunks = getToStringChunks( this );
571 - for ( Chunk chunk : chunks )
572 - {
573 - sb.append( chunk );
574 - }
575 - return sb.toString();
480 + return mFormat.format( this );
576 481 }
577 482
578 - public String toYMD()
483 + public static String toString( SimpleDate pDate )
579 484 {
580 - return toYMD( this );
485 + return (pDate != null) ? pDate.toString() : null;
581 486 }
582 487
583 - public static String toYMD( SimpleDate pFromYMD )
488 + public String toYMD()
584 489 {
585 - if ( pFromYMD == null )
586 - {
587 - return null;
588 - }
589 490 StringBuilder sb = new StringBuilder();
590 - sb.append( pFromYMD.getYear() );
591 - if ( pFromYMD.isValidToMonth() )
491 + sb.append( getYear() );
492 + if ( isValidToMonth() )
592 493 {
593 - sb.append( '/' ).append( new MM_Chunk( pFromYMD ) );
594 - if ( pFromYMD.isValidToDay() )
494 + sb.append( '/' );
495 + MM_Chunk.appendTo( sb, this );
496 + if ( isValidToDay() )
595 497 {
596 - sb.append( '/' ).append( new dd_Chunk( pFromYMD ) );
498 + sb.append( '/' );
499 + dd_Chunk.appendTo( sb, this );
597 500 }
598 501 }
599 502 return sb.toString();
600 503 }
601 504
602 - public static SimpleDate fromYMD( String pFormat, String pToYMD )
505 + public static String toYMD( SimpleDate pFromYMD )
506 + {
507 + return (pFromYMD != null) ? pFromYMD.toYMD() : null;
508 + }
509 +
510 + public static SimpleDate fromYMD( DateFormat pFormat, String pToYMD )
603 511 throws IllegalArgumentException
604 512 {
605 513 if ( pToYMD == null )
  @@ -626,18 +534,71 @@
626 534 }
627 535 }
628 536
537 + @Override
538 + public java.sql.Date toSQLvalue()
539 + {
540 + return new java.sql.Date( toUtilDate().getTime() );
541 + }
542 +
543 + // vvvvvvvvvvvvvvvvvv Support methods vvvvvvvvvvvvvvvvv
544 +
545 + private void validateValidToDay( String pWhat, SimpleDate pThem )
546 + throws IllegalArgumentException
547 + {
548 + mFormat.validateValidToDay( pWhat );
549 + undefinedResultIfNull( pWhat, pThem );
550 + if ( !pThem.isValidToDay() )
551 + {
552 + throw new IllegalArgumentException( "Parameter to " + pWhat + " does NOT have Day resolution" );
553 + }
554 + }
555 +
556 + private SimpleDate LLsetYear( int pNewYear, boolean pAdjustForward )
557 + {
558 + return (mYear == pNewYear) ? this : new Mutable( this ).setYear( pNewYear, pAdjustForward ).toSimpleDate();
559 + }
560 +
561 + private SimpleDate LLsetMonth( int pNewMonth, boolean pAdjustForward )
562 + throws IllegalArgumentException
563 + {
564 + mFormat.validateMonthAdjustable();
565 + return (mMonth == pNewMonth) ? this : new Mutable( this ).setMonth( pNewMonth, pAdjustForward ).toSimpleDate();
566 + }
567 +
568 + private SimpleDate LLsetDay( int pDay )
569 + throws IllegalArgumentException
570 + {
571 + mFormat.validateDayAdjustable();
572 + return (mDay == pDay) ? this : new Mutable( this ).setDay( pDay ).toSimpleDate();
573 + }
574 +
575 + private boolean LLbeforeOrAfter( SimpleDate pThem, String pWhat, int pCompareRetValue )
576 + throws IllegalArgumentException
577 + {
578 + undefinedResultIfNull( pWhat, pThem );
579 + if ( (this.mYear == pThem.mYear) && this.isValidToMonth() && pThem.isValidToMonth() )
580 + {
581 + if ( (this.mMonth == pThem.mMonth) && this.isValidToDay() && pThem.isValidToDay() )
582 + {
583 + return pCompareRetValue == compare( this.mDay, pThem.mDay );
584 + }
585 + return pCompareRetValue == compare( this.mMonth, pThem.mMonth );
586 + }
587 + return pCompareRetValue == compare( this.mYear, pThem.mYear );
588 + }
589 +
629 590 private static class DaysDiff
630 591 {
631 592 private int mYear, mMonth, mDay, mDiff = 0;
632 593
633 - public DaysDiff( YMDaccessor pYMDaccessor )
594 + public DaysDiff( YearMonthDayAccessor pYMDaccessor )
634 595 {
635 596 mYear = pYMDaccessor.getYear();
636 597 mMonth = pYMDaccessor.getMonth();
637 598 mDay = pYMDaccessor.getDay();
638 599 }
639 600
640 - public int till( YMDaccessor pThem ) // !null and is in our future
601 + public int till( YearMonthDayAccessor pThem ) // !null and is in our future
641 602 {
642 603 if ( mYear != pThem.getYear() )
643 604 {
  @@ -650,7 +611,7 @@
650 611
651 612 for (; mYear < pThem.getYear(); mYear++ )
652 613 {
653 - mDiff += isLeapYear( mYear ) ? 366 : 365;
614 + mDiff += Year.isLeap( mYear ) ? 366 : 365;
654 615 }
655 616 }
656 617 while ( mMonth < pThem.getMonth() )
  @@ -662,7 +623,7 @@
662 623
663 624 private void advanceTo1stOfNextMonth()
664 625 {
665 - int zDaysInMonth = daysInMonth( mYear, mMonth );
626 + int zDaysInMonth = Month.daysIn( mYear, mMonth );
666 627 mDiff += zDaysInMonth - (mDay - 1);
667 628 mDay = 1;
668 629 if ( ++mMonth > 12 )
  @@ -673,41 +634,166 @@
673 634 }
674 635 }
675 636
676 - protected void validateMonthAdjustable()
677 - throws IllegalArgumentException
637 + private static class Mutable implements YearMonthDayAccessor
678 638 {
679 - if ( !isValidToMonth() )
639 + private DateFormat mDateFormat;
640 + private int mYear, mMonth, mDay;
641 +
642 + private Mutable( DateFormat pDateFormat, int pYear, int pMonth, int pDay )
680 643 {
681 - throw doesNotContain( DateRes.ToMONTH, ", but Month adjustment attempted" );
644 + mDateFormat = pDateFormat;
645 + mYear = pYear;
646 + mMonth = pMonth;
647 + mDay = pDay;
648 + normalizeMonthOfYear();
649 + normalizeDayOfMonth();
682 650 }
683 - }
684 651
685 - protected void validateDayAdjustable()
686 - throws IllegalArgumentException
687 - {
688 - if ( !isValidToDay() )
652 + private Mutable( SimpleDate pDate )
689 653 {
690 - throw doesNotContain( DateRes.ToDAY, ", but Day adjustment attempted" );
654 + this( pDate.mFormat, pDate.getYear(), pDate.getMonth(), pDate.getDay() );
691 655 }
692 - }
693 656
694 - private void validateValidToDay( String pWhat, SimpleDate pThem )
695 - throws IllegalArgumentException
696 - {
697 - if ( !isValidToDay() )
657 + @Override
658 + public int getYear()
698 659 {
699 - throw doesNotContain( DateRes.ToDAY, ", but " + pWhat + " attempted" );
660 + return mYear;
700 661 }
701 - undefinedResultIfNull( pWhat, pThem );
702 - if ( !pThem.isValidToDay() )
662 +
663 + public Mutable setYear( int pYear )
703 664 {
704 - throw new IllegalArgumentException( "Parameter to " + pWhat + " does NOT have Day resolution" );
665 + return setYear( pYear, (pYear > mYear) );
705 666 }
706 - }
707 667
708 - @Override
709 - public java.sql.Date toSQLvalue()
710 - {
711 - return new java.sql.Date( getDate().getTime() );
668 + public Mutable setYear( int pYear, boolean pAdjustForward )
669 + {
670 + mYear = pYear;
671 + return adjustDayOfMonthForMonthOrYearChange( pAdjustForward );
672 + }
673 +
674 + @Override
675 + public int getMonth()
676 + {
677 + return mMonth;
678 + }
679 +
680 + public Mutable setMonth( int pMonth )
681 + {
682 + return setMonth( pMonth, (pMonth > mMonth) );
683 + }
684 +
685 + public Mutable setMonth( int pMonth, boolean pAdjustForward )
686 + {
687 + mMonth = pMonth;
688 + return adjustDayOfMonthForMonthOrYearChange( pAdjustForward );
689 + }
690 +
691 + @Override
692 + public int getDay()
693 + {
694 + return mDay;
695 + }
696 +
697 + public Mutable setDay( int pDay )
698 + {
699 + mDay = pDay;
700 + return normalizeDayOfMonth();
701 + }
702 +
703 + private Mutable normalizeMonthOfYear()
704 + {
705 + while ( mMonth > 12 )
706 + {
707 + mYear++;
708 + mMonth -= 12;
709 + }
710 + while ( mMonth < 1 )
711 + {
712 + mYear--;
713 + mMonth += 12;
714 + }
715 + return this;
716 + }
717 +
718 + private Mutable normalizeDayOfMonth()
719 + {
720 + while ( mDay < 1 )
721 + {
722 + if ( --mMonth < 1 )
723 + {
724 + mMonth = 12;
725 + mYear--;
726 + }
727 + mDay += Month.daysIn( mYear, mMonth );
728 + }
729 + while ( 28 < mDay )
730 + {
731 + int zDaysInMonth = Month.daysIn( mYear, mMonth );
732 + if ( mDay <= zDaysInMonth )
733 + {
734 + break;
735 + }
736 + mDay -= zDaysInMonth;
737 + if ( 12 < ++mMonth )
738 + {
739 + mMonth = 1;
740 + mYear++;
741 + }
742 + }
743 + return this;
744 + }
745 +
746 + private Mutable adjustDayOfMonthForMonthOrYearChange( boolean pAdjustForward )
747 + {
748 + normalizeMonthOfYear();
749 + if ( mDateFormat.getDateRes().isValidToDay() ) // if Not, then any year works with any month
750 + {
751 + int maxDaysInMonth = Month.daysIn( mYear, mMonth );
752 + if ( maxDaysInMonth < mDay )
753 + {
754 + mDay = maxDaysInMonth;
755 + if ( pAdjustForward )
756 + {
757 + return addDays( 1 );
758 + }
759 + }
760 + }
761 + return this;
762 + }
763 +
764 + public Mutable addDays( int pDays )
765 + {
766 + mDay += pDays;
767 + for ( int maxDaysInMonth; (maxDaysInMonth = Month.daysIn( mYear, mMonth )) < mDay; )
768 + {
769 + mDay -= maxDaysInMonth;
770 + if ( ++mMonth > 12 )
771 + {
772 + mMonth = 1;
773 + mYear++;
774 + }
775 + }
776 + return this;
777 + }
778 +
779 + public Mutable minusDays( int pDays )
780 + {
781 + mDay -= pDays;
782 + while ( mDay < 1 )
783 + {
784 + if ( --mMonth < 1 )
785 + {
786 + mMonth = 12;
787 + mYear--;
788 + }
789 + mDay += Month.daysIn( mYear, mMonth );
790 + }
791 + return this;
792 + }
793 +
794 + public SimpleDate toSimpleDate()
795 + {
796 + return new SimpleDate( this, mDateFormat );
797 + }
712 798 }
713 799 }