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 }