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