Skip to content

Commit e24e977

Browse files
committed
Add StrictDate::on_or_after for date >= date ignoring time
1 parent d96f36c commit e24e977

File tree

3 files changed

+109
-11
lines changed

3 files changed

+109
-11
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
### Unreleased
22

3+
### v0.1.4 (2018-04-30)
4+
5+
* Add StrictDate::on_or_after for validating date >= date ignoring any time component
6+
37
### v0.1.3 (2018-02-22)
48

59
* Extract the basic ValidNumber class for validating minimum

src/Validation/StrictDate.php

Lines changed: 46 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,25 +16,65 @@ class StrictDate
1616
* Validate that value of one field is a date after the value of another
1717
*
1818
* @param \ArrayAccess $validation
19-
* @param string $from_field
20-
* @param string $to_field
19+
* @param string $from_field
20+
* @param string $to_field
2121
*
2222
* @return bool
2323
*/
2424
public static function date_after(\ArrayAccess $validation, $from_field, $to_field)
25+
{
26+
if ( ! $dates = static::get_valid_date_pair($validation, $from_field, $to_field)) {
27+
// Return true if either value is empty or invalid, this will be picked up by other rules
28+
return TRUE;
29+
}
30+
31+
list($from, $to) = $dates;
32+
33+
return ($to > $from);
34+
}
35+
36+
/**
37+
* Validate that value of one field is a date on or after value of another (>= ignoring time)
38+
*
39+
* @param \ArrayAccess $validation
40+
* @param string $from_field
41+
* @param string $to_field
42+
*
43+
* @return bool
44+
*/
45+
public static function date_on_or_after(\ArrayAccess $validation, $from_field, $to_field)
46+
{
47+
if ( ! $dates = static::get_valid_date_pair($validation, $from_field, $to_field)) {
48+
// Return true if either value is empty or invalid, this will be picked up by other rules
49+
return TRUE;
50+
}
51+
52+
list($from, $to) = $dates;
53+
54+
return ($to->format('Y-m-d') >= $from->format('Y-m-d'));
55+
}
56+
57+
/**
58+
* @param \ArrayAccess $validation
59+
* @param string $from_field
60+
* @param string $to_field
61+
*
62+
* @return \DateTimeImmutable[]
63+
*/
64+
protected static function get_valid_date_pair(\ArrayAccess $validation, $from_field, $to_field)
2565
{
2666
$from = $validation[$from_field];
2767
$to = $validation[$to_field];
2868

2969
// Return true if either value is empty or invalid, this will be picked up by other rules
3070
if ($from instanceof InvalidUserDateTime OR ! $from instanceof \DateTimeImmutable) {
31-
return TRUE;
71+
return NULL;
3272
}
3373
if ($to instanceof InvalidUserDateTime OR ! $to instanceof \DateTimeImmutable) {
34-
return TRUE;
74+
return NULL;
3575
}
3676

37-
return ($to > $from);
77+
return [$from, $to];
3878
}
3979

4080
/**
@@ -107,6 +147,7 @@ public static function rule($rulename)
107147
{
108148
switch ($rulename) {
109149
case 'date_after':
150+
case 'date_on_or_after':
110151
case 'date_immutable':
111152
case 'datetime_immutable':
112153
case 'iso_date':

test/unit/Validation/StrictDateTest.php

Lines changed: 59 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ public function test_it_validates_date_immutable_instance($value, $expect)
7171
$this->assertSame($expect, StrictDate::date_immutable($value));
7272
}
7373

74-
public function provider_date_after_date()
74+
public function provider_date_before_after_invalid_inputs()
7575
{
7676
return [
7777
[['from' => NULL, 'to' => NULL], 'from', 'to', TRUE],
@@ -89,6 +89,28 @@ public function provider_date_after_date()
8989
'to',
9090
TRUE
9191
],
92+
];
93+
}
94+
95+
/**
96+
* @dataProvider provider_date_before_after_invalid_inputs
97+
*/
98+
public function test_date_compare_funcs_validate_invalid_input($data, $from_field, $to_field)
99+
{
100+
// This is so that an invalid date just says "invalid date" rather than also "must be after"
101+
$data = new \ArrayObject($data);
102+
$this->assertTrue(StrictDate::date_after($data, $from_field, $to_field), 'date_after');
103+
$this->assertTrue(
104+
StrictDate::date_on_or_after($data, $from_field, $to_field),
105+
'date_on_or_after'
106+
);
107+
}
108+
109+
public function provider_date_after_date()
110+
{
111+
return [
112+
// Invalid inputs all true as they should be caught by other rules
113+
// Simple > the first one
92114
[
93115
['a' => new \DateTimeImmutable, 'b' => new \DateTimeImmutable('-5 mins')],
94116
'a',
@@ -105,16 +127,47 @@ public function provider_date_after_date()
105127
}
106128

107129
/**
108-
* @dataProvider provider_date_after_date
130+
* @testWith ["", "-5 mins", false]
131+
* ["-5 mins", "", true]
109132
*/
110-
public function test_it_validates_date_after_date($data, $from_field, $to_field, $expect)
133+
public function test_it_validates_date_after_date($from, $to, $expect)
111134
{
112135
$this->assertSame(
113136
$expect,
114137
StrictDate::date_after(
115-
new \ArrayObject($data),
116-
$from_field,
117-
$to_field
138+
new \ArrayObject(
139+
[
140+
'from' => new \DateTimeImmutable($from),
141+
'to' => new \DateTimeImmutable($to)
142+
]
143+
),
144+
'from',
145+
'to'
146+
)
147+
);
148+
}
149+
150+
/**
151+
* @testWith ["2017-01-05 00:00:00", "2017-01-04 23:59:59", false]
152+
* ["2017-01-04 10:00:00", "2017-01-04 23:59:59", true]
153+
* ["2017-01-04 00:00:00", "2017-01-04 00:00:00", true]
154+
* ["2017-01-04 10:00:00", "2017-01-04 08:00:00", true]
155+
* ["2017-05-06 10:00:00", "2018-12-30 00:00:00", true]
156+
*
157+
*/
158+
public function test_it_validates_date_on_or_after_date($from, $to, $expect)
159+
{
160+
$this->assertSame(
161+
$expect,
162+
StrictDate::date_on_or_after(
163+
new \ArrayObject(
164+
[
165+
'from' => new \DateTimeImmutable($from),
166+
'to' => new \DateTimeImmutable($to)
167+
]
168+
),
169+
'from',
170+
'to'
118171
)
119172
);
120173
}

0 commit comments

Comments
 (0)