Mercurial > hg > rc1
comparison plugins/libcalendaring/lib/Sabre/VObject/DateTimeParser.php @ 4:888e774ee983
libcalendar plugin as distributed
| author | Charlie Root |
|---|---|
| date | Sat, 13 Jan 2018 08:57:56 -0500 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| 3:f6fe4b6ae66a | 4:888e774ee983 |
|---|---|
| 1 <?php | |
| 2 | |
| 3 namespace Sabre\VObject; | |
| 4 | |
| 5 /** | |
| 6 * DateTimeParser | |
| 7 * | |
| 8 * This class is responsible for parsing the several different date and time | |
| 9 * formats iCalendar and vCards have. | |
| 10 * | |
| 11 * @copyright Copyright (C) 2007-2013 fruux GmbH (https://fruux.com/). | |
| 12 * @author Evert Pot (http://evertpot.com/) | |
| 13 * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License | |
| 14 */ | |
| 15 class 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-4][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 \LogicException('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-4][0-9]{3})([0-1][0-9])([0-3][0-9])$/',$date,$matches); | |
| 58 | |
| 59 if (!$result) { | |
| 60 throw new \LogicException('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 \LogicException('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 } |
