Completed
Push — master ( d8776d...afe412 )
by Robbie
46s queued 25s
created

DBDateTest::restoreNotices()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 0
dl 0
loc 4
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace SilverStripe\ORM\Tests;
4
5
use PHPUnit\Framework\Error\Notice;
6
use SilverStripe\Dev\SapphireTest;
7
use SilverStripe\i18n\i18n;
8
use SilverStripe\ORM\FieldType\DBDatetime;
9
use SilverStripe\ORM\FieldType\DBField;
10
11
/**
12
 * @skipUpgrade
13
 */
14
class DBDateTest extends SapphireTest
15
{
16
    protected $oldError = null;
17
18
    protected function setUp() : void
19
    {
20
        parent::setUp();
21
        $this->oldError = error_reporting();
22
        // Validate setup
23
        assert(date_default_timezone_get() === 'UTC');
24
        i18n::set_locale('en_NZ');
25
    }
26
27
    public function testNiceDate()
28
    {
29
        $this->assertEquals(
30
            '31/03/2008',
31
            DBField::create_field('Date', 1206968400)->Nice(),
0 ignored issues
show
Bug introduced by
The method Nice() does not exist on SilverStripe\ORM\FieldType\DBField. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

31
            DBField::create_field('Date', 1206968400)->/** @scrutinizer ignore-call */ Nice(),
Loading history...
32
            "Date->Nice() works with timestamp integers"
33
        );
34
        $this->assertEquals(
35
            '30/03/2008',
36
            DBField::create_field('Date', 1206882000)->Nice(),
37
            "Date->Nice() works with timestamp integers"
38
        );
39
        $this->assertEquals(
40
            '31/03/2008',
41
            DBField::create_field('Date', '1206968400')->Nice(),
42
            "Date->Nice() works with timestamp strings"
43
        );
44
        $this->assertEquals(
45
            '30/03/2008',
46
            DBField::create_field('Date', '1206882000')->Nice(),
47
            "Date->Nice() works with timestamp strings"
48
        );
49
        $this->assertEquals(
50
            '4/03/2003',
51
            DBField::create_field('Date', '4.3.2003')->Nice(),
52
            "Date->Nice() works with D.M.YYYY format"
53
        );
54
        $this->assertEquals(
55
            '4/03/2003',
56
            DBField::create_field('Date', '04.03.2003')->Nice(),
57
            "Date->Nice() works with DD.MM.YYYY format"
58
        );
59
        $this->assertEquals(
60
            '4/03/2003',
61
            DBField::create_field('Date', '2003-3-4')->Nice(),
62
            "Date->Nice() works with YYYY-M-D format"
63
        );
64
        $this->assertEquals(
65
            '4/03/2003',
66
            DBField::create_field('Date', '2003-03-04')->Nice(),
67
            "Date->Nice() works with YYYY-MM-DD format"
68
        );
69
    }
70
71
    public function testMDYConversion()
72
    {
73
        $this->expectException(\InvalidArgumentException::class);
74
        $this->expectExceptionMessage('Invalid date: \'3/16/2003\'. Use y-MM-dd to prevent this error.');
75
        DBField::create_field('Date', '3/16/2003');
76
    }
77
78
    public function testY2kCorrection()
79
    {
80
        $this->expectException(\InvalidArgumentException::class);
81
        $this->expectExceptionMessage('Invalid date: \'03-03-04\'. Use y-MM-dd to prevent this error.');
82
        DBField::create_field('Date', '03-03-04');
83
    }
84
85
    public function testInvertedYearCorrection()
86
    {
87
        // iso8601 expects year first, but support year last
88
        $this->assertEquals(
89
            '4/03/2003',
90
            DBField::create_field('Date', '04-03-2003')->Nice(),
91
            "Date->Nice() works with DD-MM-YYYY format"
92
        );
93
    }
94
95
    public function testYear()
96
    {
97
        $this->assertEquals(
98
            '2008',
99
            DBField::create_field('Date', 1206968400)->Year(),
0 ignored issues
show
Bug introduced by
The method Year() does not exist on SilverStripe\ORM\FieldType\DBField. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

99
            DBField::create_field('Date', 1206968400)->/** @scrutinizer ignore-call */ Year(),
Loading history...
100
            "Date->Year() works with timestamp integers"
101
        );
102
    }
103
104
    public function testDayOfWeek()
105
    {
106
        $this->assertEquals(
107
            'Monday',
108
            DBField::create_field('Date', 1206968400)->DayOfWeek(),
0 ignored issues
show
Bug introduced by
The method DayOfWeek() does not exist on SilverStripe\ORM\FieldType\DBField. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

108
            DBField::create_field('Date', 1206968400)->/** @scrutinizer ignore-call */ DayOfWeek(),
Loading history...
109
            "Date->Day() works with timestamp integers"
110
        );
111
    }
112
113
    public function testMonth()
114
    {
115
        $this->assertEquals(
116
            'March',
117
            DBField::create_field('Date', 1206968400)->Month(),
0 ignored issues
show
Bug introduced by
The method Month() does not exist on SilverStripe\ORM\FieldType\DBField. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

117
            DBField::create_field('Date', 1206968400)->/** @scrutinizer ignore-call */ Month(),
Loading history...
118
            "Date->Month() works with timestamp integers"
119
        );
120
    }
121
122
    public function testShortMonth()
123
    {
124
        $this->assertEquals(
125
            'Mar',
126
            DBField::create_field('Date', 1206968400)->ShortMonth(),
0 ignored issues
show
Bug introduced by
The method ShortMonth() does not exist on SilverStripe\ORM\FieldType\DBField. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

126
            DBField::create_field('Date', 1206968400)->/** @scrutinizer ignore-call */ ShortMonth(),
Loading history...
127
            "Date->ShortMonth() works with timestamp integers"
128
        );
129
    }
130
131
    public function testLongDate()
132
    {
133
        $this->assertEquals(
134
            '31 March 2008',
135
            DBField::create_field('Date', 1206968400)->Long(),
0 ignored issues
show
Bug introduced by
The method Long() does not exist on SilverStripe\ORM\FieldType\DBField. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

135
            DBField::create_field('Date', 1206968400)->/** @scrutinizer ignore-call */ Long(),
Loading history...
136
            "Date->Long() works with numeric timestamp"
137
        );
138
        $this->assertEquals(
139
            '31 March 2008',
140
            DBField::create_field('Date', '1206968400')->Long(),
141
            "Date->Long() works with string timestamp"
142
        );
143
        $this->assertEquals(
144
            '30 March 2008',
145
            DBField::create_field('Date', 1206882000)->Long(),
146
            "Date->Long() works with numeric timestamp"
147
        );
148
        $this->assertEquals(
149
            '30 March 2008',
150
            DBField::create_field('Date', '1206882000')->Long(),
151
            "Date->Long() works with numeric timestamp"
152
        );
153
        $this->assertEquals(
154
            '3 April 2003',
155
            DBField::create_field('Date', '2003-4-3')->Long(),
156
            "Date->Long() works with YYYY-M-D"
157
        );
158
        $this->assertEquals(
159
            '3 April 2003',
160
            DBField::create_field('Date', '3.4.2003')->Long(),
161
            "Date->Long() works with D.M.YYYY"
162
        );
163
    }
164
165
    public function testFull()
166
    {
167
        $this->assertEquals(
168
            'Monday, 31 March 2008',
169
            DBField::create_field('Date', 1206968400)->Full(),
0 ignored issues
show
Bug introduced by
The method Full() does not exist on SilverStripe\ORM\FieldType\DBField. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

169
            DBField::create_field('Date', 1206968400)->/** @scrutinizer ignore-call */ Full(),
Loading history...
170
            "Date->Full() works with timestamp integers"
171
        );
172
    }
173
174
    public function testSetNullAndZeroValues()
175
    {
176
        $date = DBField::create_field('Date', '');
177
        $this->assertNull($date->getValue(), 'Empty string evaluates to NULL');
178
179
        $date = DBField::create_field('Date', null);
180
        $this->assertNull($date->getValue(), 'NULL is set as NULL');
181
182
        $date = DBField::create_field('Date', false);
183
        $this->assertNull($date->getValue(), 'Boolean FALSE evaluates to NULL');
184
185
        $date = DBField::create_field('Date', array());
186
        $this->assertNull($date->getValue(), 'Empty array evaluates to NULL');
187
188
        $date = DBField::create_field('Date', '0');
189
        $this->assertEquals('1970-01-01', $date->getValue(), 'Zero is UNIX epoch date');
190
191
        $date = DBField::create_field('Date', 0);
192
        $this->assertEquals('1970-01-01', $date->getValue(), 'Zero is UNIX epoch date');
193
194
        $date = DBField::create_field('Date', '0000-00-00 00:00:00');
195
        $this->assertNull($date->getValue(), '0000-00-00 00:00:00 is set as NULL');
196
197
        $date = DBField::create_field('Date', '00/00/0000');
198
        $this->assertNull($date->getValue(), '00/00/0000 is set as NULL');
199
    }
200
201
    public function testDayOfMonth()
202
    {
203
        $date = DBField::create_field('Date', '2000-10-10');
204
        $this->assertEquals('10', $date->DayOfMonth());
0 ignored issues
show
Bug introduced by
The method DayOfMonth() does not exist on SilverStripe\ORM\FieldType\DBField. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

204
        $this->assertEquals('10', $date->/** @scrutinizer ignore-call */ DayOfMonth());
Loading history...
205
        $this->assertEquals('10th', $date->DayOfMonth(true));
206
207
        $range = $date->RangeString(DBField::create_field('Date', '2000-10-20'));
0 ignored issues
show
Bug introduced by
The method RangeString() does not exist on SilverStripe\ORM\FieldType\DBField. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

207
        /** @scrutinizer ignore-call */ 
208
        $range = $date->RangeString(DBField::create_field('Date', '2000-10-20'));
Loading history...
208
        $this->assertEquals('10 - 20 Oct 2000', $range);
209
        $range = $date->RangeString(DBField::create_field('Date', '2000-10-20'), true);
210
        $this->assertEquals('10th - 20th Oct 2000', $range);
211
    }
212
213
    public function testFormatReplacesOrdinals()
214
    {
215
        $this->assertEquals(
216
            '20th October 2000',
217
            DBField::create_field('Date', '2000-10-20')->Format('{o} MMMM YYYY'),
0 ignored issues
show
Bug introduced by
The method Format() does not exist on SilverStripe\ORM\FieldType\DBField. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

217
            DBField::create_field('Date', '2000-10-20')->/** @scrutinizer ignore-call */ Format('{o} MMMM YYYY'),
Loading history...
218
            'Ordinal day of month was not injected'
219
        );
220
221
        $this->assertEquals(
222
            '20th is the 20th day of the month',
223
            DBField::create_field('Date', '2000-10-20')->Format("{o} 'is the' {o} 'day of the month'"),
224
            'Failed to inject multiple ordinal values into one string'
225
        );
226
    }
227
228
    public function testExtendedDates()
229
    {
230
        $date = DBField::create_field('Date', '1800-10-10');
231
        $this->assertEquals('10 Oct 1800', $date->Format('dd MMM y'));
232
233
        // Note: Fails around 1500 or older
234
        $date = DBField::create_field('Date', '1600-10-10');
235
        $this->assertEquals('10 Oct 1600', $date->Format('dd MMM y'));
236
237
        $date = DBField::create_field('Date', '3000-4-3');
238
        $this->assertEquals('03 Apr 3000', $date->Format('dd MMM y'));
239
    }
240
241
    public function testAgoInPast()
242
    {
243
        DBDatetime::set_mock_now('2000-12-31 12:00:00');
244
245
        $this->assertEquals(
246
            '1 month ago',
247
            DBField::create_field('Date', '2000-11-26')->Ago(true, 1),
0 ignored issues
show
Bug introduced by
The method Ago() does not exist on SilverStripe\ORM\FieldType\DBField. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

247
            DBField::create_field('Date', '2000-11-26')->/** @scrutinizer ignore-call */ Ago(true, 1),
Loading history...
248
            'Past match on days, less than two months, lowest significance'
249
        );
250
251
        $this->assertEquals(
252
            '50 days ago', // Rounded from 49.5 days up
253
            DBField::create_field('Date', '2000-11-12')->Ago(),
254
            'Past match on days, less than two months'
255
        );
256
257
        $this->assertEquals(
258
            '2 months ago',
259
            DBField::create_field('Date', '2000-10-27')->Ago(),
260
            'Past match on days, over two months'
261
        );
262
263
        $this->assertEquals(
264
            '66 days ago', // rounded from 65.5 days up
265
            DBField::create_field('Date', '2000-10-27')->Ago(true, 3),
266
            'Past match on days, over two months, significance of 3'
267
        );
268
269
        $this->assertEquals(
270
            '10 years ago',
271
            DBField::create_field('Date', '1990-12-31')->Ago(),
272
            'Exact past match on years'
273
        );
274
275
        $this->assertEquals(
276
            '10 years ago',
277
            DBField::create_field('Date', '1990-12-30')->Ago(),
278
            'Approximate past match on years'
279
        );
280
281
        $this->assertEquals(
282
            '1 year ago',
283
            DBField::create_field('Date', '1999-12-30')->Ago(true, 1),
284
            'Approximate past match in singular, lowest significance'
285
        );
286
287
        $this->assertEquals(
288
            '12 months ago',
289
            DBField::create_field('Date', '1999-12-30')->Ago(),
290
            'Approximate past match in singular'
291
        );
292
293
        DBDatetime::clear_mock_now();
294
    }
295
296
    public function testAgoInFuture()
297
    {
298
        DBDatetime::set_mock_now('2000-12-31 00:00:00');
299
300
        $this->assertEquals(
301
            'in 10 years',
302
            DBField::create_field('Date', '2010-12-31')->Ago(),
303
            'Exact past match on years'
304
        );
305
306
        $this->assertEquals(
307
            'in 1 day',
308
            DBField::create_field('Date', '2001-01-01')->Ago(true, 1),
309
            'Approximate past match on minutes'
310
        );
311
312
        $this->assertEquals(
313
            'in 24 hours',
314
            DBField::create_field('Date', '2001-01-01')->Ago(),
315
            'Approximate past match on minutes'
316
        );
317
318
        DBDatetime::clear_mock_now();
319
    }
320
321
    public function testRfc3999()
322
    {
323
        // Dates should be formatted as: 2018-01-24T14:05:53+00:00
324
        $date = DBField::create_field('Date', '2010-12-31');
325
        $this->assertEquals('2010-12-31T00:00:00+00:00', $date->Rfc3339());
0 ignored issues
show
Bug introduced by
The method Rfc3339() does not exist on SilverStripe\ORM\FieldType\DBField. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

325
        $this->assertEquals('2010-12-31T00:00:00+00:00', $date->/** @scrutinizer ignore-call */ Rfc3339());
Loading history...
326
    }
327
328
    /**
329
     * @param string $adjustment
330
     * @param string $expected
331
     * @dataProvider modifyProvider
332
     */
333
    public function testModify($adjustment, $expected)
334
    {
335
        /** @var DBDate $dateField */
336
        $dateField = DBField::create_field('Date', '2019-03-03');
337
        $result = $dateField->modify($adjustment)->URLDate();
338
        $this->assertSame($expected, $result);
339
    }
340
341
    /**
342
     * @return array[]
343
     */
344
    public function modifyProvider()
345
    {
346
        return [
347
            ['+1 day', '2019-03-04'],
348
            ['-1 day', '2019-03-02'],
349
            ['+24 hours', '2019-03-04'],
350
            ['-24 hours', '2019-03-02'],
351
            ['+2 weeks', '2019-03-17'],
352
            ['-2 weeks', '2019-02-17'],
353
            ['+2 years', '2021-03-03'],
354
            ['-2 years', '2017-03-03'],
355
        ];
356
    }
357
}
358