1<?php
2
3namespace Sabre\VObject\Property\VCard;
4
5use PHPUnit\Framework\TestCase;
6use Sabre\VObject;
7use Sabre\VObject\Reader;
8
9class DateAndOrTimeTest extends TestCase
10{
11    /**
12     * @dataProvider dates
13     */
14    public function testGetJsonValue($input, $output)
15    {
16        $vcard = new VObject\Component\VCard();
17        $prop = $vcard->createProperty('BDAY', $input);
18
19        $this->assertEquals([$output], $prop->getJsonValue());
20    }
21
22    public function dates()
23    {
24        return [
25            [
26                '19961022T140000',
27                '1996-10-22T14:00:00',
28            ],
29            [
30                '--1022T1400',
31                '--10-22T14:00',
32            ],
33            [
34                '---22T14',
35                '---22T14',
36            ],
37            [
38                '19850412',
39                '1985-04-12',
40            ],
41            [
42                '1985-04',
43                '1985-04',
44            ],
45            [
46                '1985',
47                '1985',
48            ],
49            [
50                '--0412',
51                '--04-12',
52            ],
53            [
54                'T102200',
55                'T10:22:00',
56            ],
57            [
58                'T1022',
59                'T10:22',
60            ],
61            [
62                'T10',
63                'T10',
64            ],
65            [
66                'T-2200',
67                'T-22:00',
68            ],
69            [
70                'T102200Z',
71                'T10:22:00Z',
72            ],
73            [
74                'T102200-0800',
75                'T10:22:00-0800',
76            ],
77            [
78                'T--00',
79                'T--00',
80            ],
81        ];
82    }
83
84    public function testSetParts()
85    {
86        $vcard = new VObject\Component\VCard();
87
88        $prop = $vcard->createProperty('BDAY');
89        $prop->setParts([
90            new \DateTime('2014-04-02 18:37:00'),
91        ]);
92
93        $this->assertEquals('20140402T183700Z', $prop->getValue());
94    }
95
96    public function testSetPartsDateTimeImmutable()
97    {
98        $vcard = new VObject\Component\VCard();
99
100        $prop = $vcard->createProperty('BDAY');
101        $prop->setParts([
102            new \DateTimeImmutable('2014-04-02 18:37:00'),
103        ]);
104
105        $this->assertEquals('20140402T183700Z', $prop->getValue());
106    }
107
108    /**
109     * @expectedException \InvalidArgumentException
110     */
111    public function testSetPartsTooMany()
112    {
113        $vcard = new VObject\Component\VCard();
114
115        $prop = $vcard->createProperty('BDAY');
116        $prop->setParts([
117            1,
118            2,
119        ]);
120    }
121
122    public function testSetPartsString()
123    {
124        $vcard = new VObject\Component\VCard();
125
126        $prop = $vcard->createProperty('BDAY');
127        $prop->setParts([
128            '20140402T183700Z',
129        ]);
130
131        $this->assertEquals('20140402T183700Z', $prop->getValue());
132    }
133
134    public function testSetValueDateTime()
135    {
136        $vcard = new VObject\Component\VCard();
137
138        $prop = $vcard->createProperty('BDAY');
139        $prop->setValue(
140            new \DateTime('2014-04-02 18:37:00')
141        );
142
143        $this->assertEquals('20140402T183700Z', $prop->getValue());
144    }
145
146    public function testSetValueDateTimeImmutable()
147    {
148        $vcard = new VObject\Component\VCard();
149
150        $prop = $vcard->createProperty('BDAY');
151        $prop->setValue(
152            new \DateTimeImmutable('2014-04-02 18:37:00')
153        );
154
155        $this->assertEquals('20140402T183700Z', $prop->getValue());
156    }
157
158    public function testSetDateTimeOffset()
159    {
160        $vcard = new VObject\Component\VCard();
161
162        $prop = $vcard->createProperty('BDAY');
163        $prop->setValue(
164            new \DateTime('2014-04-02 18:37:00', new \DateTimeZone('America/Toronto'))
165        );
166
167        $this->assertEquals('20140402T183700-0400', $prop->getValue());
168    }
169
170    public function testGetDateTime()
171    {
172        $datetime = new \DateTime('2014-04-02 18:37:00', new \DateTimeZone('America/Toronto'));
173
174        $vcard = new VObject\Component\VCard();
175        $prop = $vcard->createProperty('BDAY', $datetime);
176
177        $dt = $prop->getDateTime();
178        $this->assertEquals('2014-04-02T18:37:00-04:00', $dt->format('c'), 'For some reason this one failed. Current default timezone is: '.date_default_timezone_get());
179    }
180
181    public function testGetDate()
182    {
183        $datetime = new \DateTime('2014-04-02');
184
185        $vcard = new VObject\Component\VCard();
186        $prop = $vcard->createProperty('BDAY', $datetime, null, 'DATE');
187
188        $this->assertEquals('DATE', $prop->getValueType());
189        $this->assertEquals('BDAY:20140402', rtrim($prop->serialize()));
190    }
191
192    public function testGetDateIncomplete()
193    {
194        $datetime = '--0407';
195
196        $vcard = new VObject\Component\VCard();
197        $prop = $vcard->add('BDAY', $datetime);
198
199        $dt = $prop->getDateTime();
200        // Note: if the year changes between the last line and the next line of
201        // code, this test may fail.
202        //
203        // If that happens, head outside and have a drink.
204        $current = new \DateTime('now');
205        $year = $current->format('Y');
206
207        $this->assertEquals($year.'0407', $dt->format('Ymd'));
208    }
209
210    public function testGetDateIncompleteFromVCard()
211    {
212        $vcard = <<<VCF
213BEGIN:VCARD
214VERSION:4.0
215BDAY:--0407
216END:VCARD
217VCF;
218        $vcard = Reader::read($vcard);
219        $prop = $vcard->BDAY;
220
221        $dt = $prop->getDateTime();
222        // Note: if the year changes between the last line and the next line of
223        // code, this test may fail.
224        //
225        // If that happens, head outside and have a drink.
226        $current = new \DateTime('now');
227        $year = $current->format('Y');
228
229        $this->assertEquals($year.'0407', $dt->format('Ymd'));
230    }
231
232    public function testValidate()
233    {
234        $datetime = '--0407';
235
236        $vcard = new VObject\Component\VCard();
237        $prop = $vcard->add('BDAY', $datetime);
238
239        $this->assertEquals([], $prop->validate());
240    }
241
242    public function testValidateBroken()
243    {
244        $datetime = '123';
245
246        $vcard = new VObject\Component\VCard();
247        $prop = $vcard->add('BDAY', $datetime);
248
249        $this->assertEquals([[
250            'level' => 3,
251            'message' => 'The supplied value (123) is not a correct DATE-AND-OR-TIME property',
252            'node' => $prop,
253        ]], $prop->validate());
254    }
255}
256