1<?php
2
3namespace Sabre\VObject\Property\ICalendar;
4
5use Sabre\VObject\Component\VCalendar;
6
7class DateTimeTest extends \PHPUnit_Framework_TestCase {
8
9    protected $vcal;
10
11    function setUp() {
12
13        $this->vcal = new VCalendar();
14
15    }
16
17    function testSetDateTime() {
18
19        $tz = new \DateTimeZone('Europe/Amsterdam');
20        $dt = new \DateTime('1985-07-04 01:30:00', $tz);
21        $dt->setTimeZone($tz);
22
23        $elem = $this->vcal->createProperty('DTSTART');
24        $elem->setDateTime($dt);
25
26        $this->assertEquals('19850704T013000', (string)$elem);
27        $this->assertEquals('Europe/Amsterdam', (string)$elem['TZID']);
28        $this->assertNull($elem['VALUE']);
29
30        $this->assertTrue($elem->hasTime());
31
32    }
33
34    function testSetDateTimeLOCAL() {
35
36        $tz = new \DateTimeZone('Europe/Amsterdam');
37        $dt = new \DateTime('1985-07-04 01:30:00', $tz);
38        $dt->setTimeZone($tz);
39
40        $elem = $this->vcal->createProperty('DTSTART');
41        $elem->setDateTime($dt, $isFloating = true);
42
43        $this->assertEquals('19850704T013000', (string)$elem);
44        $this->assertNull($elem['TZID']);
45
46        $this->assertTrue($elem->hasTime());
47    }
48
49    function testSetDateTimeUTC() {
50
51        $tz = new \DateTimeZone('GMT');
52        $dt = new \DateTime('1985-07-04 01:30:00', $tz);
53        $dt->setTimeZone($tz);
54
55        $elem = $this->vcal->createProperty('DTSTART');
56        $elem->setDateTime($dt);
57
58        $this->assertEquals('19850704T013000Z', (string)$elem);
59        $this->assertNull($elem['TZID']);
60
61        $this->assertTrue($elem->hasTime());
62    }
63
64    function testSetDateTimeFromUnixTimestamp() {
65
66        // When initialized from a Unix timestamp, the timezone is set to "+00:00".
67        $dt = new \DateTime('@489288600');
68
69        $elem = $this->vcal->createProperty('DTSTART');
70        $elem->setDateTime($dt);
71
72        $this->assertEquals('19850704T013000Z', (string)$elem);
73        $this->assertNull($elem['TZID']);
74
75        $this->assertTrue($elem->hasTime());
76    }
77
78    function testSetDateTimeLOCALTZ() {
79
80        $tz = new \DateTimeZone('Europe/Amsterdam');
81        $dt = new \DateTime('1985-07-04 01:30:00', $tz);
82        $dt->setTimeZone($tz);
83
84        $elem = $this->vcal->createProperty('DTSTART');
85        $elem->setDateTime($dt);
86
87        $this->assertEquals('19850704T013000', (string)$elem);
88        $this->assertEquals('Europe/Amsterdam', (string)$elem['TZID']);
89
90        $this->assertTrue($elem->hasTime());
91    }
92
93    function testSetDateTimeDATE() {
94
95        $tz = new \DateTimeZone('Europe/Amsterdam');
96        $dt = new \DateTime('1985-07-04 01:30:00', $tz);
97        $dt->setTimeZone($tz);
98
99        $elem = $this->vcal->createProperty('DTSTART');
100        $elem['VALUE'] = 'DATE';
101        $elem->setDateTime($dt);
102
103        $this->assertEquals('19850704', (string)$elem);
104        $this->assertNull($elem['TZID']);
105        $this->assertEquals('DATE', (string)$elem['VALUE']);
106
107        $this->assertFalse($elem->hasTime());
108    }
109
110    function testSetValue() {
111
112        $tz = new \DateTimeZone('Europe/Amsterdam');
113        $dt = new \DateTime('1985-07-04 01:30:00', $tz);
114        $dt->setTimeZone($tz);
115
116        $elem = $this->vcal->createProperty('DTSTART');
117        $elem->setValue($dt);
118
119        $this->assertEquals('19850704T013000', (string)$elem);
120        $this->assertEquals('Europe/Amsterdam', (string)$elem['TZID']);
121        $this->assertNull($elem['VALUE']);
122
123        $this->assertTrue($elem->hasTime());
124
125    }
126
127    function testSetValueArray() {
128
129        $tz = new \DateTimeZone('Europe/Amsterdam');
130        $dt1 = new \DateTime('1985-07-04 01:30:00', $tz);
131        $dt2 = new \DateTime('1985-07-04 02:30:00', $tz);
132        $dt1->setTimeZone($tz);
133        $dt2->setTimeZone($tz);
134
135        $elem = $this->vcal->createProperty('DTSTART');
136        $elem->setValue([$dt1, $dt2]);
137
138        $this->assertEquals('19850704T013000,19850704T023000', (string)$elem);
139        $this->assertEquals('Europe/Amsterdam', (string)$elem['TZID']);
140        $this->assertNull($elem['VALUE']);
141
142        $this->assertTrue($elem->hasTime());
143
144    }
145
146    function testSetParts() {
147
148        $tz = new \DateTimeZone('Europe/Amsterdam');
149        $dt1 = new \DateTime('1985-07-04 01:30:00', $tz);
150        $dt2 = new \DateTime('1985-07-04 02:30:00', $tz);
151        $dt1->setTimeZone($tz);
152        $dt2->setTimeZone($tz);
153
154        $elem = $this->vcal->createProperty('DTSTART');
155        $elem->setParts([$dt1, $dt2]);
156
157        $this->assertEquals('19850704T013000,19850704T023000', (string)$elem);
158        $this->assertEquals('Europe/Amsterdam', (string)$elem['TZID']);
159        $this->assertNull($elem['VALUE']);
160
161        $this->assertTrue($elem->hasTime());
162
163    }
164    function testSetPartsStrings() {
165
166        $dt1 = '19850704T013000Z';
167        $dt2 = '19850704T023000Z';
168
169        $elem = $this->vcal->createProperty('DTSTART');
170        $elem->setParts([$dt1, $dt2]);
171
172        $this->assertEquals('19850704T013000Z,19850704T023000Z', (string)$elem);
173        $this->assertNull($elem['VALUE']);
174
175        $this->assertTrue($elem->hasTime());
176
177    }
178
179
180    function testGetDateTimeCached() {
181
182        $tz = new \DateTimeZone('Europe/Amsterdam');
183        $dt = new \DateTimeImmutable('1985-07-04 01:30:00', $tz);
184        $dt->setTimeZone($tz);
185
186        $elem = $this->vcal->createProperty('DTSTART');
187        $elem->setDateTime($dt);
188
189        $this->assertEquals($elem->getDateTime(), $dt);
190
191    }
192
193    function testGetDateTimeDateNULL() {
194
195        $elem = $this->vcal->createProperty('DTSTART');
196        $dt = $elem->getDateTime();
197
198        $this->assertNull($dt);
199
200    }
201
202    function testGetDateTimeDateDATE() {
203
204        $elem = $this->vcal->createProperty('DTSTART', '19850704');
205        $dt = $elem->getDateTime();
206
207        $this->assertInstanceOf('DateTimeImmutable', $dt);
208        $this->assertEquals('1985-07-04 00:00:00', $dt->format('Y-m-d H:i:s'));
209
210    }
211
212    function testGetDateTimeDateDATEReferenceTimeZone() {
213
214        $elem = $this->vcal->createProperty('DTSTART', '19850704');
215
216        $tz = new \DateTimeZone('America/Toronto');
217        $dt = $elem->getDateTime($tz);
218        $dt = $dt->setTimeZone(new \DateTimeZone('UTC'));
219
220        $this->assertInstanceOf('DateTimeImmutable', $dt);
221        $this->assertEquals('1985-07-04 04:00:00', $dt->format('Y-m-d H:i:s'));
222
223    }
224
225    function testGetDateTimeDateFloating() {
226
227        $elem = $this->vcal->createProperty('DTSTART', '19850704T013000');
228        $dt = $elem->getDateTime();
229
230        $this->assertInstanceOf('DateTimeImmutable', $dt);
231        $this->assertEquals('1985-07-04 01:30:00', $dt->format('Y-m-d H:i:s'));
232
233    }
234
235    function testGetDateTimeDateFloatingReferenceTimeZone() {
236
237        $elem = $this->vcal->createProperty('DTSTART', '19850704T013000');
238
239        $tz = new \DateTimeZone('America/Toronto');
240        $dt = $elem->getDateTime($tz);
241        $dt = $dt->setTimeZone(new \DateTimeZone('UTC'));
242
243        $this->assertInstanceOf('DateTimeInterface', $dt);
244        $this->assertEquals('1985-07-04 05:30:00', $dt->format('Y-m-d H:i:s'));
245
246    }
247
248    function testGetDateTimeDateUTC() {
249
250        $elem = $this->vcal->createProperty('DTSTART', '19850704T013000Z');
251        $dt = $elem->getDateTime();
252
253        $this->assertInstanceOf('DateTimeImmutable', $dt);
254        $this->assertEquals('1985-07-04 01:30:00', $dt->format('Y-m-d H:i:s'));
255        $this->assertEquals('UTC', $dt->getTimeZone()->getName());
256
257    }
258
259    function testGetDateTimeDateLOCALTZ() {
260
261        $elem = $this->vcal->createProperty('DTSTART', '19850704T013000');
262        $elem['TZID'] = 'Europe/Amsterdam';
263
264        $dt = $elem->getDateTime();
265
266        $this->assertInstanceOf('DateTimeImmutable', $dt);
267        $this->assertEquals('1985-07-04 01:30:00', $dt->format('Y-m-d H:i:s'));
268        $this->assertEquals('Europe/Amsterdam', $dt->getTimeZone()->getName());
269
270    }
271
272    /**
273     * @expectedException \Sabre\VObject\InvalidDataException
274     */
275    function testGetDateTimeDateInvalid() {
276
277        $elem = $this->vcal->createProperty('DTSTART', 'bla');
278        $dt = $elem->getDateTime();
279
280    }
281
282    function testGetDateTimeWeirdTZ() {
283
284        $elem = $this->vcal->createProperty('DTSTART', '19850704T013000');
285        $elem['TZID'] = '/freeassociation.sourceforge.net/Tzfile/Europe/Amsterdam';
286
287
288        $event = $this->vcal->createComponent('VEVENT');
289        $event->add($elem);
290
291        $timezone = $this->vcal->createComponent('VTIMEZONE');
292        $timezone->TZID = '/freeassociation.sourceforge.net/Tzfile/Europe/Amsterdam';
293        $timezone->{'X-LIC-LOCATION'} = 'Europe/Amsterdam';
294
295        $this->vcal->add($event);
296        $this->vcal->add($timezone);
297
298        $dt = $elem->getDateTime();
299
300        $this->assertInstanceOf('DateTimeImmutable', $dt);
301        $this->assertEquals('1985-07-04 01:30:00', $dt->format('Y-m-d H:i:s'));
302        $this->assertEquals('Europe/Amsterdam', $dt->getTimeZone()->getName());
303
304    }
305
306    function testGetDateTimeBadTimeZone() {
307
308        $default = date_default_timezone_get();
309        date_default_timezone_set('Canada/Eastern');
310
311        $elem = $this->vcal->createProperty('DTSTART', '19850704T013000');
312        $elem['TZID'] = 'Moon';
313
314
315        $event = $this->vcal->createComponent('VEVENT');
316        $event->add($elem);
317
318        $timezone = $this->vcal->createComponent('VTIMEZONE');
319        $timezone->TZID = 'Moon';
320        $timezone->{'X-LIC-LOCATION'} = 'Moon';
321
322
323        $this->vcal->add($event);
324        $this->vcal->add($timezone);
325
326        $dt = $elem->getDateTime();
327
328        $this->assertInstanceOf('DateTimeImmutable', $dt);
329        $this->assertEquals('1985-07-04 01:30:00', $dt->format('Y-m-d H:i:s'));
330        $this->assertEquals('Canada/Eastern', $dt->getTimeZone()->getName());
331        date_default_timezone_set($default);
332
333    }
334
335    function testUpdateValueParameter() {
336
337        $dtStart = $this->vcal->createProperty('DTSTART', new \DateTime('2013-06-07 15:05:00'));
338        $dtStart['VALUE'] = 'DATE';
339
340        $this->assertEquals("DTSTART;VALUE=DATE:20130607\r\n", $dtStart->serialize());
341
342    }
343
344    function testValidate() {
345
346        $exDate = $this->vcal->createProperty('EXDATE', '-00011130T143000Z');
347        $messages = $exDate->validate();
348        $this->assertEquals(1, count($messages));
349        $this->assertEquals(3, $messages[0]['level']);
350
351    }
352
353    /**
354     * This issue was discovered on the sabredav mailing list.
355     */
356    function testCreateDatePropertyThroughAdd() {
357
358        $vcal = new VCalendar();
359        $vevent = $vcal->add('VEVENT');
360
361        $dtstart = $vevent->add(
362            'DTSTART',
363            new \DateTime('2014-03-07'),
364            ['VALUE' => 'DATE']
365        );
366
367        $this->assertEquals("DTSTART;VALUE=DATE:20140307\r\n", $dtstart->serialize());
368
369    }
370
371}
372