Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/phabricator
Path: blob/master/src/applications/calendar/parser/data/PhutilCalendarAbsoluteDateTime.php
12262 views
1
<?php
2
3
final class PhutilCalendarAbsoluteDateTime
4
extends PhutilCalendarDateTime {
5
6
private $year;
7
private $month;
8
private $day;
9
private $hour = 0;
10
private $minute = 0;
11
private $second = 0;
12
private $timezone;
13
14
public static function newFromISO8601($value, $timezone = 'UTC') {
15
$pattern =
16
'/^'.
17
'(?P<y>\d{4})(?P<m>\d{2})(?P<d>\d{2})'.
18
'(?:'.
19
'T(?P<h>\d{2})(?P<i>\d{2})(?P<s>\d{2})(?<z>Z)?'.
20
')?'.
21
'\z/';
22
23
$matches = null;
24
$ok = preg_match($pattern, $value, $matches);
25
if (!$ok) {
26
throw new Exception(
27
pht(
28
'Expected ISO8601 datetime in the format "19990105T112233Z", '.
29
'found "%s".',
30
$value));
31
}
32
33
if (isset($matches['z'])) {
34
if ($timezone != 'UTC') {
35
throw new Exception(
36
pht(
37
'ISO8601 date ends in "Z" indicating UTC, but a timezone other '.
38
'than UTC ("%s") was specified.',
39
$timezone));
40
}
41
}
42
43
$datetime = id(new self())
44
->setYear((int)$matches['y'])
45
->setMonth((int)$matches['m'])
46
->setDay((int)$matches['d'])
47
->setTimezone($timezone);
48
49
if (isset($matches['h'])) {
50
$datetime
51
->setHour((int)$matches['h'])
52
->setMinute((int)$matches['i'])
53
->setSecond((int)$matches['s']);
54
} else {
55
$datetime
56
->setIsAllDay(true);
57
}
58
59
return $datetime;
60
}
61
62
public static function newFromEpoch($epoch, $timezone = 'UTC') {
63
$date = new DateTime('@'.$epoch);
64
65
$zone = new DateTimeZone($timezone);
66
$date->setTimezone($zone);
67
68
return id(new self())
69
->setYear((int)$date->format('Y'))
70
->setMonth((int)$date->format('m'))
71
->setDay((int)$date->format('d'))
72
->setHour((int)$date->format('H'))
73
->setMinute((int)$date->format('i'))
74
->setSecond((int)$date->format('s'))
75
->setTimezone($timezone);
76
}
77
78
public static function newFromDictionary(array $dict) {
79
static $keys;
80
if ($keys === null) {
81
$keys = array_fuse(
82
array(
83
'kind',
84
'year',
85
'month',
86
'day',
87
'hour',
88
'minute',
89
'second',
90
'timezone',
91
'isAllDay',
92
));
93
}
94
95
foreach ($dict as $key => $value) {
96
if (!isset($keys[$key])) {
97
throw new Exception(
98
pht(
99
'Unexpected key "%s" in datetime dictionary, expected keys: %s.',
100
$key,
101
implode(', ', array_keys($keys))));
102
}
103
}
104
105
if (idx($dict, 'kind') !== 'absolute') {
106
throw new Exception(
107
pht(
108
'Expected key "%s" with value "%s" in datetime dictionary.',
109
'kind',
110
'absolute'));
111
}
112
113
if (!isset($dict['year'])) {
114
throw new Exception(
115
pht(
116
'Expected key "%s" in datetime dictionary.',
117
'year'));
118
}
119
120
$datetime = id(new self())
121
->setYear(idx($dict, 'year'))
122
->setMonth(idx($dict, 'month', 1))
123
->setDay(idx($dict, 'day', 1))
124
->setHour(idx($dict, 'hour', 0))
125
->setMinute(idx($dict, 'minute', 0))
126
->setSecond(idx($dict, 'second', 0))
127
->setTimezone(idx($dict, 'timezone'))
128
->setIsAllDay((bool)idx($dict, 'isAllDay', false));
129
130
return $datetime;
131
}
132
133
public function newRelativeDateTime($duration) {
134
if (is_string($duration)) {
135
$duration = PhutilCalendarDuration::newFromISO8601($duration);
136
}
137
138
if (!($duration instanceof PhutilCalendarDuration)) {
139
throw new Exception(
140
pht(
141
'Expected "PhutilCalendarDuration" object or ISO8601 duration '.
142
'string.'));
143
}
144
145
return id(new PhutilCalendarRelativeDateTime())
146
->setOrigin($this)
147
->setDuration($duration);
148
}
149
150
public function toDictionary() {
151
return array(
152
'kind' => 'absolute',
153
'year' => (int)$this->getYear(),
154
'month' => (int)$this->getMonth(),
155
'day' => (int)$this->getDay(),
156
'hour' => (int)$this->getHour(),
157
'minute' => (int)$this->getMinute(),
158
'second' => (int)$this->getSecond(),
159
'timezone' => $this->getTimezone(),
160
'isAllDay' => (bool)$this->getIsAllDay(),
161
);
162
}
163
164
public function setYear($year) {
165
$this->year = $year;
166
return $this;
167
}
168
169
public function getYear() {
170
return $this->year;
171
}
172
173
public function setMonth($month) {
174
$this->month = $month;
175
return $this;
176
}
177
178
public function getMonth() {
179
return $this->month;
180
}
181
182
public function setDay($day) {
183
$this->day = $day;
184
return $this;
185
}
186
187
public function getDay() {
188
return $this->day;
189
}
190
191
public function setHour($hour) {
192
$this->hour = $hour;
193
return $this;
194
}
195
196
public function getHour() {
197
return $this->hour;
198
}
199
200
public function setMinute($minute) {
201
$this->minute = $minute;
202
return $this;
203
}
204
205
public function getMinute() {
206
return $this->minute;
207
}
208
209
public function setSecond($second) {
210
$this->second = $second;
211
return $this;
212
}
213
214
public function getSecond() {
215
return $this->second;
216
}
217
218
public function setTimezone($timezone) {
219
$this->timezone = $timezone;
220
return $this;
221
}
222
223
public function getTimezone() {
224
return $this->timezone;
225
}
226
227
private function getEffectiveTimezone() {
228
$date_timezone = $this->getTimezone();
229
$viewer_timezone = $this->getViewerTimezone();
230
231
// Because all-day events are always "floating", the effective timezone
232
// is the viewer timezone if it is available. Otherwise, we'll return a
233
// DateTime object with the correct values, but it will be incorrectly
234
// adjusted forward or backward to the viewer's zone later.
235
236
$zones = array();
237
if ($this->getIsAllDay()) {
238
$zones[] = $viewer_timezone;
239
$zones[] = $date_timezone;
240
} else {
241
$zones[] = $date_timezone;
242
$zones[] = $viewer_timezone;
243
}
244
$zones = array_filter($zones);
245
246
if (!$zones) {
247
throw new Exception(
248
pht(
249
'Datetime has no timezone or viewer timezone.'));
250
}
251
252
return head($zones);
253
}
254
255
public function newPHPDateTimeZone() {
256
$zone = $this->getEffectiveTimezone();
257
return new DateTimeZone($zone);
258
}
259
260
public function newPHPDateTime() {
261
$zone = $this->newPHPDateTimeZone();
262
263
$y = $this->getYear();
264
$m = $this->getMonth();
265
$d = $this->getDay();
266
267
if ($this->getIsAllDay()) {
268
$h = 0;
269
$i = 0;
270
$s = 0;
271
} else {
272
$h = $this->getHour();
273
$i = $this->getMinute();
274
$s = $this->getSecond();
275
}
276
277
$format = sprintf('%04d-%02d-%02d %02d:%02d:%02d', $y, $m, $d, $h, $i, $s);
278
279
return new DateTime($format, $zone);
280
}
281
282
283
public function newAbsoluteDateTime() {
284
return clone $this;
285
}
286
287
}
288
289