0
# Date and Time Matchers
1
2
JVM date and time assertions for Java time API including temporal comparisons, duration validation, and specialized date/time operations for comprehensive temporal testing capabilities.
3
4
## Capabilities
5
6
### LocalDate Matchers
7
8
Matchers for LocalDate validation including comparisons and date-specific operations.
9
10
```kotlin { .api }
11
/**
12
* Assert that LocalDate is before another date
13
* @param other The date this should be before
14
* @return The original LocalDate for chaining
15
*/
16
infix fun LocalDate.shouldBeBefore(other: LocalDate): LocalDate
17
18
/**
19
* Assert that LocalDate is not before another date
20
* @param other The date this should not be before
21
* @return The original LocalDate for chaining
22
*/
23
infix fun LocalDate.shouldNotBeBefore(other: LocalDate): LocalDate
24
25
/**
26
* Assert that LocalDate is after another date
27
* @param other The date this should be after
28
* @return The original LocalDate for chaining
29
*/
30
infix fun LocalDate.shouldBeAfter(other: LocalDate): LocalDate
31
32
/**
33
* Assert that LocalDate is not after another date
34
* @param other The date this should not be after
35
* @return The original LocalDate for chaining
36
*/
37
infix fun LocalDate.shouldNotBeAfter(other: LocalDate): LocalDate
38
39
/**
40
* Assert that LocalDate is today's date
41
* @return The original LocalDate for chaining
42
*/
43
fun LocalDate.shouldBeToday(): LocalDate
44
45
/**
46
* Assert that LocalDate is not today's date
47
* @return The original LocalDate for chaining
48
*/
49
fun LocalDate.shouldNotBeToday(): LocalDate
50
51
/**
52
* Assert that LocalDate is yesterday's date
53
* @return The original LocalDate for chaining
54
*/
55
fun LocalDate.shouldBeYesterday(): LocalDate
56
57
/**
58
* Assert that LocalDate is tomorrow's date
59
* @return The original LocalDate for chaining
60
*/
61
fun LocalDate.shouldBeTomorrow(): LocalDate
62
63
/**
64
* Assert that LocalDate is within specified number of days from another date
65
* @param days Number of days tolerance
66
* @param other The reference date
67
* @return The original LocalDate for chaining
68
*/
69
fun LocalDate.shouldBeWithinDays(days: Int, other: LocalDate): LocalDate
70
71
/**
72
* Create matcher for date comparison (before)
73
* @param other The date to compare against
74
* @return Matcher that passes when date is before other
75
*/
76
fun beBefore(other: LocalDate): Matcher<LocalDate>
77
78
/**
79
* Create matcher for date comparison (after)
80
* @param other The date to compare against
81
* @return Matcher that passes when date is after other
82
*/
83
fun beAfter(other: LocalDate): Matcher<LocalDate>
84
85
/**
86
* Create matcher for today validation
87
* @return Matcher that passes when date is today
88
*/
89
fun beToday(): Matcher<LocalDate>
90
91
/**
92
* Create matcher for yesterday validation
93
* @return Matcher that passes when date is yesterday
94
*/
95
fun beYesterday(): Matcher<LocalDate>
96
97
/**
98
* Create matcher for tomorrow validation
99
* @return Matcher that passes when date is tomorrow
100
*/
101
fun beTomorrow(): Matcher<LocalDate>
102
103
/**
104
* Create matcher for date proximity validation
105
* @param days Number of days tolerance
106
* @param other The reference date
107
* @return Matcher that passes when date is within specified days
108
*/
109
fun beWithinDays(days: Int, other: LocalDate): Matcher<LocalDate>
110
```
111
112
**Usage Examples:**
113
114
```kotlin
115
import io.kotest.matchers.date.*
116
import java.time.LocalDate
117
118
val today = LocalDate.now()
119
val birthday = LocalDate.of(1990, 6, 15)
120
val deadline = LocalDate.of(2024, 12, 31)
121
122
// Date comparison
123
birthday shouldBeBefore today
124
deadline shouldBeAfter today
125
today.shouldBeToday()
126
127
// Proximity validation
128
val nearDate = today.plusDays(2)
129
nearDate.shouldBeWithinDays(5, today)
130
131
// Using matcher syntax
132
birthday should beBefore(today)
133
today should beToday()
134
deadline should beAfter(LocalDate.now())
135
```
136
137
### LocalTime Matchers
138
139
Matchers for LocalTime validation and time-specific operations.
140
141
```kotlin { .api }
142
/**
143
* Assert that LocalTime is before another time
144
* @param other The time this should be before
145
* @return The original LocalTime for chaining
146
*/
147
infix fun LocalTime.shouldBeBefore(other: LocalTime): LocalTime
148
149
/**
150
* Assert that LocalTime is after another time
151
* @param other The time this should be after
152
* @return The original LocalTime for chaining
153
*/
154
infix fun LocalTime.shouldBeAfter(other: LocalTime): LocalTime
155
156
/**
157
* Assert that LocalTime is within specified duration of another time
158
* @param duration The maximum allowed difference
159
* @param other The reference time
160
* @return The original LocalTime for chaining
161
*/
162
fun LocalTime.shouldBeWithin(duration: Duration, other: LocalTime): LocalTime
163
164
/**
165
* Assert that LocalTime represents morning (AM)
166
* @return The original LocalTime for chaining
167
*/
168
fun LocalTime.shouldBeMorning(): LocalTime
169
170
/**
171
* Assert that LocalTime represents afternoon (PM)
172
* @return The original LocalTime for chaining
173
*/
174
fun LocalTime.shouldBeAfternoon(): LocalTime
175
176
/**
177
* Assert that LocalTime is within business hours (9 AM - 5 PM)
178
* @return The original LocalTime for chaining
179
*/
180
fun LocalTime.shouldBeBusinessHours(): LocalTime
181
182
/**
183
* Create matcher for time comparison (before)
184
* @param other The time to compare against
185
* @return Matcher that passes when time is before other
186
*/
187
fun beBefore(other: LocalTime): Matcher<LocalTime>
188
189
/**
190
* Create matcher for time comparison (after)
191
* @param other The time to compare against
192
* @return Matcher that passes when time is after other
193
*/
194
fun beAfter(other: LocalTime): Matcher<LocalTime>
195
196
/**
197
* Create matcher for time proximity validation
198
* @param duration Maximum allowed difference
199
* @param other The reference time
200
* @return Matcher that passes when time is within duration
201
*/
202
fun beWithin(duration: Duration, other: LocalTime): Matcher<LocalTime>
203
204
/**
205
* Create matcher for morning time validation
206
* @return Matcher that passes for morning times
207
*/
208
fun beMorning(): Matcher<LocalTime>
209
210
/**
211
* Create matcher for business hours validation
212
* @return Matcher that passes for business hour times
213
*/
214
fun beBusinessHours(): Matcher<LocalTime>
215
```
216
217
### LocalDateTime Matchers
218
219
Matchers for LocalDateTime combining date and time validation capabilities.
220
221
```kotlin { .api }
222
/**
223
* Assert that LocalDateTime is before another datetime
224
* @param other The datetime this should be before
225
* @return The original LocalDateTime for chaining
226
*/
227
infix fun LocalDateTime.shouldBeBefore(other: LocalDateTime): LocalDateTime
228
229
/**
230
* Assert that LocalDateTime is after another datetime
231
* @param other The datetime this should be after
232
* @return The original LocalDateTime for chaining
233
*/
234
infix fun LocalDateTime.shouldBeAfter(other: LocalDateTime): LocalDateTime
235
236
/**
237
* Assert that LocalDateTime is within specified duration of another datetime
238
* @param duration The maximum allowed difference
239
* @param other The reference datetime
240
* @return The original LocalDateTime for chaining
241
*/
242
fun LocalDateTime.shouldBeWithin(duration: Duration, other: LocalDateTime): LocalDateTime
243
244
/**
245
* Assert that LocalDateTime is close to now within specified duration
246
* @param duration Maximum allowed difference from current time
247
* @return The original LocalDateTime for chaining
248
*/
249
fun LocalDateTime.shouldBeCloseToNow(duration: Duration): LocalDateTime
250
251
/**
252
* Assert that LocalDateTime represents today (same date as today)
253
* @return The original LocalDateTime for chaining
254
*/
255
fun LocalDateTime.shouldBeToday(): LocalDateTime
256
257
/**
258
* Assert that LocalDateTime is in the past
259
* @return The original LocalDateTime for chaining
260
*/
261
fun LocalDateTime.shouldBeInPast(): LocalDateTime
262
263
/**
264
* Assert that LocalDateTime is in the future
265
* @return The original LocalDateTime for chaining
266
*/
267
fun LocalDateTime.shouldBeInFuture(): LocalDateTime
268
269
/**
270
* Create matcher for datetime comparison (before)
271
* @param other The datetime to compare against
272
* @return Matcher that passes when datetime is before other
273
*/
274
fun beBefore(other: LocalDateTime): Matcher<LocalDateTime>
275
276
/**
277
* Create matcher for datetime comparison (after)
278
* @param other The datetime to compare against
279
* @return Matcher that passes when datetime is after other
280
*/
281
fun beAfter(other: LocalDateTime): Matcher<LocalDateTime>
282
283
/**
284
* Create matcher for datetime proximity validation
285
* @param duration Maximum allowed difference
286
* @param other The reference datetime
287
* @return Matcher that passes when datetime is within duration
288
*/
289
fun beWithin(duration: Duration, other: LocalDateTime): Matcher<LocalDateTime>
290
291
/**
292
* Create matcher for recent time validation
293
* @param duration Maximum age from now
294
* @return Matcher that passes when datetime is recent
295
*/
296
fun beCloseToNow(duration: Duration): Matcher<LocalDateTime>
297
298
/**
299
* Create matcher for past time validation
300
* @return Matcher that passes for past datetimes
301
*/
302
fun beInPast(): Matcher<LocalDateTime>
303
304
/**
305
* Create matcher for future time validation
306
* @return Matcher that passes for future datetimes
307
*/
308
fun beInFuture(): Matcher<LocalDateTime>
309
```
310
311
**Usage Examples:**
312
313
```kotlin
314
import io.kotest.matchers.date.*
315
import java.time.*
316
317
val now = LocalDateTime.now()
318
val pastEvent = now.minusHours(2)
319
val futureEvent = now.plusDays(1)
320
val morningTime = LocalTime.of(9, 30)
321
322
// DateTime comparison
323
pastEvent shouldBeBefore now
324
futureEvent shouldBeAfter now
325
pastEvent.shouldBeInPast()
326
futureEvent.shouldBeInFuture()
327
328
// Time validation
329
morningTime.shouldBeMorning()
330
morningTime.shouldBeBusinessHours()
331
332
// Proximity validation
333
val recent = now.minusMinutes(5)
334
recent.shouldBeCloseToNow(Duration.ofMinutes(10))
335
336
// Using matcher syntax
337
pastEvent should beInPast()
338
futureEvent should beInFuture()
339
morningTime should beMorning()
340
```
341
342
### Instant and ZonedDateTime Matchers
343
344
Matchers for timezone-aware and UTC instant validation.
345
346
```kotlin { .api }
347
/**
348
* Assert that Instant is before another instant
349
* @param other The instant this should be before
350
* @return The original Instant for chaining
351
*/
352
infix fun Instant.shouldBeBefore(other: Instant): Instant
353
354
/**
355
* Assert that Instant is after another instant
356
* @param other The instant this should be after
357
* @return The original Instant for chaining
358
*/
359
infix fun Instant.shouldBeAfter(other: Instant): Instant
360
361
/**
362
* Assert that Instant is within specified duration of another instant
363
* @param duration The maximum allowed difference
364
* @param other The reference instant
365
* @return The original Instant for chaining
366
*/
367
fun Instant.shouldBeWithin(duration: Duration, other: Instant): Instant
368
369
/**
370
* Assert that Instant is close to now within specified duration
371
* @param duration Maximum allowed difference from current instant
372
* @return The original Instant for chaining
373
*/
374
fun Instant.shouldBeCloseToNow(duration: Duration): Instant
375
376
/**
377
* Assert that ZonedDateTime is in specified timezone
378
* @param zone The expected timezone
379
* @return The original ZonedDateTime for chaining
380
*/
381
infix fun ZonedDateTime.shouldBeInZone(zone: ZoneId): ZonedDateTime
382
383
/**
384
* Assert that ZonedDateTime is in UTC timezone
385
* @return The original ZonedDateTime for chaining
386
*/
387
fun ZonedDateTime.shouldBeInUTC(): ZonedDateTime
388
389
/**
390
* Assert that ZonedDateTime is before another zoned datetime
391
* @param other The datetime this should be before
392
* @return The original ZonedDateTime for chaining
393
*/
394
infix fun ZonedDateTime.shouldBeBefore(other: ZonedDateTime): ZonedDateTime
395
396
/**
397
* Assert that ZonedDateTime is after another zoned datetime
398
* @param other The datetime this should be after
399
* @return The original ZonedDateTime for chaining
400
*/
401
infix fun ZonedDateTime.shouldBeAfter(other: ZonedDateTime): ZonedDateTime
402
403
/**
404
* Create matcher for instant comparison (before)
405
* @param other The instant to compare against
406
* @return Matcher that passes when instant is before other
407
*/
408
fun beBefore(other: Instant): Matcher<Instant>
409
410
/**
411
* Create matcher for instant proximity validation
412
* @param duration Maximum allowed difference
413
* @param other The reference instant
414
* @return Matcher that passes when instant is within duration
415
*/
416
fun beWithin(duration: Duration, other: Instant): Matcher<Instant>
417
418
/**
419
* Create matcher for timezone validation
420
* @param zone Expected timezone
421
* @return Matcher that passes when datetime is in specified zone
422
*/
423
fun beInZone(zone: ZoneId): Matcher<ZonedDateTime>
424
425
/**
426
* Create matcher for UTC timezone validation
427
* @return Matcher that passes when datetime is in UTC
428
*/
429
fun beInUTC(): Matcher<ZonedDateTime>
430
```
431
432
### Duration and Period Matchers
433
434
Matchers for validating time durations and date periods.
435
436
```kotlin { .api }
437
/**
438
* Assert that Duration is positive (greater than zero)
439
* @return The original Duration for chaining
440
*/
441
fun Duration.shouldBePositive(): Duration
442
443
/**
444
* Assert that Duration is negative (less than zero)
445
* @return The original Duration for chaining
446
*/
447
fun Duration.shouldBeNegative(): Duration
448
449
/**
450
* Assert that Duration is zero
451
* @return The original Duration for chaining
452
*/
453
fun Duration.shouldBeZero(): Duration
454
455
/**
456
* Assert that Duration is greater than another duration
457
* @param other The duration to compare against
458
* @return The original Duration for chaining
459
*/
460
infix fun Duration.shouldBeGreaterThan(other: Duration): Duration
461
462
/**
463
* Assert that Duration is less than another duration
464
* @param other The duration to compare against
465
* @return The original Duration for chaining
466
*/
467
infix fun Duration.shouldBeLessThan(other: Duration): Duration
468
469
/**
470
* Assert that Duration is between two durations (inclusive)
471
* @param min Lower bound duration (inclusive)
472
* @param max Upper bound duration (inclusive)
473
* @return The original Duration for chaining
474
*/
475
fun Duration.shouldBeBetween(min: Duration, max: Duration): Duration
476
477
/**
478
* Assert that Period is positive (all components positive or zero)
479
* @return The original Period for chaining
480
*/
481
fun Period.shouldBePositive(): Period
482
483
/**
484
* Assert that Period is negative (at least one component negative)
485
* @return The original Period for chaining
486
*/
487
fun Period.shouldBeNegative(): Period
488
489
/**
490
* Assert that Period is zero (all components zero)
491
* @return The original Period for chaining
492
*/
493
fun Period.shouldBeZero(): Period
494
495
/**
496
* Create matcher for positive duration validation
497
* @return Matcher that passes for positive durations
498
*/
499
fun bePositive(): Matcher<Duration>
500
501
/**
502
* Create matcher for duration comparison (greater than)
503
* @param other The duration to compare against
504
* @return Matcher that passes when duration is greater
505
*/
506
fun beGreaterThan(other: Duration): Matcher<Duration>
507
508
/**
509
* Create matcher for duration range validation
510
* @param min Lower bound duration
511
* @param max Upper bound duration
512
* @return Matcher that passes when duration is within range
513
*/
514
fun beBetween(min: Duration, max: Duration): Matcher<Duration>
515
```
516
517
**Usage Examples:**
518
519
```kotlin
520
import io.kotest.matchers.date.*
521
import java.time.*
522
523
val utcZone = ZoneId.of("UTC")
524
val pacificZone = ZoneId.of("America/Los_Angeles")
525
val utcTime = ZonedDateTime.now(utcZone)
526
val pacificTime = ZonedDateTime.now(pacificZone)
527
528
// Timezone validation
529
utcTime.shouldBeInUTC()
530
pacificTime shouldBeInZone pacificZone
531
532
// Instant validation
533
val now = Instant.now()
534
val past = now.minusSeconds(30)
535
val future = now.plusMinutes(5)
536
537
past shouldBeBefore now
538
future shouldBeAfter now
539
past.shouldBeCloseToNow(Duration.ofMinutes(1))
540
541
// Duration validation
542
val shortDuration = Duration.ofSeconds(30)
543
val longDuration = Duration.ofHours(2)
544
545
shortDuration.shouldBePositive()
546
longDuration shouldBeGreaterThan shortDuration
547
shortDuration.shouldBeBetween(Duration.ofSeconds(10), Duration.ofMinutes(1))
548
549
// Using matcher syntax
550
utcTime should beInUTC()
551
shortDuration should bePositive()
552
longDuration should beGreaterThan(Duration.ofHours(1))
553
```
554
555
### Specialized Date Operations
556
557
Advanced matchers for complex date and time operations.
558
559
```kotlin { .api }
560
/**
561
* Assert that date is a weekend (Saturday or Sunday)
562
* @return The original LocalDate for chaining
563
*/
564
fun LocalDate.shouldBeWeekend(): LocalDate
565
566
/**
567
* Assert that date is a weekday (Monday through Friday)
568
* @return The original LocalDate for chaining
569
*/
570
fun LocalDate.shouldBeWeekday(): LocalDate
571
572
/**
573
* Assert that date is a specific day of week
574
* @param dayOfWeek The expected day of week
575
* @return The original LocalDate for chaining
576
*/
577
infix fun LocalDate.shouldBeDayOfWeek(dayOfWeek: DayOfWeek): LocalDate
578
579
/**
580
* Assert that date is in specified month
581
* @param month The expected month
582
* @return The original LocalDate for chaining
583
*/
584
infix fun LocalDate.shouldBeInMonth(month: Month): LocalDate
585
586
/**
587
* Assert that date is in specified year
588
* @param year The expected year
589
* @return The original LocalDate for chaining
590
*/
591
infix fun LocalDate.shouldBeInYear(year: Int): LocalDate
592
593
/**
594
* Assert that date is a leap year
595
* @return The original LocalDate for chaining
596
*/
597
fun LocalDate.shouldBeLeapYear(): LocalDate
598
599
/**
600
* Assert that date is not a leap year
601
* @return The original LocalDate for chaining
602
*/
603
fun LocalDate.shouldNotBeLeapYear(): LocalDate
604
605
/**
606
* Assert that date is first day of month
607
* @return The original LocalDate for chaining
608
*/
609
fun LocalDate.shouldBeFirstDayOfMonth(): LocalDate
610
611
/**
612
* Assert that date is last day of month
613
* @return The original LocalDate for chaining
614
*/
615
fun LocalDate.shouldBeLastDayOfMonth(): LocalDate
616
617
/**
618
* Create matcher for weekend validation
619
* @return Matcher that passes for weekend dates
620
*/
621
fun beWeekend(): Matcher<LocalDate>
622
623
/**
624
* Create matcher for weekday validation
625
* @return Matcher that passes for weekday dates
626
*/
627
fun beWeekday(): Matcher<LocalDate>
628
629
/**
630
* Create matcher for day of week validation
631
* @param dayOfWeek The expected day of week
632
* @return Matcher that passes for specified day of week
633
*/
634
fun beDayOfWeek(dayOfWeek: DayOfWeek): Matcher<LocalDate>
635
636
/**
637
* Create matcher for month validation
638
* @param month The expected month
639
* @return Matcher that passes for dates in specified month
640
*/
641
fun beInMonth(month: Month): Matcher<LocalDate>
642
643
/**
644
* Create matcher for leap year validation
645
* @return Matcher that passes for leap year dates
646
*/
647
fun beLeapYear(): Matcher<LocalDate>
648
649
/**
650
* Create matcher for month boundary validation
651
* @return Matcher that passes for first day of month
652
*/
653
fun beFirstDayOfMonth(): Matcher<LocalDate>
654
```
655
656
**Usage Examples:**
657
658
```kotlin
659
import io.kotest.matchers.date.*
660
import java.time.*
661
662
val monday = LocalDate.of(2024, 1, 1) // Assuming this is a Monday
663
val saturday = LocalDate.of(2024, 1, 6)
664
val christmas = LocalDate.of(2024, 12, 25)
665
val leapYearDate = LocalDate.of(2024, 2, 29)
666
667
// Day of week validation
668
monday.shouldBeWeekday()
669
saturday.shouldBeWeekend()
670
monday shouldBeDayOfWeek DayOfWeek.MONDAY
671
672
// Month and year validation
673
christmas shouldBeInMonth Month.DECEMBER
674
christmas shouldBeInYear 2024
675
676
// Leap year validation
677
leapYearDate.shouldBeLeapYear()
678
679
// Month boundary validation
680
val firstDay = LocalDate.of(2024, 1, 1)
681
firstDay.shouldBeFirstDayOfMonth()
682
683
// Using matcher syntax
684
monday should beWeekday()
685
saturday should beWeekend()
686
christmas should beInMonth(Month.DECEMBER)
687
leapYearDate should beLeapYear()
688
```
689
690
## Error Handling
691
692
Date and time matchers provide comprehensive error messages for assertion failures:
693
694
- **Temporal comparison failures**: Show expected vs actual dates/times with clear temporal relationship
695
- **Duration failures**: Display expected vs actual durations in human-readable format
696
- **Timezone failures**: Indicate expected vs actual timezones with offset information
697
- **Proximity failures**: Show the actual difference compared to allowed tolerance
698
- **Calendar failures**: Clear indication of expected vs actual day/month/year components
699
- **Period failures**: Detailed breakdown of period components (years, months, days)
700
701
All date/time matchers handle edge cases like leap years, daylight saving transitions, and timezone conversions while providing meaningful error context for temporal assertion failures.