001 package org.fest.assertions.api;
002
003 import static org.fest.util.Dates.ISO_DATE_FORMAT;
004
005 import java.text.DateFormat;
006 import java.text.ParseException;
007 import java.util.ArrayList;
008 import java.util.Calendar;
009 import java.util.Collection;
010 import java.util.Comparator;
011 import java.util.Date;
012 import java.util.concurrent.TimeUnit;
013
014 import org.fest.assertions.core.Assert;
015 import org.fest.assertions.internal.Dates;
016 import org.fest.assertions.internal.Failures;
017 import org.fest.util.ComparatorBasedComparisonStrategy;
018 import org.fest.util.VisibleForTesting;
019
020 /**
021 *
022 * Assertions for {@code Date}s.
023 * <p>
024 * To create a new instance of this class invoke <code>{@link Assertions#assertThat(Date)}</code>.
025 * </p>
026 * Note that assertions with date parameter comes with two flavor, one is obviously a {@link Date} and the other is a
027 * String representing a Date.<br>
028 * For the latter, the default format follows ISO 8901 : "yyyy-MM-dd", user can override it with a custom format by
029 * calling {@link #withDateFormat(DateFormat)}.<br>
030 * The user custom format will then be used for all next Date assertions (i.e not limited to the current assertion) in
031 * the test suite.<br>
032 * To turn back to default format, simply call {@link #withIsoDateFormat()}.
033 *
034 * @author Tomasz Nurkiewicz (thanks for giving assertions idea)
035 * @author Joel Costigliola
036 */
037 public class DateAssert extends AbstractAssert<DateAssert, Date> {
038
039 @VisibleForTesting
040 Dates dates = Dates.instance();
041
042 /**
043 * Used in String based Date assertions - like {@link #isAfter(String)} - to convert input date represented as string
044 * to Date.<br>
045 * The format used can be overriden by invoking {@link #withDateFormat(DateFormat)}
046 */
047 @VisibleForTesting
048 static DateFormat dateFormat = ISO_DATE_FORMAT;
049
050 /**
051 * Creates a new </code>{@link DateAssert}</code>.
052 * @param actual the target to verify.
053 */
054 protected DateAssert(Date actual) {
055 super(actual, DateAssert.class);
056 }
057
058 /**
059 * Same assertion as {@link AbstractAssert#isEqualTo(Object) isEqualTo(Date date)} but given Date is represented as String either with ISO date format
060 * (yyyy-MM-dd) or user custom date format (set with method {@link #withDateFormat(DateFormat)}).
061 * @param dateAsString the given Date represented as String in default or custom date format.
062 * @return this assertion object.
063 * @throws AssertionError if actual and given Date represented as String are not equal.
064 * @throws AssertionError if the given date as String could not be converted to a Date.
065 */
066 public DateAssert isEqualTo(String dateAsString) {
067 return isEqualTo(parse(dateAsString));
068 }
069
070 /**
071 * Same assertion as {@link AbstractAssert#isNotEqualTo(Object) isNotEqualTo(Date date)} but given Date is represented as String either with ISO date format
072 * (yyyy-MM-dd) or user custom date format (set with method {@link #withDateFormat(DateFormat)}).
073 * @param dateAsString the given Date represented as String in default or custom date format.
074 * @return this assertion object.
075 * @throws AssertionError if actual and given Date represented as String are equal.
076 * @throws AssertionError if the given date as String could not be converted to a Date.
077 */
078 public DateAssert isNotEqualTo(String dateAsString) {
079 return isNotEqualTo(parse(dateAsString));
080 }
081
082 /**
083 * Same assertion as {@link Assert#isIn(Object...)} but given Dates are represented as String either with ISO date format
084 * (yyyy-MM-dd) or user custom date format (set with method {@link #withDateFormat(DateFormat)}).
085 * @param datesAsString the given Dates represented as String in default or custom date format.
086 * @return this assertion object.
087 * @throws AssertionError if actual is not in given Dates represented as String.
088 * @throws AssertionError if one of the given date as String could not be converted to a Date.
089 */
090 public DateAssert isIn(String... datesAsString) {
091 Date[] dates = new Date[datesAsString.length];
092 for (int i = 0; i < datesAsString.length; i++) {
093 dates[i] = parse(datesAsString[i]);
094 }
095 return isIn(dates);
096 }
097
098 /**
099 * Same assertion as {@link Assert#isIn(Iterable)} but given Dates are represented as String either with ISO date format
100 * (yyyy-MM-dd) or user custom date format (set with method {@link #withDateFormat(DateFormat)}).<br>
101 * Method signature could not be <code>isIn(Collection<String>)</code> because it would be same signature as
102 * <code>isIn(Collection<Date>)</code> since java collection type are erased at runtime.
103 * @param datesAsString the given Dates represented as String in default or custom date format.
104 * @return this assertion object.
105 * @throws AssertionError if actual is not in given Dates represented as String.
106 * @throws AssertionError if one of the given date as String could not be converted to a Date.
107 */
108 public DateAssert isInWithStringDateCollection(Collection<String> datesAsString) {
109 Collection<Date> dates = new ArrayList<Date>(datesAsString.size());
110 for (String dateAsString : datesAsString) {
111 dates.add(parse(dateAsString));
112 }
113 return isIn(dates);
114 }
115
116 /**
117 * Same assertion as {@link Assert#isNotIn(Object...)} but given Dates are represented as String either with ISO date
118 * format (yyyy-MM-dd) or user custom date format (set with method {@link #withDateFormat(DateFormat)}).
119 * @param datesAsString the given Dates represented as String in default or custom date format.
120 * @return this assertion object.
121 * @throws AssertionError if actual is in given Dates represented as String.
122 * @throws AssertionError if one of the given date as String could not be converted to a Date.
123 */
124 public DateAssert isNotIn(String... datesAsString) {
125 Date[] dates = new Date[datesAsString.length];
126 for (int i = 0; i < datesAsString.length; i++) {
127 dates[i] = parse(datesAsString[i]);
128 }
129 return isNotIn(dates);
130 }
131
132 /**
133 * Same assertion as {@link Assert#isNotIn(Iterable)} but given Dates are represented as String either with ISO date
134 * format (yyyy-MM-dd) or user custom date format (set with method {@link #withDateFormat(DateFormat)}).<br>
135 * Method signature could not be <code>isNotIn(Collection<String>)</code> because it would be same signature as
136 * <code>isNotIn(Collection<Date>)</code> since java collection type are erased at runtime.
137 * @param datesAsString the given Dates represented as String in default or custom date format.
138 * @return this assertion object.
139 * @throws AssertionError if actual is in given Dates represented as String.
140 * @throws AssertionError if one of the given date as String could not be converted to a Date.
141 */
142 public DateAssert isNotInWithStringDateCollection(Collection<String> datesAsString) {
143 Collection<Date> dates = new ArrayList<Date>(datesAsString.size());
144 for (String dateAsString : datesAsString) {
145 dates.add(parse(dateAsString));
146 }
147 return isNotIn(dates);
148 }
149
150 /**
151 * Verifies that the actual {@code Date} is <b>strictly</b> before the given one.
152 * @param other the given Date.
153 * @return this assertion object.
154 * @throws AssertionError if the actual {@code Date} is {@code null}.
155 * @throws NullPointerException if other {@code Date} is {@code null}.
156 * @throws AssertionError if the actual {@code Date} is not strictly before the given one.
157 */
158 public DateAssert isBefore(Date other) {
159 dates.assertIsBefore(info, actual, other);
160 return this;
161 }
162
163 /**
164 * Same assertion as {@link #isBefore(Date)} but given Date is represented as String either with ISO date format
165 * (yyyy-MM-dd) or user custom date format (set with method {@link #withDateFormat(DateFormat)}).
166 * @param dateAsString the given Date represented as String in default or custom date format.
167 * @return this assertion object.
168 * @throws AssertionError if the actual {@code Date} is {@code null}.
169 * @throws NullPointerException if given date as String is {@code null}.
170 * @throws AssertionError if the actual {@code Date} is not strictly before the given Date represented as String.
171 * @throws AssertionError if the given date as String could not be converted to a Date.
172 */
173 public DateAssert isBefore(String dateAsString) {
174 return isBefore(parse(dateAsString));
175 }
176
177 /**
178 * Verifies that the actual {@code Date} is before or equals to the given one.
179 * @param other the given Date.
180 * @return this assertion object.
181 * @throws AssertionError if the actual {@code Date} is {@code null}.
182 * @throws NullPointerException if other {@code Date} is {@code null}.
183 * @throws AssertionError if the actual {@code Date} is not before or equals to the given one.
184 */
185 public DateAssert isBeforeOrEqualsTo(Date other) {
186 dates.assertIsBeforeOrEqualsTo(info, actual, other);
187 return this;
188 }
189
190 /**
191 * Same assertion as {@link #isBeforeOrEqualsTo(Date)} but given Date is represented as String either with ISO date
192 * format (yyyy-MM-dd) or user custom date format (set with method {@link #withDateFormat(DateFormat)}).
193 * @param dateAsString the given Date represented as String in default or custom date format.
194 * @return this assertion object.
195 * @throws AssertionError if the actual {@code Date} is {@code null}.
196 * @throws NullPointerException if given date as String is {@code null}.
197 * @throws AssertionError if the actual {@code Date} is not before or equals to the given Date represented as String.
198 * @throws AssertionError if the given date as String could not be converted to a Date.
199 */
200 public DateAssert isBeforeOrEqualsTo(String dateAsString) {
201 return isBeforeOrEqualsTo(parse(dateAsString));
202 }
203
204 /**
205 * Verifies that the actual {@code Date} is <b>strictly</b> after the given one.
206 * @param other the given Date.
207 * @return this assertion object.
208 * @throws AssertionError if the actual {@code Date} is {@code null}.
209 * @throws NullPointerException if other {@code Date} is {@code null}.
210 * @throws AssertionError if the actual {@code Date} is not strictly after the given one.
211 */
212 public DateAssert isAfter(Date other) {
213 dates.assertIsAfter(info, actual, other);
214 return this;
215 }
216
217 /**
218 * Same assertion as {@link #isAfter(Date)} but given Date is represented as String either with ISO date format
219 * (yyyy-MM-dd) or user custom date format (set with method {@link #withDateFormat(DateFormat)}).
220 * @param dateAsString the given Date represented as String in default or custom date format.
221 * @return this assertion object.
222 * @throws AssertionError if the actual {@code Date} is {@code null}.
223 * @throws NullPointerException if given date as String is {@code null}.
224 * @throws AssertionError if the actual {@code Date} is not strictly after the given Date represented as String.
225 * @throws AssertionError if the given date as String could not be converted to a Date.
226 */
227 public DateAssert isAfter(String dateAsString) {
228 return isAfter(parse(dateAsString));
229 }
230
231 /**
232 * Verifies that the actual {@code Date} is after or equals to the given one.
233 * @param other the given Date.
234 * @return this assertion object.
235 * @throws AssertionError if the actual {@code Date} is {@code null}.
236 * @throws NullPointerException if other {@code Date} is {@code null}.
237 * @throws AssertionError if the actual {@code Date} is not after or equals to the given one.
238 */
239 public DateAssert isAfterOrEqualsTo(Date other) {
240 dates.assertIsAfterOrEqualsTo(info, actual, other);
241 return this;
242 }
243
244 /**
245 * Same assertion as {@link #isAfterOrEqualsTo(Date)} but given Date is represented as String either with ISO date
246 * format (yyyy-MM-dd) or user custom date format (set with method {@link #withDateFormat(DateFormat)}).
247 * @param dateAsString the given Date represented as String in default or custom date format.
248 * @return this assertion object.
249 * @throws AssertionError if the actual {@code Date} is {@code null}.
250 * @throws NullPointerException if given date as String is {@code null}.
251 * @throws AssertionError if the actual {@code Date} is not after or equals to the given Date represented as String.
252 * @throws AssertionError if the given date as String could not be converted to a Date.
253 */
254 public DateAssert isAfterOrEqualsTo(String dateAsString) {
255 return isAfterOrEqualsTo(parse(dateAsString));
256 }
257
258 /**
259 * Verifies that the actual {@code Date} is in [start, end[ period (start included, end excluded).
260 * @param start the period start (inclusive), expected not to be null.
261 * @param end the period end (exclusive), expected not to be null.
262 * @return this assertion object.
263 * @throws AssertionError if the actual {@code Date} is {@code null}.
264 * @throws NullPointerException if start {@code Date} is {@code null}.
265 * @throws NullPointerException if end {@code Date} is {@code null}.
266 * @throws AssertionError if the actual {@code Date} is not in [start, end[ period.
267 */
268 public DateAssert isBetween(Date start, Date end) {
269 return isBetween(start, end, true, false);
270 }
271
272 /**
273 * Same assertion as {@link #isBetween(Date, Date)} but given Dates are represented as String either with ISO date
274 * format (yyyy-MM-dd) or user custom date format (set with method {@link #withDateFormat(DateFormat)}).
275 * @param start the period start (inclusive), expected not to be null.
276 * @param end the period end (exclusive), expected not to be null.
277 * @return this assertion object.
278 * @throws AssertionError if the actual {@code Date} is {@code null}.
279 * @throws NullPointerException if start Date as String is {@code null}.
280 * @throws NullPointerException if end Date as String is {@code null}.
281 * @throws AssertionError if the actual {@code Date} is not in [start, end[ period.
282 * @throws AssertionError if one of the given date as String could not be converted to a Date.
283 */
284 public DateAssert isBetween(String start, String end) {
285 return isBetween(parse(start), parse(end));
286 }
287
288 /**
289 * Verifies that the actual {@code Date} is in the given period defined by start and end dates.<br>
290 * To include start in the period set inclusiveStart parameter to <code>true</code>.<br>
291 * To include end in the period set inclusiveEnd parameter to <code>true</code>.<br>
292 * @param start the period start, expected not to be null.
293 * @param end the period end, expected not to be null.
294 * @param inclusiveStart wether to include start date in period.
295 * @param inclusiveEnd wether to include end date in period.
296 * @return this assertion object.
297 * @throws AssertionError if {@code actual} is {@code null}.
298 * @throws NullPointerException if start {@code Date} is {@code null}.
299 * @throws NullPointerException if end {@code Date} is {@code null}.
300 * @throws AssertionError if the actual {@code Date} is not in (start, end) period.
301 */
302 public DateAssert isBetween(Date start, Date end, boolean inclusiveStart, boolean inclusiveEnd) {
303 dates.assertIsBetween(info, actual, start, end, inclusiveStart, inclusiveEnd);
304 return this;
305 }
306
307 /**
308 * Same assertion as {@link #isBetween(Date, Date, boolean, boolean)} but given Dates are represented as String either
309 * with ISO date format (yyyy-MM-dd) or user custom date format (set with method {@link #withDateFormat(DateFormat)}).
310 * @param start the period start, expected not to be null.
311 * @param end the period end, expected not to be null.
312 * @param inclusiveStart wether to include start date in period.
313 * @param inclusiveEnd wether to include end date in period.
314 * @return this assertion object.
315 * @throws AssertionError if {@code actual} is {@code null}.
316 * @throws NullPointerException if start Date as String is {@code null}.
317 * @throws NullPointerException if end Date as String is {@code null}.
318 * @throws AssertionError if the actual {@code Date} is not in (start, end) period.
319 * @throws AssertionError if one of the given date as String could not be converted to a Date.
320 */
321 public DateAssert isBetween(String start, String end, boolean inclusiveStart, boolean inclusiveEnd) {
322 dates.assertIsBetween(info, actual, parse(start), parse(end), inclusiveStart, inclusiveEnd);
323 return this;
324 }
325
326 /**
327 * Verifies that the actual {@code Date} is not in the given period defined by start and end dates.<br>
328 * To include start in the period set inclusiveStart parameter to <code>true</code>.<br>
329 * To include end in the period set inclusiveEnd parameter to <code>true</code>.<br>
330 * @param start the period start (inclusive), expected not to be null.
331 * @param end the period end (exclusive), expected not to be null.
332 * @param inclusiveStart wether to include start date in period.
333 * @param inclusiveEnd wether to include end date in period.
334 * @return this assertion object.
335 * @throws AssertionError if {@code actual} is {@code null}.
336 * @throws NullPointerException if start {@code Date} is {@code null}.
337 * @throws NullPointerException if end {@code Date} is {@code null}.
338 * @throws AssertionError if the actual {@code Date} is not in (start, end) period.
339 */
340 public DateAssert isNotBetween(Date start, Date end, boolean inclusiveStart, boolean inclusiveEnd) {
341 dates.assertIsNotBetween(info, actual, start, end, inclusiveStart, inclusiveEnd);
342 return this;
343 }
344
345 /**
346 * Same assertion as {@link #isNotBetween(Date, Date, boolean, boolean)} but given Dates are represented as String
347 * either with ISO date format (yyyy-MM-dd) or user custom date format (set with method
348 * {@link #withDateFormat(DateFormat)}).
349 * @param start the period start (inclusive), expected not to be null.
350 * @param end the period end (exclusive), expected not to be null.
351 * @param inclusiveStart wether to include start date in period.
352 * @param inclusiveEnd wether to include end date in period.
353 * @return this assertion object.
354 * @throws AssertionError if {@code actual} is {@code null}.
355 * @throws NullPointerException if start Date as String is {@code null}.
356 * @throws NullPointerException if end Date as String is {@code null}.
357 * @throws AssertionError if the actual {@code Date} is not in (start, end) period.
358 * @throws AssertionError if one of the given date as String could not be converted to a Date.
359 */
360 public DateAssert isNotBetween(String start, String end, boolean inclusiveStart, boolean inclusiveEnd) {
361 return isNotBetween(parse(start), parse(end), inclusiveStart, inclusiveEnd);
362 }
363
364 /**
365 * Verifies that the actual {@code Date} is not in [start, end[ period
366 * @param start the period start (inclusive), expected not to be null.
367 * @param end the period end (exclusive), expected not to be null.
368 * @return this assertion object.
369 * @throws AssertionError if the actual {@code Date} is {@code null}.
370 * @throws NullPointerException if start {@code Date} is {@code null}.
371 * @throws NullPointerException if end {@code Date} is {@code null}.
372 * @throws AssertionError if the actual {@code Date} is in [start, end[ period.
373 * @throws AssertionError if one of the given date as String could not be converted to a Date.
374 */
375 public DateAssert isNotBetween(Date start, Date end) {
376 return isNotBetween(start, end, true, false);
377 }
378
379 /**
380 * Same assertion as {@link #isNotBetween(Date, Date)} but given Dates are represented as String either with ISO date
381 * format (yyyy-MM-dd) or user custom date format (set with method {@link #withDateFormat(DateFormat)}).
382 * @param start the period start (inclusive), expected not to be null.
383 * @param end the period end (exclusive), expected not to be null.
384 * @return this assertion object.
385 * @throws AssertionError if the actual {@code Date} is {@code null}.
386 * @throws NullPointerException if start Date as String is {@code null}.
387 * @throws NullPointerException if end Date as String is {@code null}.
388 * @throws AssertionError if the actual {@code Date} is in [start, end[ period.
389 * @throws AssertionError if one of the given date as String could not be converted to a Date.
390 */
391 public DateAssert isNotBetween(String start, String end) {
392 return isNotBetween(parse(start), parse(end), true, false);
393 }
394
395 /**
396 * Verifies that the actual {@code Date} is strictly in the past.
397 * @return this assertion object.
398 * @throws AssertionError if the actual {@code Date} is {@code null}.
399 * @throws AssertionError if the actual {@code Date} is not in the past.
400 */
401 public DateAssert isInThePast() {
402 dates.assertIsInThePast(info, actual);
403 return this;
404 }
405
406 /**
407 * Verifies that the actual {@code Date} is today, that is matching current year, month and day (no check on hour,
408 * minute, second, milliseconds).
409 * @return this assertion object.
410 * @throws AssertionError if the actual {@code Date} is {@code null}.
411 * @throws AssertionError if the actual {@code Date} is not today.
412 */
413 public DateAssert isToday() {
414 dates.assertIsToday(info, actual);
415 return this;
416 }
417
418 /**
419 * Verifies that the actual {@code Date} is strictly in the future.
420 * @return this assertion object.
421 * @throws AssertionError if the actual {@code Date} is {@code null}.
422 * @throws AssertionError if the actual {@code Date} is not in the future.
423 */
424 public DateAssert isInTheFuture() {
425 dates.assertIsInTheFuture(info, actual);
426 return this;
427 }
428
429 /**
430 * Verifies that the actual {@code Date} is <b>strictly</b> before the given year.
431 * @param year the year to compare actual year to
432 * @return this assertion object.
433 * @throws AssertionError if the actual {@code Date} is {@code null}.
434 * @throws AssertionError if the actual {@code Date} year is after or equals to the given year.
435 */
436 public DateAssert isBeforeYear(int year) {
437 dates.assertIsBeforeYear(info, actual, year);
438 return this;
439 }
440
441 /**
442 * Verifies that the actual {@code Date} is <b>strictly</b> after the given year.
443 * @param year the year to compare actual year to
444 * @return this assertion object.
445 * @throws AssertionError if the actual {@code Date} is {@code null}.
446 * @throws AssertionError if the actual {@code Date} year is before or equals to the given year.
447 */
448 public DateAssert isAfterYear(int year) {
449 dates.assertIsAfterYear(info, actual, year);
450 return this;
451 }
452
453 /**
454 * Verifies that the actual {@code Date} year is equal to the given year.
455 * <p>
456 * Note that using a custom comparator has no effect on this assertion (see {@link #usingComparator(Comparator)}.
457 *
458 * @param year the year to compare actual year to
459 * @return this assertion object.
460 * @throws AssertionError if the actual {@code Date} is {@code null}.
461 * @throws AssertionError if the actual {@code Date} year is not equal to the given year.
462 */
463 public DateAssert isWithinYear(int year) {
464 dates.assertIsWithinYear(info, actual, year);
465 return this;
466 }
467
468 /**
469 * Verifies that the actual {@code Date} month is equal to the given month, <b>month value starting at 1</b>
470 * (January=1, February=2, ...).
471 * <p>
472 * Note that using a custom comparator has no effect on this assertion (see {@link #usingComparator(Comparator)}.
473 *
474 * @param month the month to compare actual month to, <b>month value starting at 1</b> (January=1, February=2, ...).
475 * @return this assertion object.
476 * @throws AssertionError if the actual {@code Date} is {@code null}.
477 * @throws AssertionError if the actual {@code Date} month is not equal to the given month.
478 */
479 public DateAssert isWithinMonth(int month) {
480 dates.assertIsWithinMonth(info, actual, month);
481 return this;
482 }
483
484 /**
485 * Verifies that the actual {@code Date} day of month is equal to the given day of month.
486 * <p>
487 * Note that using a custom comparator has no effect on this assertion (see {@link #usingComparator(Comparator)}.
488 *
489 * @param dayOfMonth the day of month to compare actual day of month to
490 * @return this assertion object.
491 * @throws AssertionError if the actual {@code Date} is {@code null}.
492 * @throws AssertionError if the actual {@code Date} month is not equal to the given day of month.
493 */
494 public DateAssert isWithinDayOfMonth(int dayOfMonth) {
495 dates.assertIsWithinDayOfMonth(info, actual, dayOfMonth);
496 return this;
497 }
498
499 /**
500 * Verifies that the actual {@code Date} day of week is equal to the given day of week (see
501 * {@link Calendar#DAY_OF_WEEK} for valid values).
502 * <p>
503 * Note that using a custom comparator has no effect on this assertion (see {@link #usingComparator(Comparator)}.
504 *
505 * @param dayOfWeek the day of week to compare actual day of week to, see {@link Calendar#DAY_OF_WEEK} for valid
506 * values
507 * @return this assertion object.
508 * @throws AssertionError if the actual {@code Date} is {@code null}.
509 * @throws AssertionError if the actual {@code Date} week is not equal to the given day of week.
510 */
511 public DateAssert isWithinDayOfWeek(int dayOfWeek) {
512 dates.assertIsWithinDayOfWeek(info, actual, dayOfWeek);
513 return this;
514 }
515
516 /**
517 * Verifies that the actual {@code Date} hour od day is equal to the given hour of day (24-hour clock).
518 * <p>
519 * Note that using a custom comparator has no effect on this assertion (see {@link #usingComparator(Comparator)}.
520 *
521 * @param hourOfDay the hour of day to compare actual hour of day to (24-hour clock)
522 * @return this assertion object.
523 * @throws AssertionError if the actual {@code Date} is {@code null}.
524 * @throws AssertionError if the actual {@code Date} hour is not equal to the given hour.
525 */
526 public DateAssert isWithinHourOfDay(int hourOfDay) {
527 dates.assertIsWithinHourOfDay(info, actual, hourOfDay);
528 return this;
529 }
530
531 /**
532 * Verifies that the actual {@code Date} minute is equal to the given minute.
533 * <p>
534 * Note that using a custom comparator has no effect on this assertion (see {@link #usingComparator(Comparator)}.
535 *
536 * @param minute the minute to compare actual minute to
537 * @return this assertion object.
538 * @throws AssertionError if the actual {@code Date} is {@code null}.
539 * @throws AssertionError if the actual {@code Date} minute is not equal to the given minute.
540 */
541 public DateAssert isWithinMinute(int minute) {
542 dates.assertIsWithinMinute(info, actual, minute);
543 return this;
544 }
545
546 /**
547 * Verifies that the actual {@code Date} second is equal to the given second.
548 * <p>
549 * Note that using a custom comparator has no effect on this assertion (see {@link #usingComparator(Comparator)}.
550 *
551 * @param second the second to compare actual second to
552 * @return this assertion object.
553 * @throws AssertionError if the actual {@code Date} is {@code null}.
554 * @throws AssertionError if the actual {@code Date} second is not equal to the given second.
555 */
556 public DateAssert isWithinSecond(int second) {
557 dates.assertIsWithinSecond(info, actual, second);
558 return this;
559 }
560
561 /**
562 * Verifies that the actual {@code Date} millisecond is equal to the given millisecond.
563 * <p>
564 * Note that using a custom comparator has no effect on this assertion (see {@link #usingComparator(Comparator)}.
565 *
566 * @param millisecond the millisecond to compare actual millisecond to
567 * @return this assertion object.
568 * @throws AssertionError if the actual {@code Date} is {@code null}.
569 * @throws AssertionError if the actual {@code Date} millisecond is not equal to the given millisecond.
570 */
571 public DateAssert isWithinMillisecond(int millisecond) {
572 dates.assertIsWithinMillisecond(info, actual, millisecond);
573 return this;
574 }
575
576 /**
577 * Verifies that actual and given {@code Date} are in the same year.
578 * <p>
579 * Note that using a custom comparator has no effect on this assertion (see {@link #usingComparator(Comparator)}.
580 *
581 * @param other the given {@code Date} to compare actual {@code Date} to.
582 * @return this assertion object.
583 * @throws NullPointerException if {@code Date} parameter is {@code null}.
584 * @throws AssertionError if the actual {@code Date} is {@code null}.
585 * @throws AssertionError if actual and given {@code Date} are not in the same year.
586 */
587 public DateAssert isInSameYearAs(Date other) {
588 dates.assertIsInSameYearAs(info, actual, other);
589 return this;
590 }
591
592 /**
593 * Same assertion as {@link #isInSameYearAs(Date)} but given Date is represented as String either with ISO date format
594 * (yyyy-MM-dd) or user custom date format (set with method {@link #withDateFormat(DateFormat)}).
595 * @param dateAsString the given Date represented as String in default or custom date format.
596 * @return this assertion object.
597 * @throws NullPointerException if dateAsString parameter is {@code null}.
598 * @throws AssertionError if the actual {@code Date} is {@code null}.
599 * @throws AssertionError if actual and given Date represented as String are not in the same year.
600 * @throws AssertionError if the given date as String could not be converted to a Date.
601 */
602 public DateAssert isInSameYearAs(String dateAsString) {
603 return isInSameYearAs(parse(dateAsString));
604 }
605
606 /**
607 * Verifies that actual and given {@code Date} are chronologically in the same month (and thus in the same year).
608 * <p>
609 * If you want to compare month only (without year), use :
610 * <code>assertThat(myDate).isWithinMonth(monthOf(otherDate))</code><br>
611 * See {@link org.fest.util.Dates#monthOf(Date)} to get the month of a given Date.
612 * <p>
613 * Note that using a custom comparator has no effect on this assertion (see {@link #usingComparator(Comparator)}.
614 *
615 * @param other the given {@code Date} to compare actual {@code Date} to.
616 * @return this assertion object.
617 * @throws NullPointerException if {@code Date} parameter is {@code null}.
618 * @throws AssertionError if the actual {@code Date} is {@code null}.
619 * @throws AssertionError if actual and given {@code Date} are not in the same month.
620 */
621 public DateAssert isInSameMonthAs(Date other) {
622 dates.assertIsInSameMonthAs(info, actual, other);
623 return this;
624 }
625
626 /**
627 * Same assertion as {@link #isInSameMonthAs(Date)} but given Date is represented as String either with ISO date
628 * format (yyyy-MM-dd) or user custom date format (set with method {@link #withDateFormat(DateFormat)}).
629 * @param dateAsString the given Date represented as String in default or custom date format.
630 * @return this assertion object.
631 * @throws NullPointerException if dateAsString parameter is {@code null}.
632 * @throws AssertionError if the actual {@code Date} is {@code null}.
633 * @throws AssertionError if actual and given {@code Date} are not in the same month.
634 */
635 public DateAssert isInSameMonthAs(String dateAsString) {
636 return isInSameMonthAs(parse(dateAsString));
637 }
638
639 /**
640 * Verifies that actual and given {@code Date} are chronologically in the same day of month (and thus in the same
641 * month and year).
642 * <p>
643 * If you want to compare day of month only (without month and year), you could write :
644 * <code>assertThat(myDate).isWithinDayOfMonth(dayOfMonthOf(otherDate))</code><br>
645 * see {@link org.fest.util.Dates#dayOfMonthOf(Date)} to get the day of month of a given Date.
646 * <p>
647 * Note that using a custom comparator has no effect on this assertion (see {@link #usingComparator(Comparator)}.
648 *
649 * @param other the given {@code Date} to compare actual {@code Date} to.
650 * @return this assertion object.
651 * @throws NullPointerException if {@code Date} parameter is {@code null}.
652 * @throws AssertionError if the actual {@code Date} is {@code null}.
653 * @throws AssertionError if actual and given {@code Date} are not in the same day of month.
654 */
655 public DateAssert isInSameDayAs(Date other) {
656 dates.assertIsInSameDayAs(info, actual, other);
657 return this;
658 }
659
660 /**
661 * Same assertion as {@link #isInSameDayAs(Date)} but given Date is represented as String either with ISO date format
662 * (yyyy-MM-dd) or user custom date format (set with method {@link #withDateFormat(DateFormat)}).
663 * @param dateAsString the given Date represented as String in default or custom date format.
664 * @return this assertion object.
665 * @throws NullPointerException if dateAsString parameter is {@code null}.
666 * @throws AssertionError if the actual {@code Date} is {@code null}.
667 * @throws AssertionError if actual and given {@code Date} are not in the same day of month.
668 */
669 public DateAssert isInSameDayAs(String dateAsString) {
670 return isInSameDayAs(parse(dateAsString));
671 }
672
673 /**
674 * Verifies that actual and given {@code Date} are chronologically in the same hour (and thus in the same day, month
675 * and year).
676 * <p>
677 * If you want to compare hour only (without day, month and year), you could write :
678 * <code>assertThat(myDate).isWithinHour(hourOfDayOf(otherDate))</code><br>
679 * see {@link org.fest.util.Dates#hourOfDay(Date)} to get the hour of a given Date.
680 * <p>
681 * Note that using a custom comparator has no effect on this assertion (see {@link #usingComparator(Comparator)}.
682 *
683 * @param other the given {@code Date} to compare actual {@code Date} to.
684 * @return this assertion object.
685 * @throws NullPointerException if {@code Date} parameter is {@code null}.
686 * @throws AssertionError if the actual {@code Date} is {@code null}.
687 * @throws AssertionError if actual and given {@code Date} are not in the same hour.
688 */
689 public DateAssert isInSameHourAs(Date other) {
690 dates.assertIsInSameHourAs(info, actual, other);
691 return this;
692 }
693
694 /**
695 * Same assertion as {@link #isInSameHourAs(Date)} but given Date is represented as String either with ISO date format
696 * (yyyy-MM-dd) or user custom date format (set with method {@link #withDateFormat(DateFormat)}).
697 * @param dateAsString the given Date represented as String in default or custom date format.
698 * @return this assertion object.
699 * @throws NullPointerException if dateAsString parameter is {@code null}.
700 * @throws AssertionError if the actual {@code Date} is {@code null}.
701 * @throws AssertionError if actual and given {@code Date} are not in the same hour.
702 */
703 public DateAssert isInSameHourAs(String dateAsString) {
704 return isInSameHourAs(parse(dateAsString));
705 }
706
707 /**
708 * Verifies that actual and given {@code Date} are chronologically in the same minute (and thus in the same hour, day,
709 * month and year).
710 * <p>
711 * If you want to compare minute only (without hour, day, month and year), you could write :
712 * <code>assertThat(myDate).isWithinMinute(minuteOf(otherDate))</code><br>
713 * see {@link org.fest.util.Dates#minuteOf(Date)} to get the minute of a given Date.
714 * <p>
715 * Note that using a custom comparator has no effect on this assertion (see {@link #usingComparator(Comparator)}.
716 *
717 * @param other the given {@code Date} to compare actual {@code Date} to.
718 * @return this assertion object.
719 * @throws NullPointerException if {@code Date} parameter is {@code null}.
720 * @throws AssertionError if the actual {@code Date} is {@code null}.
721 * @throws AssertionError if actual and given {@code Date} are not in the same minute.
722 */
723 public DateAssert isInSameMinuteAs(Date other) {
724 dates.assertIsInSameMinuteAs(info, actual, other);
725 return this;
726 }
727
728 /**
729 * Same assertion as {@link #isInSameMinuteAs(Date)} but given Date is represented as String either with ISO date
730 * format (yyyy-MM-dd) or user custom date format (set with method {@link #withDateFormat(DateFormat)}).
731 * @param dateAsString the given Date represented as String in default or custom date format.
732 * @return this assertion object.
733 * @throws NullPointerException if dateAsString parameter is {@code null}.
734 * @throws AssertionError if the actual {@code Date} is {@code null}.
735 * @throws AssertionError if actual and given {@code Date} are not in the same minute.
736 */
737 public DateAssert isInSameMinuteAs(String dateAsString) {
738 return isInSameMinuteAs(parse(dateAsString));
739 }
740
741 /**
742 * Verifies that actual and given {@code Date} are chronologically in the same second (and thus in the same minute,
743 * hour, day, month and year).
744 * <p>
745 * If you want to compare second only (without minute, hour, day, month and year), you could write :
746 * <code>assertThat(myDate).isWithinSecond(secondOf(otherDate))</code><br>
747 * see {@link org.fest.util.Dates#secondOf(Date)} to get the second of a given Date.
748 * <p>
749 * Note that using a custom comparator has no effect on this assertion (see {@link #usingComparator(Comparator)}.
750 *
751 * @param other the given {@code Date} to compare actual {@code Date} to.
752 * @return this assertion object.
753 * @throws NullPointerException if {@code Date} parameter is {@code null}.
754 * @throws AssertionError if the actual {@code Date} is {@code null}.
755 * @throws AssertionError if actual and given {@code Date} are not in the same second.
756 */
757 public DateAssert isInSameSecondAs(Date other) {
758 dates.assertIsInSameSecondAs(info, actual, other);
759 return this;
760 }
761
762 /**
763 * Same assertion as {@link #isInSameSecondAs(Date)} but given Date is represented as String either with ISO date
764 * format (yyyy-MM-dd) or user custom date format (set with method {@link #withDateFormat(DateFormat)}).
765 * @param dateAsString the given Date represented as String in default or custom date format.
766 * @return this assertion object.
767 * @throws NullPointerException if dateAsString parameter is {@code null}.
768 * @throws AssertionError if the actual {@code Date} is {@code null}.
769 * @throws AssertionError if actual and given {@code Date} are not in the same second.
770 */
771 public DateAssert isInSameSecondAs(String dateAsString) {
772 return isInSameSecondAs(parse(dateAsString));
773 }
774
775 /**
776 * Verifies that the actual {@code Date} is close to the other date by less than delta (expressed in milliseconds), if
777 * difference is equals to delta it's ok.
778 * <p>
779 * One can use handy {@link TimeUnit} to convert a duration in milliseconds, for example you can express a delta of 5 seconds with
780 * <code>TimeUnit.SECONDS.toMillis(5)</code>.
781 * <p>
782 * Note that using a custom comparator has no effect on this assertion (see {@link #usingComparator(Comparator)}.
783 * @param other the date to compare actual to
784 * @param deltaInMilliseconds the delta used for date comparison, expressed in milliseconds
785 * @return this assertion object.
786 * @throws NullPointerException if {@code Date} parameter is {@code null}.
787 * @throws AssertionError if the actual {@code Date} is {@code null}.
788 * @throws AssertionError if the actual {@code Date} week is not close to the given date by less than delta.
789 */
790 public DateAssert isCloseTo(Date other, long deltaInMilliseconds) {
791 dates.assertIsCloseTo(info, actual, other, deltaInMilliseconds);
792 return this;
793 }
794
795 /**
796 * Same assertion as {@link #isCloseTo(Date, long)} but given Date is represented as String either with ISO date
797 * format (yyyy-MM-dd) or user custom date format (set with method {@link #withDateFormat(DateFormat)}).
798 * @param dateAsString the given Date represented as String in default or custom date format.
799 * @param deltaInMilliseconds the delta used for date comparison, expressed in milliseconds
800 * @return this assertion object.
801 * @throws NullPointerException if dateAsString parameter is {@code null}.
802 * @throws AssertionError if the actual {@code Date} is {@code null}.
803 * @throws AssertionError if the actual {@code Date} week is not close to the given date by less than delta.
804 */
805 public DateAssert isCloseTo(String dateAsString, long deltaInMilliseconds) {
806 return isCloseTo(parse(dateAsString), deltaInMilliseconds);
807 }
808
809 /**
810 * For String based Date assertions like {@link #isBefore(String)}, given String is expected to follow the default
811 * Date format, that is ISO 8601 format : "yyyy-MM-dd".
812 * <p>
813 * With this method, user can specify its own date format, replacing the current date format for all future Date
814 * assertions in the test suite (i.e. not only the current assertions) since custom DateFormat is stored in a static
815 * field.
816 * <p>
817 * To revert to default format simply call {@link #withIsoDateFormat()}.
818 *
819 * @param userCustomDateFormat the new Date format used for String based Date assertions.
820 * @return this assertion object.
821 */
822 public DateAssert withDateFormat(DateFormat userCustomDateFormat) {
823 useDateFormat(userCustomDateFormat);
824 return this;
825 }
826
827 /**
828 * For String based Date assertions like {@link #isBefore(String)}, given String is expected to follow the default
829 * Date format, that is ISO 8601 format : "yyyy-MM-dd".
830 * <p>
831 * With this method, user can specify its own date format, replacing the current date format for all future Date
832 * assertions in the test suite (i.e. not only the current assertions) since custom DateFormat is stored in a static
833 * field.
834 * <p>
835 * To revert to default format simply call {@link #useIsoDateFormat()} (static method) or {@link #withIsoDateFormat()}.
836 *
837 * @param userCustomDateFormat the new Date format used for String based Date assertions.
838 */
839 public static void useDateFormat(DateFormat userCustomDateFormat) {
840 if (userCustomDateFormat == null) throw new NullPointerException("The given date format should not be null");
841 dateFormat = userCustomDateFormat;
842 }
843
844 /**
845 * Use ISO 8601 date format ("yyyy-MM-dd") for String based Date assertions.
846 * @return this assertion object.
847 */
848 public DateAssert withIsoDateFormat() {
849 useIsoDateFormat();
850 return this;
851 }
852
853 /**
854 * Use ISO 8601 date format ("yyyy-MM-dd") for String based Date assertions.
855 */
856 public static void useIsoDateFormat() {
857 dateFormat = ISO_DATE_FORMAT;
858 }
859
860 /**
861 * Utillity method to parse a Date with {@link #dateFormat}, note that it is thread safe.<br>
862 * Returns <code>null</code> if dateAsString parameter is <code>null</code>.
863 * @param dateAsString the string to parse as a Date with {@link #dateFormat}
864 * @return the corrresponding Date, null if dateAsString parameter is null.
865 * @throws AssertionError if the string can't be parsed as a Date
866 */
867 private static Date parse(String dateAsString) {
868 if (dateAsString == null) { return null; }
869 try {
870 // synchronized is used because SimpleDateFormat which is not thread safe (sigh).
871 synchronized (dateFormat) {
872 return dateFormat.parse(dateAsString);
873 }
874 } catch (ParseException e) {
875 throw Failures.instance().failure("Failed to parse " + dateAsString + " with date format " + dateFormat);
876 }
877 }
878
879 @Override
880 public DateAssert usingComparator(Comparator<?> customComparator) {
881 super.usingComparator(customComparator);
882 this.dates = new Dates(new ComparatorBasedComparisonStrategy(customComparator));
883 return myself;
884 }
885
886 @Override
887 public DateAssert usingDefaultComparator() {
888 super.usingDefaultComparator();
889 this.dates = Dates.instance();
890 return myself;
891 }
892 }