]> git.mxchange.org Git - friendica-addons.git/blob - dav/SabreDAV/lib/Sabre/VObject/DateTimeParser.php
Move friendica-specific parts into an own subdirectory
[friendica-addons.git] / dav / SabreDAV / lib / Sabre / VObject / DateTimeParser.php
1 <?php
2
3 /**
4  * DateTimeParser
5  *
6  * This class is responsible for parsing the several different date and time
7  * formats iCalendar and vCards have.
8  *
9  * @package Sabre
10  * @subpackage VObject
11  * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
12  * @author Evert Pot (http://www.rooftopsolutions.nl/)
13  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
14  */
15 class Sabre_VObject_DateTimeParser {
16
17     /**
18      * Parses an iCalendar (rfc5545) formatted datetime and returns a DateTime object
19      *
20      * Specifying a reference timezone is optional. It will only be used
21      * if the non-UTC format is used. The argument is used as a reference, the
22      * returned DateTime object will still be in the UTC timezone.
23      *
24      * @param string $dt
25      * @param DateTimeZone $tz
26      * @return DateTime
27      */
28     static public function parseDateTime($dt,DateTimeZone $tz = null) {
29
30         // Format is YYYYMMDD + "T" + hhmmss
31         $result = preg_match('/^([1-3][0-9]{3})([0-1][0-9])([0-3][0-9])T([0-2][0-9])([0-5][0-9])([0-5][0-9])([Z]?)$/',$dt,$matches);
32
33         if (!$result) {
34             throw new Sabre_DAV_Exception_BadRequest('The supplied iCalendar datetime value is incorrect: ' . $dt);
35         }
36
37         if ($matches[7]==='Z' || is_null($tz)) {
38             $tz = new DateTimeZone('UTC');
39         }
40         $date = new DateTime($matches[1] . '-' . $matches[2] . '-' . $matches[3] . ' ' . $matches[4] . ':' . $matches[5] .':' . $matches[6], $tz);
41
42         // Still resetting the timezone, to normalize everything to UTC
43         $date->setTimeZone(new DateTimeZone('UTC'));
44         return $date;
45
46     }
47
48     /**
49      * Parses an iCalendar (rfc5545) formatted date and returns a DateTime object
50      *
51      * @param string $date
52      * @return DateTime
53      */
54     static public function parseDate($date) {
55
56         // Format is YYYYMMDD
57         $result = preg_match('/^([1-3][0-9]{3})([0-1][0-9])([0-3][0-9])$/',$date,$matches);
58
59         if (!$result) {
60             throw new Sabre_DAV_Exception_BadRequest('The supplied iCalendar date value is incorrect: ' . $date);
61         }
62
63         $date = new DateTime($matches[1] . '-' . $matches[2] . '-' . $matches[3], new DateTimeZone('UTC'));
64         return $date;
65
66     }
67
68     /**
69      * Parses an iCalendar (RFC5545) formatted duration value.
70      *
71      * This method will either return a DateTimeInterval object, or a string
72      * suitable for strtotime or DateTime::modify.
73      *
74      * @param string $duration
75      * @param bool $asString
76      * @return DateInterval|string
77      */
78     static public function parseDuration($duration, $asString = false) {
79
80         $result = preg_match('/^(?P<plusminus>\+|-)?P((?P<week>\d+)W)?((?P<day>\d+)D)?(T((?P<hour>\d+)H)?((?P<minute>\d+)M)?((?P<second>\d+)S)?)?$/', $duration, $matches);
81         if (!$result) {
82             throw new Sabre_DAV_Exception_BadRequest('The supplied iCalendar duration value is incorrect: ' . $duration);
83         }
84
85         if (!$asString) {
86             $invert = false;
87             if ($matches['plusminus']==='-') {
88                 $invert = true;
89             }
90
91
92             $parts = array(
93                 'week',
94                 'day',
95                 'hour',
96                 'minute',
97                 'second',
98             );
99             foreach($parts as $part) {
100                 $matches[$part] = isset($matches[$part])&&$matches[$part]?(int)$matches[$part]:0;
101             }
102
103
104             // We need to re-construct the $duration string, because weeks and
105             // days are not supported by DateInterval in the same string.
106             $duration = 'P';
107             $days = $matches['day'];
108             if ($matches['week']) {
109                 $days+=$matches['week']*7;
110             }
111             if ($days)
112                 $duration.=$days . 'D';
113
114             if ($matches['minute'] || $matches['second'] || $matches['hour']) {
115                 $duration.='T';
116
117                 if ($matches['hour'])
118                     $duration.=$matches['hour'].'H';
119
120                 if ($matches['minute'])
121                     $duration.=$matches['minute'].'M';
122
123                 if ($matches['second'])
124                     $duration.=$matches['second'].'S';
125
126             }
127
128             if ($duration==='P') {
129                 $duration = 'PT0S';
130             }
131             $iv = new DateInterval($duration);
132             if ($invert) $iv->invert = true;
133
134             return $iv;
135
136         }
137
138
139
140         $parts = array(
141             'week',
142             'day',
143             'hour',
144             'minute',
145             'second',
146         );
147
148         $newDur = '';
149         foreach($parts as $part) {
150             if (isset($matches[$part]) && $matches[$part]) {
151                 $newDur.=' '.$matches[$part] . ' ' . $part . 's';
152             }
153         }
154
155         $newDur = ($matches['plusminus']==='-'?'-':'+') . trim($newDur);
156         if ($newDur === '+') { $newDur = '+0 seconds'; };
157         return $newDur;
158
159     }
160
161     /**
162      * Parses either a Date or DateTime, or Duration value.
163      *
164      * @param string $date
165      * @param DateTimeZone|string $referenceTZ
166      * @return DateTime|DateInterval
167      */
168     static public function parse($date, $referenceTZ = null) {
169
170         if ($date[0]==='P' || ($date[0]==='-' && $date[1]==='P')) {
171             return self::parseDuration($date);
172         } elseif (strlen($date)===8) {
173             return self::parseDate($date);
174         } else {
175             return self::parseDateTime($date, $referenceTZ);
176         }
177
178     }
179
180
181 }