Completed
Pull Request — master (#6783)
by Ingo
08:19
created

DatetimeFieldTest::testTimezoneSetValueLocalised()   B

Complexity

Conditions 1
Paths 1

Size

Total Lines 24
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 16
nc 1
nop 0
dl 0
loc 24
rs 8.9713
c 0
b 0
f 0
1
<?php
2
3
namespace SilverStripe\Forms\Tests;
4
5
use SilverStripe\Dev\SapphireTest;
6
use SilverStripe\Control\Controller;
7
use SilverStripe\Forms\DatetimeField;
8
use SilverStripe\Forms\RequiredFields;
9
use SilverStripe\Forms\DateField;
10
use SilverStripe\Forms\Tests\DatetimeFieldTest\Model;
11
use SilverStripe\Forms\TimeField;
12
use SilverStripe\Forms\FieldList;
13
use SilverStripe\Forms\FormAction;
14
use SilverStripe\Forms\Form;
15
use SilverStripe\i18n\i18n;
16
use SilverStripe\ORM\FieldType\DBDatetime;
17
18
class DatetimeFieldTest extends SapphireTest
19
{
20
    protected $timezone = null;
21
22
    protected function setUp()
23
    {
24
        parent::setUp();
25
        i18n::set_locale('en_NZ');
26
        $this->timezone = date_default_timezone_get();
27
    }
28
29
    protected function tearDown()
30
    {
31
        date_default_timezone_set($this->timezone);
32
        parent::tearDown(); // TODO: Change the autogenerated stub
33
    }
34
35
    public function testFormSaveInto()
36
    {
37
        $dateTimeField = new DatetimeField('MyDatetime');
38
        $form = $this->getMockForm();
39
        $form->Fields()->push($dateTimeField);
40
41
        $dateTimeField->setSubmittedValue('2003-03-29T23:59:38');
42
        $validator = new RequiredFields();
43
        $this->assertTrue($dateTimeField->validate($validator));
44
        $m = new Model();
45
        $form->saveInto($m);
46
        $this->assertEquals('2003-03-29 23:59:38', $m->MyDatetime);
47
    }
48
49
    public function testFormSaveIntoLocalised()
50
    {
51
        $dateTimeField = new DatetimeField('MyDatetime');
52
        $dateTimeField
53
            ->setHTML5(false)
54
            ->setLocale('en_NZ');
55
56
        $form = $this->getMockForm();
57
        $form->Fields()->push($dateTimeField);
58
59
        // en_NZ standard format
60
        $dateTimeField->setSubmittedValue('29/03/2003 11:59:38 pm');
61
        $validator = new RequiredFields();
62
        $this->assertTrue($dateTimeField->validate($validator));
63
        $m = new Model();
64
        $form->saveInto($m);
65
        $this->assertEquals('2003-03-29 23:59:38', $m->MyDatetime);
66
    }
67
68
    public function testDataValue()
69
    {
70
        $f = new DatetimeField('Datetime');
71
        $this->assertEquals(null, $f->dataValue(), 'Empty field');
72
73
        $f = new DatetimeField('Datetime', null, '2003-03-29 23:59:38');
74
        $this->assertEquals('2003-03-29 23:59:38', $f->dataValue(), 'From date/time string');
75
    }
76
77
    public function testDataValueWithTimezone()
78
    {
79
        // Berlin and Auckland have 12h time difference in northern hemisphere winter
80
        date_default_timezone_set('Europe/Berlin');
81
82
        $f = new DatetimeField('Datetime');
83
        $f->setTimezone('Pacific/Auckland');
84
        $f->setSubmittedValue('2003-01-30T23:59:38'); // frontend timezone (Auckland)
85
        $this->assertEquals('2003-01-30 11:59:38', $f->dataValue()); // server timezone (Berlin)
86
    }
87
88
    public function testConstructorWithoutArgs()
89
    {
90
        $f = new DatetimeField('Datetime');
91
        $this->assertEquals($f->dataValue(), null);
92
    }
93
94
    public function testConstructorWithLocalizedDateSetsNullValue()
95
    {
96
        $f = new DatetimeField('Datetime', 'Datetime', '29/03/2003 23:59:38');
97
        $this->assertNull($f->Value());
98
    }
99
100
    public function testConstructorWithIsoDate()
101
    {
102
        // used by Form->loadDataFrom()
103
        $f = new DatetimeField('Datetime', 'Datetime', '2003-03-29 23:59:38');
104
        $this->assertEquals($f->dataValue(), '2003-03-29 23:59:38');
105
    }
106
107
    public function testSetValueWithDateTimeString()
108
    {
109
        $f = new DatetimeField('Datetime', 'Datetime');
110
        $f->setValue('2003-03-29 23:59:38');
111
        $this->assertEquals($f->dataValue(), '2003-03-29 23:59:38', 'Accepts ISO');
112
113
        $f = new DatetimeField('Datetime', 'Datetime');
114
        $f->setValue('2003-03-29T23:59:38');
115
        $this->assertNull($f->dataValue(), 'Rejects normalised ISO');
116
    }
117
118
    public function testSubmittedValue()
119
    {
120
        $datetimeField = new DatetimeField('Datetime', 'Datetime');
121
        $datetimeField->setSubmittedValue('2003-03-29 23:00:00');
122
        $this->assertEquals($datetimeField->dataValue(), '2003-03-29 23:00:00');
123
124
        $datetimeField = new DatetimeField('Datetime', 'Datetime');
125
        $datetimeField->setSubmittedValue('2003-03-29T23:00:00');
126
        $this->assertEquals($datetimeField->dataValue(), '2003-03-29 23:00:00', 'Normalised ISO');
127
    }
128
129
    public function testSetValueWithLocalised()
130
    {
131
        $datetimeField = new DatetimeField('Datetime', 'Datetime');
132
133
        $datetimeField
134
            ->setHTML5(false)
135
            ->setLocale('en_NZ');
136
137
        $datetimeField->setSubmittedValue('29/03/2003 11:00:00 pm');
138
        $this->assertEquals($datetimeField->dataValue(), '2003-03-29 23:00:00');
139
140
        // Some localisation packages exclude the ',' in default medium format
141
        $this->assertRegExp(
142
            '#29/03/2003(,)? 11:00:00 (PM|pm)#',
143
            $datetimeField->Value(),
144
            'User value is formatted, and in user timezone'
145
        );
146
    }
147
148
    public function testValidate()
149
    {
150
        $f = new DatetimeField('Datetime', 'Datetime', '2003-03-29 23:59:38');
151
        $this->assertTrue($f->validate(new RequiredFields()));
152
153
        $f = new DatetimeField('Datetime', 'Datetime', '2003-03-29T23:59:38');
154
        $this->assertFalse($f->validate(new RequiredFields()), 'Normalised ISO');
155
156
        $f = new DatetimeField('Datetime', 'Datetime', '2003-03-29');
157
        $this->assertFalse($f->validate(new RequiredFields()), 'Leaving out time');
158
159
        $f = (new DatetimeField('Datetime', 'Datetime'))
160
            ->setSubmittedValue('2003-03-29T00:00');
161
        $this->assertTrue($f->validate(new RequiredFields()), 'Leaving out seconds (like many browsers)');
162
163
        $f = new DatetimeField('Datetime', 'Datetime', 'wrong');
164
        $this->assertFalse($f->validate(new RequiredFields()));
165
    }
166
167
    public function testSetMinDate()
168
    {
169
        $f = (new DatetimeField('Datetime'))->setMinDatetime('2009-03-31T23:00:00');
170
        $this->assertEquals($f->getMinDatetime(), '2009-03-31 23:00:00', 'Retains ISO');
171
172
        $f = (new DatetimeField('Datetime'))->setMinDatetime('2009-03-31 23:00:00');
173
        $this->assertEquals($f->getMinDatetime(), '2009-03-31 23:00:00', 'Converts normalised ISO to ISO');
174
175
        $f = (new DatetimeField('Datetime'))->setMinDatetime('invalid');
176
        $this->assertNull($f->getMinDatetime(), 'Ignores invalid values');
177
    }
178
179
    public function testSetMaxDate()
180
    {
181
        $f = (new DatetimeField('Datetime'))->setMaxDatetime('2009-03-31T23:00:00');
182
        $this->assertEquals($f->getMaxDatetime(), '2009-03-31 23:00:00', 'Retains ISO');
183
184
        $f = (new DatetimeField('Datetime'))->setMaxDatetime('2009-03-31 23:00:00');
185
        $this->assertEquals($f->getMaxDatetime(), '2009-03-31 23:00:00', 'Converts normalised ISO to ISO');
186
187
        $f = (new DatetimeField('Datetime'))->setMaxDatetime('invalid');
188
        $this->assertNull($f->getMaxDatetime(), 'Ignores invalid values');
189
    }
190
191
    public function testValidateMinDate()
192
    {
193
        $dateField = new DatetimeField('Datetime');
194
        $dateField->setMinDatetime('2009-03-31 23:00:00');
195
        $dateField->setValue('2009-03-31 23:00:01');
196
        $this->assertTrue($dateField->validate(new RequiredFields()), 'Time above min datetime');
197
198
        $dateField = new DatetimeField('Datetime');
199
        $dateField->setMinDatetime('2009-03-31 23:00:00');
200
        $dateField->setValue('2009-03-31 22:00:00');
201
        $this->assertFalse($dateField->validate(new RequiredFields()), 'Time below min datetime');
202
203
        $dateField = new DatetimeField('Datetime');
204
        $dateField->setMinDatetime('2009-03-31 23:00:00');
205
        $dateField->setValue('2009-03-31 23:00:00');
206
        $this->assertTrue($dateField->validate(new RequiredFields()), 'Date and time matching min datetime');
207
208
        $dateField = new DatetimeField('Datetime');
209
        $dateField->setMinDatetime('2009-03-31 23:00:00');
210
        $dateField->setValue('2008-03-31 23:00:00');
211
        $this->assertFalse($dateField->validate(new RequiredFields()), 'Date below min datetime');
212
    }
213
214
    public function testValidateMinDateWithSubmittedValueAndTimezone()
215
    {
216
        // Berlin and Auckland have 12h time difference in northern hemisphere winter
217
        date_default_timezone_set('Europe/Berlin');
218
219
        $dateField = new DatetimeField('Datetime');
220
        $dateField->setTimezone('Pacific/Auckland');
221
        $dateField->setMinDatetime('2009-01-30 23:00:00'); // server timezone (Berlin)
222
        $dateField->setSubmittedValue('2009-01-31T11:00:01'); // frontend timezone (Auckland)
223
        $this->assertTrue($dateField->validate(new RequiredFields()), 'Time above min datetime');
224
225
        $dateField = new DatetimeField('Datetime');
226
        $dateField->setTimezone('Pacific/Auckland');
227
        $dateField->setMinDatetime('2009-01-30 23:00:00');
228
        $dateField->setSubmittedValue('2009-01-31T10:00:00');
229
        $this->assertFalse($dateField->validate(new RequiredFields()), 'Time below min datetime');
230
231
        $dateField = new DatetimeField('Datetime');
232
        $dateField->setTimezone('Pacific/Auckland');
233
        $dateField->setMinDatetime('2009-01-30 23:00:00');
234
        $dateField->setSubmittedValue('2009-01-31T11:00:00');
235
        $this->assertTrue($dateField->validate(new RequiredFields()), 'Date and time matching min datetime');
236
237
        $dateField = new DatetimeField('Datetime');
238
        $dateField->setTimezone('Pacific/Auckland');
239
        $dateField->setMinDatetime('2009-01-30 23:00:00');
240
        $dateField->setSubmittedValue('2008-01-31T11:00:00');
241
        $this->assertFalse($dateField->validate(new RequiredFields()), 'Date below min datetime');
242
    }
243
244
    public function testValidateMinDateStrtotime()
245
    {
246
        $f = new DatetimeField('Datetime');
247
        $f->setMinDatetime('-7 days');
248
        $f->setValue(strftime('%Y-%m-%d %T', strtotime('-8 days', DBDatetime::now()->getTimestamp())));
249
        $this->assertFalse($f->validate(new RequiredFields()), 'Date below min datetime, with strtotime');
250
251
        $f = new DatetimeField('Datetime');
252
        $f->setMinDatetime('-7 days');
253
        $f->setValue(strftime('%Y-%m-%d %T', strtotime('-7 days', DBDatetime::now()->getTimestamp())));
254
        $this->assertTrue($f->validate(new RequiredFields()), 'Date matching min datetime, with strtotime');
255
    }
256
257
    public function testValidateMaxDateStrtotime()
258
    {
259
        $f = new DatetimeField('Datetime');
260
        $f->setMaxDatetime('7 days');
261
        $f->setValue(strftime('%Y-%m-%d %T', strtotime('8 days', DBDatetime::now()->getTimestamp())));
262
        $this->assertFalse($f->validate(new RequiredFields()), 'Date above max date, with strtotime');
263
264
        $f = new DatetimeField('Datetime');
265
        $f->setMaxDatetime('7 days');
266
        $f->setValue(strftime('%Y-%m-%d %T', strtotime('7 days', DBDatetime::now()->getTimestamp())));
267
        $this->assertTrue($f->validate(new RequiredFields()), 'Date matching max date, with strtotime');
268
    }
269
270
    public function testValidateMaxDate()
271
    {
272
        $f = new DatetimeField('Datetime');
273
        $f->setMaxDatetime('2009-03-31 23:00:00');
274
        $f->setValue('2009-03-31 22:00:00');
275
        $this->assertTrue($f->validate(new RequiredFields()), 'Time below max datetime');
276
277
        $f = new DatetimeField('Datetime');
278
        $f->setMaxDatetime('2009-03-31 23:00:00');
279
        $f->setValue('2010-03-31 23:00:01');
280
        $this->assertFalse($f->validate(new RequiredFields()), 'Time above max datetime');
281
282
        $f = new DatetimeField('Datetime');
283
        $f->setMaxDatetime('2009-03-31 23:00:00');
284
        $f->setValue('2009-03-31 23:00:00');
285
        $this->assertTrue($f->validate(new RequiredFields()), 'Date and time matching max datetime');
286
287
        $f = new DatetimeField('Datetime');
288
        $f->setMaxDatetime('2009-03-31 23:00:00');
289
        $f->setValue('2010-03-31 23:00:00');
290
        $this->assertFalse($f->validate(new RequiredFields()), 'Date above max datetime');
291
    }
292
293
    public function testValidateMaxDateWithSubmittedValueAndTimezone()
294
    {
295
        // Berlin and Auckland have 12h time difference in northern hemisphere winter
296
        date_default_timezone_set('Europe/Berlin');
297
298
        $f = new DatetimeField('Datetime');
299
        $f->setTimezone('Pacific/Auckland');
300
        $f->setMaxDatetime('2009-01-31 23:00:00'); // server timezone (Berlin)
301
        $f->setSubmittedValue('2009-01-31T10:00:00'); // frontend timezone (Auckland)
302
        $this->assertTrue($f->validate(new RequiredFields()), 'Time below max datetime');
303
304
        $f = new DatetimeField('Datetime');
305
        $f->setTimezone('Pacific/Auckland');
306
        $f->setMaxDatetime('2009-01-31 23:00:00');
307
        $f->setSubmittedValue('2010-01-31T11:00:01');
308
        $this->assertFalse($f->validate(new RequiredFields()), 'Time above max datetime');
309
310
        $f = new DatetimeField('Datetime');
311
        $f->setTimezone('Pacific/Auckland');
312
        $f->setMaxDatetime('2009-01-31 23:00:00');
313
        $f->setSubmittedValue('2009-01-31T11:00:00');
314
        $this->assertTrue($f->validate(new RequiredFields()), 'Date and time matching max datetime');
315
316
        $f = new DatetimeField('Datetime');
317
        $f->setTimezone('Pacific/Auckland');
318
        $f->setMaxDatetime('2009-01-31 23:00:00');
319
        $f->setSubmittedValue('2010-01-31T11:00:00');
320
        $this->assertFalse($f->validate(new RequiredFields()), 'Date above max datetime');
321
    }
322
323
    public function testTimezoneSetValueLocalised()
324
    {
325
        date_default_timezone_set('Europe/Berlin');
326
        // Berlin and Auckland have 12h time difference in northern hemisphere winter
327
        $datetimeField = new DatetimeField('Datetime', 'Datetime');
328
329
        $datetimeField
330
            ->setHTML5(false)
331
            ->setDatetimeFormat('dd/MM/y HH:mm:ss');
332
333
        $datetimeField->setTimezone('Pacific/Auckland');
334
        $datetimeField->setValue('2003-12-24 23:59:59');
335
        $this->assertEquals(
336
            '25/12/2003 11:59:59',
337
            $datetimeField->Value(),
338
            'User value is formatted, and in user timezone'
339
        );
340
341
        $this->assertEquals(
342
            '2003-12-24 23:59:59',
343
            $datetimeField->dataValue(),
344
            'Data value is in ISO format, and in server timezone'
345
        );
346
    }
347
348
    public function testTimezoneSetValueWithHtml5()
349
    {
350
        date_default_timezone_set('Europe/Berlin');
351
        // Berlin and Auckland have 12h time difference in northern hemisphere winter
352
        $datetimeField = new DatetimeField('Datetime', 'Datetime');
353
354
        $datetimeField->setTimezone('Pacific/Auckland');
355
        $datetimeField->setValue('2003-12-24 23:59:59');
356
        $this->assertEquals(
357
            '2003-12-25T11:59:59',
358
            $datetimeField->Value(),
359
            'User value is in normalised ISO format and in user timezone'
360
        );
361
362
        $this->assertEquals(
363
            '2003-12-24 23:59:59',
364
            $datetimeField->dataValue(),
365
            'Data value is in ISO format, and in server timezone'
366
        );
367
    }
368
369
    public function testTimezoneSetSubmittedValueLocalised()
370
    {
371
        date_default_timezone_set('Europe/Berlin');
372
        // Berlin and Auckland have 12h time difference in northern hemisphere summer, but Berlin and Moscow only 2h.
373
        $datetimeField = new DatetimeField('Datetime', 'Datetime');
374
375
        $datetimeField
376
            ->setHTML5(false)
377
            ->setLocale('en_NZ');
378
379
        $datetimeField->setTimezone('Europe/Moscow');
380
        // pass in default format, at user time (Moscow)
381
        $datetimeField->setSubmittedValue('24/06/2003 11:59:59 pm');
382
        $this->assertTrue($datetimeField->validate(new RequiredFields()));
383
        $this->assertEquals('2003-06-24 21:59:59', $datetimeField->dataValue(), 'Data value matches server timezone');
384
    }
385
386
    public function testGetName()
387
    {
388
        $field = new DatetimeField('Datetime');
389
390
        $this->assertEquals('Datetime', $field->getName());
391
    }
392
393
    public function testSetName()
394
    {
395
        $field = new DatetimeField('Datetime', 'Datetime');
396
        $field->setName('CustomDatetime');
397
        $this->assertEquals('CustomDatetime', $field->getName());
398
    }
399
400
    public function testSchemaDataDefaultsIncludesMinMax()
401
    {
402
        $field = new DatetimeField('Datetime');
403
        $field->setMinDatetime('2009-03-31 23:00:00');
404
        $field->setMaxDatetime('2010-03-31 23:00:00');
405
        $defaults = $field->getSchemaDataDefaults();
406
        $this->assertEquals($defaults['data']['min'], '2009-03-31T23:00:00');
407
        $this->assertEquals($defaults['data']['max'], '2010-03-31T23:00:00');
408
    }
409
410
    public function testSchemaDataDefaultsAdjustsMinMaxToTimezone()
411
    {
412
        date_default_timezone_set('Europe/Berlin');
413
        // Berlin and Auckland have 12h time difference in northern hemisphere summer, but Berlin and Moscow only 2h.
414
415
        $field = new DatetimeField('Datetime');
416
        $field->setTimezone('Pacific/Auckland');
417
        $field->setMinDatetime('2009-01-31 11:00:00'); // server timezone
418
        $field->setMaxDatetime('2010-01-31 11:00:00'); // server timezone
419
        $defaults = $field->getSchemaDataDefaults();
420
        $this->assertEquals($defaults['data']['min'], '2009-01-31T23:00:00'); // frontend timezone
421
        $this->assertEquals($defaults['data']['max'], '2010-01-31T23:00:00'); // frontend timezone
422
    }
423
424
    public function testAttributesIncludesMinMax()
425
    {
426
        $field = new DatetimeField('Datetime');
427
        $field->setMinDatetime('2009-03-31 23:00:00');
428
        $field->setMaxDatetime('2010-03-31 23:00:00');
429
        $attrs = $field->getAttributes();
430
        $this->assertEquals($attrs['min'], '2009-03-31T23:00:00');
431
        $this->assertEquals($attrs['max'], '2010-03-31T23:00:00');
432
    }
433
434
    public function testAttributesAdjustsMinMaxToTimezone()
435
    {
436
        date_default_timezone_set('Europe/Berlin');
437
        // Berlin and Auckland have 12h time difference in northern hemisphere summer, but Berlin and Moscow only 2h.
438
439
        $field = new DatetimeField('Datetime');
440
        $field->setTimezone('Pacific/Auckland');
441
        $field->setMinDatetime('2009-01-31 11:00:00'); // server timezone
442
        $field->setMaxDatetime('2010-01-31 11:00:00'); // server timezone
443
        $attrs = $field->getAttributes();
444
        $this->assertEquals($attrs['min'], '2009-01-31T23:00:00'); // frontend timezone
445
        $this->assertEquals($attrs['max'], '2010-01-31T23:00:00'); // frontend timezone
446
    }
447
448
    protected function getMockForm()
449
    {
450
        /** @skipUpgrade */
451
        return new Form(
452
            new Controller(),
453
            'Form',
454
            new FieldList(),
455
            new FieldList(
456
                new FormAction('doSubmit')
457
            )
458
        );
459
    }
460
}
461