This source file includes following definitions.
- php_date_llabs
- php_date_llabs
- php_date_llabs
- PHP_INI_BEGIN
- php_date_get_immutable_ce
- php_date_get_timezone_ce
- PHP_GINIT_FUNCTION
- _php_date_tzinfo_dtor
- PHP_RINIT_FUNCTION
- PHP_RSHUTDOWN_FUNCTION
- PHP_MINIT_FUNCTION
- PHP_MSHUTDOWN_FUNCTION
- PHP_MINFO_FUNCTION
- php_date_parse_tzfile
- php_date_parse_tzfile_wrapper
- PHP_INI_MH
- guess_timezone
- get_timezone_info
- english_suffix
- php_date_full_day_name
- php_date_short_day_name
- date_format
- php_date
- php_format_date
- php_idate
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- php_date_set_tzdb
- php_parse_date
- PHP_FUNCTION
- php_mktime
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- php_strftime
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- date_period_it_invalidate_current
- date_period_it_dtor
- date_period_it_has_more
- date_period_it_current_data
- date_period_it_current_key
- date_period_it_move_forward
- date_period_it_rewind
- date_object_period_get_iterator
- implement_date_interface_handler
- date_register_classes
- date_object_new_date_ex
- date_object_new_date
- date_object_clone_date
- date_clone_immutable
- date_object_compare_date
- date_object_get_gc
- date_object_get_gc_timezone
- date_object_get_properties
- date_object_new_timezone_ex
- date_object_new_timezone
- date_object_clone_timezone
- date_object_get_properties_timezone
- date_object_new_interval_ex
- date_object_new_interval
- date_object_clone_interval
- date_object_get_gc_interval
- date_object_get_properties_interval
- date_object_new_period_ex
- date_object_new_period
- date_object_clone_period
- date_object_free_storage_date
- date_object_free_storage_timezone
- date_object_free_storage_interval
- date_object_free_storage_period
- php_date_instantiate
- update_errors_warnings
- php_date_initialize
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_METHOD
- PHP_METHOD
- PHP_METHOD
- php_date_initialize_from_hash
- PHP_METHOD
- PHP_METHOD
- PHP_METHOD
- zval_from_error_container
- PHP_FUNCTION
- php_date_do_return_parsed_time
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- php_date_modify
- PHP_FUNCTION
- PHP_METHOD
- php_date_add
- PHP_FUNCTION
- PHP_METHOD
- php_date_sub
- PHP_FUNCTION
- PHP_METHOD
- set_timezone_from_timelib_time
- PHP_FUNCTION
- php_date_timezone_set
- PHP_FUNCTION
- PHP_METHOD
- PHP_FUNCTION
- php_date_time_set
- PHP_FUNCTION
- PHP_METHOD
- php_date_date_set
- PHP_FUNCTION
- PHP_METHOD
- php_date_isodate_set
- PHP_FUNCTION
- PHP_METHOD
- php_date_timestamp_set
- PHP_FUNCTION
- PHP_METHOD
- PHP_FUNCTION
- PHP_FUNCTION
- timezone_initialize
- PHP_FUNCTION
- PHP_METHOD
- php_date_timezone_initialize_from_hash
- PHP_METHOD
- PHP_METHOD
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- date_interval_initialize
- date_interval_read_property
- date_interval_write_property
- PHP_METHOD
- php_date_interval_initialize_from_hash
- PHP_METHOD
- PHP_METHOD
- PHP_FUNCTION
- date_interval_format
- PHP_FUNCTION
- date_period_initialize
- PHP_METHOD
- PHP_METHOD
- PHP_METHOD
- PHP_METHOD
- check_id_allowed
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- php_do_date_sunrise_sunset
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- date_object_get_gc_period
- date_object_get_properties_period
- php_date_period_initialize_from_hash
- PHP_METHOD
- PHP_METHOD
- date_period_read_property
- date_period_write_property
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 #include "php.h"
22 #include "php_streams.h"
23 #include "php_main.h"
24 #include "php_globals.h"
25 #include "php_ini.h"
26 #include "ext/standard/info.h"
27 #include "ext/standard/php_versioning.h"
28 #include "ext/standard/php_math.h"
29 #include "php_date.h"
30 #include "zend_interfaces.h"
31 #include "lib/timelib.h"
32 #include <time.h>
33
34 #ifdef PHP_WIN32
35 static __inline __int64 php_date_llabs( __int64 i ) { return i >= 0? i: -i; }
36 #elif defined(__GNUC__) && __GNUC__ < 3
37 static __inline __int64_t php_date_llabs( __int64_t i ) { return i >= 0 ? i : -i; }
38 #else
39 static inline long long php_date_llabs( long long i ) { return i >= 0 ? i : -i; }
40 #endif
41
42 #ifdef PHP_WIN32
43 #define DATE_I64_BUF_LEN 65
44 # define DATE_I64A(i, s, len) _i64toa_s(i, s, len, 10)
45 # define DATE_A64I(i, s) i = _atoi64(s)
46 #else
47 #define DATE_I64_BUF_LEN 65
48 # define DATE_I64A(i, s, len) \
49 do { \
50 int st = snprintf(s, len, "%lld", i); \
51 s[st] = '\0'; \
52 } while (0);
53 #ifdef HAVE_ATOLL
54 # define DATE_A64I(i, s) i = atoll(s)
55 #else
56 # define DATE_A64I(i, s) i = strtoll(s, NULL, 10)
57 #endif
58 #endif
59
60
61 ZEND_BEGIN_ARG_INFO_EX(arginfo_date, 0, 0, 1)
62 ZEND_ARG_INFO(0, format)
63 ZEND_ARG_INFO(0, timestamp)
64 ZEND_END_ARG_INFO()
65
66 ZEND_BEGIN_ARG_INFO_EX(arginfo_gmdate, 0, 0, 1)
67 ZEND_ARG_INFO(0, format)
68 ZEND_ARG_INFO(0, timestamp)
69 ZEND_END_ARG_INFO()
70
71 ZEND_BEGIN_ARG_INFO_EX(arginfo_idate, 0, 0, 1)
72 ZEND_ARG_INFO(0, format)
73 ZEND_ARG_INFO(0, timestamp)
74 ZEND_END_ARG_INFO()
75
76 ZEND_BEGIN_ARG_INFO_EX(arginfo_strtotime, 0, 0, 1)
77 ZEND_ARG_INFO(0, time)
78 ZEND_ARG_INFO(0, now)
79 ZEND_END_ARG_INFO()
80
81 ZEND_BEGIN_ARG_INFO_EX(arginfo_mktime, 0, 0, 0)
82 ZEND_ARG_INFO(0, hour)
83 ZEND_ARG_INFO(0, min)
84 ZEND_ARG_INFO(0, sec)
85 ZEND_ARG_INFO(0, mon)
86 ZEND_ARG_INFO(0, day)
87 ZEND_ARG_INFO(0, year)
88 ZEND_END_ARG_INFO()
89
90 ZEND_BEGIN_ARG_INFO_EX(arginfo_gmmktime, 0, 0, 0)
91 ZEND_ARG_INFO(0, hour)
92 ZEND_ARG_INFO(0, min)
93 ZEND_ARG_INFO(0, sec)
94 ZEND_ARG_INFO(0, mon)
95 ZEND_ARG_INFO(0, day)
96 ZEND_ARG_INFO(0, year)
97 ZEND_END_ARG_INFO()
98
99 ZEND_BEGIN_ARG_INFO(arginfo_checkdate, 0)
100 ZEND_ARG_INFO(0, month)
101 ZEND_ARG_INFO(0, day)
102 ZEND_ARG_INFO(0, year)
103 ZEND_END_ARG_INFO()
104
105 ZEND_BEGIN_ARG_INFO_EX(arginfo_strftime, 0, 0, 1)
106 ZEND_ARG_INFO(0, format)
107 ZEND_ARG_INFO(0, timestamp)
108 ZEND_END_ARG_INFO()
109
110 ZEND_BEGIN_ARG_INFO_EX(arginfo_gmstrftime, 0, 0, 1)
111 ZEND_ARG_INFO(0, format)
112 ZEND_ARG_INFO(0, timestamp)
113 ZEND_END_ARG_INFO()
114
115 ZEND_BEGIN_ARG_INFO(arginfo_time, 0)
116 ZEND_END_ARG_INFO()
117
118 ZEND_BEGIN_ARG_INFO_EX(arginfo_localtime, 0, 0, 0)
119 ZEND_ARG_INFO(0, timestamp)
120 ZEND_ARG_INFO(0, associative_array)
121 ZEND_END_ARG_INFO()
122
123 ZEND_BEGIN_ARG_INFO_EX(arginfo_getdate, 0, 0, 0)
124 ZEND_ARG_INFO(0, timestamp)
125 ZEND_END_ARG_INFO()
126
127 ZEND_BEGIN_ARG_INFO(arginfo_date_default_timezone_set, 0)
128 ZEND_ARG_INFO(0, timezone_identifier)
129 ZEND_END_ARG_INFO()
130
131 ZEND_BEGIN_ARG_INFO(arginfo_date_default_timezone_get, 0)
132 ZEND_END_ARG_INFO()
133
134 ZEND_BEGIN_ARG_INFO_EX(arginfo_date_sunrise, 0, 0, 1)
135 ZEND_ARG_INFO(0, time)
136 ZEND_ARG_INFO(0, format)
137 ZEND_ARG_INFO(0, latitude)
138 ZEND_ARG_INFO(0, longitude)
139 ZEND_ARG_INFO(0, zenith)
140 ZEND_ARG_INFO(0, gmt_offset)
141 ZEND_END_ARG_INFO()
142
143 ZEND_BEGIN_ARG_INFO_EX(arginfo_date_sunset, 0, 0, 1)
144 ZEND_ARG_INFO(0, time)
145 ZEND_ARG_INFO(0, format)
146 ZEND_ARG_INFO(0, latitude)
147 ZEND_ARG_INFO(0, longitude)
148 ZEND_ARG_INFO(0, zenith)
149 ZEND_ARG_INFO(0, gmt_offset)
150 ZEND_END_ARG_INFO()
151
152 ZEND_BEGIN_ARG_INFO(arginfo_date_sun_info, 0)
153 ZEND_ARG_INFO(0, time)
154 ZEND_ARG_INFO(0, latitude)
155 ZEND_ARG_INFO(0, longitude)
156 ZEND_END_ARG_INFO()
157
158 ZEND_BEGIN_ARG_INFO_EX(arginfo_date_create, 0, 0, 0)
159 ZEND_ARG_INFO(0, time)
160 ZEND_ARG_INFO(0, object)
161 ZEND_END_ARG_INFO()
162
163 ZEND_BEGIN_ARG_INFO_EX(arginfo_date_create_from_format, 0, 0, 2)
164 ZEND_ARG_INFO(0, format)
165 ZEND_ARG_INFO(0, time)
166 ZEND_ARG_INFO(0, object)
167 ZEND_END_ARG_INFO()
168
169 ZEND_BEGIN_ARG_INFO_EX(arginfo_date_parse, 0, 0, 1)
170 ZEND_ARG_INFO(0, date)
171 ZEND_END_ARG_INFO()
172
173 ZEND_BEGIN_ARG_INFO_EX(arginfo_date_parse_from_format, 0, 0, 2)
174 ZEND_ARG_INFO(0, format)
175 ZEND_ARG_INFO(0, date)
176 ZEND_END_ARG_INFO()
177
178 ZEND_BEGIN_ARG_INFO(arginfo_date_get_last_errors, 0)
179 ZEND_END_ARG_INFO()
180
181 ZEND_BEGIN_ARG_INFO_EX(arginfo_date_format, 0, 0, 2)
182 ZEND_ARG_INFO(0, object)
183 ZEND_ARG_INFO(0, format)
184 ZEND_END_ARG_INFO()
185
186 ZEND_BEGIN_ARG_INFO_EX(arginfo_date_method_format, 0, 0, 1)
187 ZEND_ARG_INFO(0, format)
188 ZEND_END_ARG_INFO()
189
190 ZEND_BEGIN_ARG_INFO_EX(arginfo_date_modify, 0, 0, 2)
191 ZEND_ARG_INFO(0, object)
192 ZEND_ARG_INFO(0, modify)
193 ZEND_END_ARG_INFO()
194
195 ZEND_BEGIN_ARG_INFO_EX(arginfo_date_method_modify, 0, 0, 1)
196 ZEND_ARG_INFO(0, modify)
197 ZEND_END_ARG_INFO()
198
199 ZEND_BEGIN_ARG_INFO_EX(arginfo_date_add, 0, 0, 2)
200 ZEND_ARG_INFO(0, object)
201 ZEND_ARG_INFO(0, interval)
202 ZEND_END_ARG_INFO()
203
204 ZEND_BEGIN_ARG_INFO_EX(arginfo_date_method_add, 0, 0, 1)
205 ZEND_ARG_INFO(0, interval)
206 ZEND_END_ARG_INFO()
207
208 ZEND_BEGIN_ARG_INFO_EX(arginfo_date_sub, 0, 0, 2)
209 ZEND_ARG_INFO(0, object)
210 ZEND_ARG_INFO(0, interval)
211 ZEND_END_ARG_INFO()
212
213 ZEND_BEGIN_ARG_INFO_EX(arginfo_date_method_sub, 0, 0, 1)
214 ZEND_ARG_INFO(0, interval)
215 ZEND_END_ARG_INFO()
216
217 ZEND_BEGIN_ARG_INFO_EX(arginfo_date_timezone_get, 0, 0, 1)
218 ZEND_ARG_INFO(0, object)
219 ZEND_END_ARG_INFO()
220
221 ZEND_BEGIN_ARG_INFO(arginfo_date_method_timezone_get, 0)
222 ZEND_END_ARG_INFO()
223
224 ZEND_BEGIN_ARG_INFO_EX(arginfo_date_timezone_set, 0, 0, 2)
225 ZEND_ARG_INFO(0, object)
226 ZEND_ARG_INFO(0, timezone)
227 ZEND_END_ARG_INFO()
228
229 ZEND_BEGIN_ARG_INFO_EX(arginfo_date_method_timezone_set, 0, 0, 1)
230 ZEND_ARG_INFO(0, timezone)
231 ZEND_END_ARG_INFO()
232
233 ZEND_BEGIN_ARG_INFO_EX(arginfo_date_offset_get, 0, 0, 1)
234 ZEND_ARG_INFO(0, object)
235 ZEND_END_ARG_INFO()
236
237 ZEND_BEGIN_ARG_INFO(arginfo_date_method_offset_get, 0)
238 ZEND_END_ARG_INFO()
239
240 ZEND_BEGIN_ARG_INFO_EX(arginfo_date_diff, 0, 0, 2)
241 ZEND_ARG_INFO(0, object)
242 ZEND_ARG_INFO(0, object2)
243 ZEND_ARG_INFO(0, absolute)
244 ZEND_END_ARG_INFO()
245
246 ZEND_BEGIN_ARG_INFO_EX(arginfo_date_method_diff, 0, 0, 1)
247 ZEND_ARG_INFO(0, object)
248 ZEND_ARG_INFO(0, absolute)
249 ZEND_END_ARG_INFO()
250
251 ZEND_BEGIN_ARG_INFO_EX(arginfo_date_time_set, 0, 0, 3)
252 ZEND_ARG_INFO(0, object)
253 ZEND_ARG_INFO(0, hour)
254 ZEND_ARG_INFO(0, minute)
255 ZEND_ARG_INFO(0, second)
256 ZEND_END_ARG_INFO()
257
258 ZEND_BEGIN_ARG_INFO_EX(arginfo_date_method_time_set, 0, 0, 2)
259 ZEND_ARG_INFO(0, hour)
260 ZEND_ARG_INFO(0, minute)
261 ZEND_ARG_INFO(0, second)
262 ZEND_END_ARG_INFO()
263
264 ZEND_BEGIN_ARG_INFO_EX(arginfo_date_date_set, 0, 0, 4)
265 ZEND_ARG_INFO(0, object)
266 ZEND_ARG_INFO(0, year)
267 ZEND_ARG_INFO(0, month)
268 ZEND_ARG_INFO(0, day)
269 ZEND_END_ARG_INFO()
270
271 ZEND_BEGIN_ARG_INFO_EX(arginfo_date_method_date_set, 0, 0, 3)
272 ZEND_ARG_INFO(0, year)
273 ZEND_ARG_INFO(0, month)
274 ZEND_ARG_INFO(0, day)
275 ZEND_END_ARG_INFO()
276
277 ZEND_BEGIN_ARG_INFO_EX(arginfo_date_isodate_set, 0, 0, 3)
278 ZEND_ARG_INFO(0, object)
279 ZEND_ARG_INFO(0, year)
280 ZEND_ARG_INFO(0, week)
281 ZEND_ARG_INFO(0, day)
282 ZEND_END_ARG_INFO()
283
284 ZEND_BEGIN_ARG_INFO_EX(arginfo_date_method_isodate_set, 0, 0, 2)
285 ZEND_ARG_INFO(0, year)
286 ZEND_ARG_INFO(0, week)
287 ZEND_ARG_INFO(0, day)
288 ZEND_END_ARG_INFO()
289
290 ZEND_BEGIN_ARG_INFO_EX(arginfo_date_timestamp_set, 0, 0, 2)
291 ZEND_ARG_INFO(0, object)
292 ZEND_ARG_INFO(0, unixtimestamp)
293 ZEND_END_ARG_INFO()
294
295 ZEND_BEGIN_ARG_INFO_EX(arginfo_date_method_timestamp_set, 0, 0, 1)
296 ZEND_ARG_INFO(0, unixtimestamp)
297 ZEND_END_ARG_INFO()
298
299 ZEND_BEGIN_ARG_INFO_EX(arginfo_date_timestamp_get, 0, 0, 1)
300 ZEND_ARG_INFO(0, object)
301 ZEND_END_ARG_INFO()
302
303 ZEND_BEGIN_ARG_INFO(arginfo_date_method_timestamp_get, 0)
304 ZEND_END_ARG_INFO()
305
306 ZEND_BEGIN_ARG_INFO_EX(arginfo_date_method_create_from_mutable, 0, 0, 1)
307 ZEND_ARG_INFO(0, DateTime)
308 ZEND_END_ARG_INFO()
309
310 ZEND_BEGIN_ARG_INFO_EX(arginfo_timezone_open, 0, 0, 1)
311 ZEND_ARG_INFO(0, timezone)
312 ZEND_END_ARG_INFO()
313
314 ZEND_BEGIN_ARG_INFO_EX(arginfo_timezone_name_get, 0, 0, 1)
315 ZEND_ARG_INFO(0, object)
316 ZEND_END_ARG_INFO()
317
318 ZEND_BEGIN_ARG_INFO(arginfo_timezone_method_name_get, 0)
319 ZEND_END_ARG_INFO()
320
321 ZEND_BEGIN_ARG_INFO_EX(arginfo_timezone_name_from_abbr, 0, 0, 1)
322 ZEND_ARG_INFO(0, abbr)
323 ZEND_ARG_INFO(0, gmtoffset)
324 ZEND_ARG_INFO(0, isdst)
325 ZEND_END_ARG_INFO()
326
327 ZEND_BEGIN_ARG_INFO_EX(arginfo_timezone_offset_get, 0, 0, 2)
328 ZEND_ARG_OBJ_INFO(0, object, DateTimeZone, 0)
329 ZEND_ARG_OBJ_INFO(0, datetime, DateTimeInterface, 0)
330 ZEND_END_ARG_INFO()
331
332 ZEND_BEGIN_ARG_INFO_EX(arginfo_timezone_method_offset_get, 0, 0, 1)
333 ZEND_ARG_INFO(0, object)
334 ZEND_END_ARG_INFO()
335
336 ZEND_BEGIN_ARG_INFO_EX(arginfo_timezone_transitions_get, 0, 0, 1)
337 ZEND_ARG_INFO(0, object)
338 ZEND_ARG_INFO(0, timestamp_begin)
339 ZEND_ARG_INFO(0, timestamp_end)
340 ZEND_END_ARG_INFO()
341
342 ZEND_BEGIN_ARG_INFO(arginfo_timezone_method_transitions_get, 0)
343 ZEND_ARG_INFO(0, timestamp_begin)
344 ZEND_ARG_INFO(0, timestamp_end)
345 ZEND_END_ARG_INFO()
346
347 ZEND_BEGIN_ARG_INFO_EX(arginfo_timezone_location_get, 0, 0, 1)
348 ZEND_ARG_INFO(0, object)
349 ZEND_END_ARG_INFO()
350
351 ZEND_BEGIN_ARG_INFO(arginfo_timezone_method_location_get, 0)
352 ZEND_END_ARG_INFO()
353
354 ZEND_BEGIN_ARG_INFO_EX(arginfo_timezone_identifiers_list, 0, 0, 0)
355 ZEND_ARG_INFO(0, what)
356 ZEND_ARG_INFO(0, country)
357 ZEND_END_ARG_INFO()
358
359 ZEND_BEGIN_ARG_INFO(arginfo_timezone_abbreviations_list, 0)
360 ZEND_END_ARG_INFO()
361
362 ZEND_BEGIN_ARG_INFO(arginfo_timezone_version_get, 0)
363 ZEND_END_ARG_INFO()
364
365 ZEND_BEGIN_ARG_INFO_EX(arginfo_date_interval_create_from_date_string, 0, 0, 1)
366 ZEND_ARG_INFO(0, time)
367 ZEND_END_ARG_INFO()
368
369 ZEND_BEGIN_ARG_INFO_EX(arginfo_date_interval_format, 0, 0, 2)
370 ZEND_ARG_INFO(0, object)
371 ZEND_ARG_INFO(0, format)
372 ZEND_END_ARG_INFO()
373
374 ZEND_BEGIN_ARG_INFO(arginfo_date_method_interval_format, 0)
375 ZEND_ARG_INFO(0, format)
376 ZEND_END_ARG_INFO()
377
378 ZEND_BEGIN_ARG_INFO_EX(arginfo_date_period_construct, 0, 0, 3)
379 ZEND_ARG_INFO(0, start)
380 ZEND_ARG_INFO(0, interval)
381 ZEND_ARG_INFO(0, end)
382 ZEND_END_ARG_INFO()
383
384 ZEND_BEGIN_ARG_INFO_EX(arginfo_date_interval_construct, 0, 0, 1)
385 ZEND_ARG_INFO(0, interval_spec)
386 ZEND_END_ARG_INFO()
387
388
389
390 const zend_function_entry date_functions[] = {
391 PHP_FE(strtotime, arginfo_strtotime)
392 PHP_FE(date, arginfo_date)
393 PHP_FE(idate, arginfo_idate)
394 PHP_FE(gmdate, arginfo_gmdate)
395 PHP_FE(mktime, arginfo_mktime)
396 PHP_FE(gmmktime, arginfo_gmmktime)
397 PHP_FE(checkdate, arginfo_checkdate)
398
399 #ifdef HAVE_STRFTIME
400 PHP_FE(strftime, arginfo_strftime)
401 PHP_FE(gmstrftime, arginfo_gmstrftime)
402 #endif
403
404 PHP_FE(time, arginfo_time)
405 PHP_FE(localtime, arginfo_localtime)
406 PHP_FE(getdate, arginfo_getdate)
407
408
409 PHP_FE(date_create, arginfo_date_create)
410 PHP_FE(date_create_immutable, arginfo_date_create)
411 PHP_FE(date_create_from_format, arginfo_date_create_from_format)
412 PHP_FE(date_create_immutable_from_format, arginfo_date_create_from_format)
413 PHP_FE(date_parse, arginfo_date_parse)
414 PHP_FE(date_parse_from_format, arginfo_date_parse_from_format)
415 PHP_FE(date_get_last_errors, arginfo_date_get_last_errors)
416 PHP_FE(date_format, arginfo_date_format)
417 PHP_FE(date_modify, arginfo_date_modify)
418 PHP_FE(date_add, arginfo_date_add)
419 PHP_FE(date_sub, arginfo_date_sub)
420 PHP_FE(date_timezone_get, arginfo_date_timezone_get)
421 PHP_FE(date_timezone_set, arginfo_date_timezone_set)
422 PHP_FE(date_offset_get, arginfo_date_offset_get)
423 PHP_FE(date_diff, arginfo_date_diff)
424
425 PHP_FE(date_time_set, arginfo_date_time_set)
426 PHP_FE(date_date_set, arginfo_date_date_set)
427 PHP_FE(date_isodate_set, arginfo_date_isodate_set)
428 PHP_FE(date_timestamp_set, arginfo_date_timestamp_set)
429 PHP_FE(date_timestamp_get, arginfo_date_timestamp_get)
430
431 PHP_FE(timezone_open, arginfo_timezone_open)
432 PHP_FE(timezone_name_get, arginfo_timezone_name_get)
433 PHP_FE(timezone_name_from_abbr, arginfo_timezone_name_from_abbr)
434 PHP_FE(timezone_offset_get, arginfo_timezone_offset_get)
435 PHP_FE(timezone_transitions_get, arginfo_timezone_transitions_get)
436 PHP_FE(timezone_location_get, arginfo_timezone_location_get)
437 PHP_FE(timezone_identifiers_list, arginfo_timezone_identifiers_list)
438 PHP_FE(timezone_abbreviations_list, arginfo_timezone_abbreviations_list)
439 PHP_FE(timezone_version_get, arginfo_timezone_version_get)
440
441 PHP_FE(date_interval_create_from_date_string, arginfo_date_interval_create_from_date_string)
442 PHP_FE(date_interval_format, arginfo_date_interval_format)
443
444
445 PHP_FE(date_default_timezone_set, arginfo_date_default_timezone_set)
446 PHP_FE(date_default_timezone_get, arginfo_date_default_timezone_get)
447
448
449 PHP_FE(date_sunrise, arginfo_date_sunrise)
450 PHP_FE(date_sunset, arginfo_date_sunset)
451 PHP_FE(date_sun_info, arginfo_date_sun_info)
452 PHP_FE_END
453 };
454
455 static const zend_function_entry date_funcs_interface[] = {
456 PHP_ABSTRACT_ME(DateTimeInterface, format, arginfo_date_method_format)
457 PHP_ABSTRACT_ME(DateTimeInterface, getTimezone, arginfo_date_method_timezone_get)
458 PHP_ABSTRACT_ME(DateTimeInterface, getOffset, arginfo_date_method_offset_get)
459 PHP_ABSTRACT_ME(DateTimeInterface, getTimestamp, arginfo_date_method_timestamp_get)
460 PHP_ABSTRACT_ME(DateTimeInterface, diff, arginfo_date_method_diff)
461 PHP_ABSTRACT_ME(DateTimeInterface, __wakeup, NULL)
462 PHP_FE_END
463 };
464
465 const zend_function_entry date_funcs_date[] = {
466 PHP_ME(DateTime, __construct, arginfo_date_create, ZEND_ACC_CTOR|ZEND_ACC_PUBLIC)
467 PHP_ME(DateTime, __wakeup, NULL, ZEND_ACC_PUBLIC)
468 PHP_ME(DateTime, __set_state, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
469 PHP_ME_MAPPING(createFromFormat, date_create_from_format, arginfo_date_create_from_format, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
470 PHP_ME_MAPPING(getLastErrors, date_get_last_errors, arginfo_date_get_last_errors, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
471 PHP_ME_MAPPING(format, date_format, arginfo_date_method_format, 0)
472 PHP_ME_MAPPING(modify, date_modify, arginfo_date_method_modify, 0)
473 PHP_ME_MAPPING(add, date_add, arginfo_date_method_add, 0)
474 PHP_ME_MAPPING(sub, date_sub, arginfo_date_method_sub, 0)
475 PHP_ME_MAPPING(getTimezone, date_timezone_get, arginfo_date_method_timezone_get, 0)
476 PHP_ME_MAPPING(setTimezone, date_timezone_set, arginfo_date_method_timezone_set, 0)
477 PHP_ME_MAPPING(getOffset, date_offset_get, arginfo_date_method_offset_get, 0)
478 PHP_ME_MAPPING(setTime, date_time_set, arginfo_date_method_time_set, 0)
479 PHP_ME_MAPPING(setDate, date_date_set, arginfo_date_method_date_set, 0)
480 PHP_ME_MAPPING(setISODate, date_isodate_set, arginfo_date_method_isodate_set, 0)
481 PHP_ME_MAPPING(setTimestamp, date_timestamp_set, arginfo_date_method_timestamp_set, 0)
482 PHP_ME_MAPPING(getTimestamp, date_timestamp_get, arginfo_date_method_timestamp_get, 0)
483 PHP_ME_MAPPING(diff, date_diff, arginfo_date_method_diff, 0)
484 PHP_FE_END
485 };
486
487 const zend_function_entry date_funcs_immutable[] = {
488 PHP_ME(DateTimeImmutable, __construct, arginfo_date_create, ZEND_ACC_CTOR|ZEND_ACC_PUBLIC)
489 PHP_ME(DateTime, __wakeup, NULL, ZEND_ACC_PUBLIC)
490 PHP_ME(DateTimeImmutable, __set_state, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
491 PHP_ME_MAPPING(createFromFormat, date_create_immutable_from_format, arginfo_date_create_from_format, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
492 PHP_ME_MAPPING(getLastErrors, date_get_last_errors, arginfo_date_get_last_errors, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
493 PHP_ME_MAPPING(format, date_format, arginfo_date_method_format, 0)
494 PHP_ME_MAPPING(getTimezone, date_timezone_get, arginfo_date_method_timezone_get, 0)
495 PHP_ME_MAPPING(getOffset, date_offset_get, arginfo_date_method_offset_get, 0)
496 PHP_ME_MAPPING(getTimestamp, date_timestamp_get, arginfo_date_method_timestamp_get, 0)
497 PHP_ME_MAPPING(diff, date_diff, arginfo_date_method_diff, 0)
498 PHP_ME(DateTimeImmutable, modify, arginfo_date_method_modify, 0)
499 PHP_ME(DateTimeImmutable, add, arginfo_date_method_add, 0)
500 PHP_ME(DateTimeImmutable, sub, arginfo_date_method_sub, 0)
501 PHP_ME(DateTimeImmutable, setTimezone, arginfo_date_method_timezone_set, 0)
502 PHP_ME(DateTimeImmutable, setTime, arginfo_date_method_time_set, 0)
503 PHP_ME(DateTimeImmutable, setDate, arginfo_date_method_date_set, 0)
504 PHP_ME(DateTimeImmutable, setISODate, arginfo_date_method_isodate_set, 0)
505 PHP_ME(DateTimeImmutable, setTimestamp, arginfo_date_method_timestamp_set, 0)
506 PHP_ME(DateTimeImmutable, createFromMutable, arginfo_date_method_create_from_mutable, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
507 PHP_FE_END
508 };
509
510 const zend_function_entry date_funcs_timezone[] = {
511 PHP_ME(DateTimeZone, __construct, arginfo_timezone_open, ZEND_ACC_CTOR|ZEND_ACC_PUBLIC)
512 PHP_ME(DateTimeZone, __wakeup, NULL, ZEND_ACC_PUBLIC)
513 PHP_ME(DateTimeZone, __set_state, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
514 PHP_ME_MAPPING(getName, timezone_name_get, arginfo_timezone_method_name_get, 0)
515 PHP_ME_MAPPING(getOffset, timezone_offset_get, arginfo_timezone_method_offset_get, 0)
516 PHP_ME_MAPPING(getTransitions, timezone_transitions_get, arginfo_timezone_method_transitions_get, 0)
517 PHP_ME_MAPPING(getLocation, timezone_location_get, arginfo_timezone_method_location_get, 0)
518 PHP_ME_MAPPING(listAbbreviations, timezone_abbreviations_list, arginfo_timezone_abbreviations_list, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
519 PHP_ME_MAPPING(listIdentifiers, timezone_identifiers_list, arginfo_timezone_identifiers_list, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
520 PHP_FE_END
521 };
522
523 const zend_function_entry date_funcs_interval[] = {
524 PHP_ME(DateInterval, __construct, arginfo_date_interval_construct, ZEND_ACC_CTOR|ZEND_ACC_PUBLIC)
525 PHP_ME(DateInterval, __wakeup, NULL, ZEND_ACC_PUBLIC)
526 PHP_ME(DateInterval, __set_state, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
527 PHP_ME_MAPPING(format, date_interval_format, arginfo_date_method_interval_format, 0)
528 PHP_ME_MAPPING(createFromDateString, date_interval_create_from_date_string, arginfo_date_interval_create_from_date_string, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
529 PHP_FE_END
530 };
531
532 const zend_function_entry date_funcs_period[] = {
533 PHP_ME(DatePeriod, __construct, arginfo_date_period_construct, ZEND_ACC_CTOR|ZEND_ACC_PUBLIC)
534 PHP_ME(DatePeriod, __wakeup, NULL, ZEND_ACC_PUBLIC)
535 PHP_ME(DatePeriod, __set_state, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
536 PHP_ME(DatePeriod, getStartDate, NULL, ZEND_ACC_PUBLIC)
537 PHP_ME(DatePeriod, getEndDate, NULL, ZEND_ACC_PUBLIC)
538 PHP_ME(DatePeriod, getDateInterval, NULL, ZEND_ACC_PUBLIC)
539 PHP_FE_END
540 };
541
542 static char* guess_timezone(const timelib_tzdb *tzdb);
543 static void date_register_classes(void);
544
545
546 ZEND_DECLARE_MODULE_GLOBALS(date)
547 static PHP_GINIT_FUNCTION(date);
548
549
550 timelib_tzdb *php_date_global_timezone_db;
551 int php_date_global_timezone_db_enabled;
552
553 #define DATE_DEFAULT_LATITUDE "31.7667"
554 #define DATE_DEFAULT_LONGITUDE "35.2333"
555
556
557 #define DATE_SUNSET_ZENITH "90.583333"
558
559
560 #define DATE_SUNRISE_ZENITH "90.583333"
561
562 static PHP_INI_MH(OnUpdate_date_timezone);
563
564
565 PHP_INI_BEGIN()
566 STD_PHP_INI_ENTRY("date.timezone", "", PHP_INI_ALL, OnUpdate_date_timezone, default_timezone, zend_date_globals, date_globals)
567 PHP_INI_ENTRY("date.default_latitude", DATE_DEFAULT_LATITUDE, PHP_INI_ALL, NULL)
568 PHP_INI_ENTRY("date.default_longitude", DATE_DEFAULT_LONGITUDE, PHP_INI_ALL, NULL)
569 PHP_INI_ENTRY("date.sunset_zenith", DATE_SUNSET_ZENITH, PHP_INI_ALL, NULL)
570 PHP_INI_ENTRY("date.sunrise_zenith", DATE_SUNRISE_ZENITH, PHP_INI_ALL, NULL)
571 PHP_INI_END()
572
573
574 zend_class_entry *date_ce_date, *date_ce_timezone, *date_ce_interval, *date_ce_period;
575 zend_class_entry *date_ce_immutable, *date_ce_interface;
576
577
578 PHPAPI zend_class_entry *php_date_get_date_ce(void)
579 {
580 return date_ce_date;
581 }
582
583 PHPAPI zend_class_entry *php_date_get_immutable_ce(void)
584 {
585 return date_ce_immutable;
586 }
587
588 PHPAPI zend_class_entry *php_date_get_timezone_ce(void)
589 {
590 return date_ce_timezone;
591 }
592
593 static zend_object_handlers date_object_handlers_date;
594 static zend_object_handlers date_object_handlers_immutable;
595 static zend_object_handlers date_object_handlers_timezone;
596 static zend_object_handlers date_object_handlers_interval;
597 static zend_object_handlers date_object_handlers_period;
598
599 #define DATE_SET_CONTEXT \
600 zval *object; \
601 object = getThis(); \
602
603 #define DATE_FETCH_OBJECT \
604 php_date_obj *obj; \
605 DATE_SET_CONTEXT; \
606 if (object) { \
607 if (zend_parse_parameters_none() == FAILURE) { \
608 return; \
609 } \
610 } else { \
611 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), NULL, "O", &object, date_ce_date) == FAILURE) { \
612 RETURN_FALSE; \
613 } \
614 } \
615 obj = Z_PHPDATE_P(object); \
616
617 #define DATE_CHECK_INITIALIZED(member, class_name) \
618 if (!(member)) { \
619 php_error_docref(NULL, E_WARNING, "The " #class_name " object has not been correctly initialized by its constructor"); \
620 RETURN_FALSE; \
621 }
622
623 static void date_object_free_storage_date(zend_object *object);
624 static void date_object_free_storage_timezone(zend_object *object);
625 static void date_object_free_storage_interval(zend_object *object);
626 static void date_object_free_storage_period(zend_object *object);
627
628 static zend_object *date_object_new_date(zend_class_entry *class_type);
629 static zend_object *date_object_new_timezone(zend_class_entry *class_type);
630 static zend_object *date_object_new_interval(zend_class_entry *class_type);
631 static zend_object *date_object_new_period(zend_class_entry *class_type);
632
633 static zend_object *date_object_clone_date(zval *this_ptr);
634 static zend_object *date_object_clone_timezone(zval *this_ptr);
635 static zend_object *date_object_clone_interval(zval *this_ptr);
636 static zend_object *date_object_clone_period(zval *this_ptr);
637
638 static int date_object_compare_date(zval *d1, zval *d2);
639 static HashTable *date_object_get_gc(zval *object, zval **table, int *n);
640 static HashTable *date_object_get_properties(zval *object);
641 static HashTable *date_object_get_gc_interval(zval *object, zval **table, int *n);
642 static HashTable *date_object_get_properties_interval(zval *object);
643 static HashTable *date_object_get_gc_period(zval *object, zval **table, int *n);
644 static HashTable *date_object_get_properties_period(zval *object);
645 static HashTable *date_object_get_properties_timezone(zval *object);
646 static HashTable *date_object_get_gc_timezone(zval *object, zval **table, int *n);
647
648 zval *date_interval_read_property(zval *object, zval *member, int type, void **cache_slot, zval *rv);
649 void date_interval_write_property(zval *object, zval *member, zval *value, void **cache_slot);
650 static zval *date_period_read_property(zval *object, zval *member, int type, void **cache_slot, zval *rv);
651 static void date_period_write_property(zval *object, zval *member, zval *value, void **cache_slot);
652
653
654 zend_module_entry date_module_entry = {
655 STANDARD_MODULE_HEADER_EX,
656 NULL,
657 NULL,
658 "date",
659 date_functions,
660 PHP_MINIT(date),
661 PHP_MSHUTDOWN(date),
662 PHP_RINIT(date),
663 PHP_RSHUTDOWN(date),
664 PHP_MINFO(date),
665 PHP_DATE_VERSION,
666 PHP_MODULE_GLOBALS(date),
667 PHP_GINIT(date),
668 NULL,
669 NULL,
670 STANDARD_MODULE_PROPERTIES_EX
671 };
672
673
674
675
676 static PHP_GINIT_FUNCTION(date)
677 {
678 date_globals->default_timezone = NULL;
679 date_globals->timezone = NULL;
680 date_globals->tzcache = NULL;
681 date_globals->timezone_valid = 0;
682 }
683
684
685
686 static void _php_date_tzinfo_dtor(zval *zv)
687 {
688 timelib_tzinfo *tzi = (timelib_tzinfo*)Z_PTR_P(zv);
689
690 timelib_tzinfo_dtor(tzi);
691 }
692
693
694 PHP_RINIT_FUNCTION(date)
695 {
696 if (DATEG(timezone)) {
697 efree(DATEG(timezone));
698 }
699 DATEG(timezone) = NULL;
700 DATEG(tzcache) = NULL;
701 DATEG(last_errors) = NULL;
702
703 return SUCCESS;
704 }
705
706
707
708 PHP_RSHUTDOWN_FUNCTION(date)
709 {
710 if (DATEG(timezone)) {
711 efree(DATEG(timezone));
712 }
713 DATEG(timezone) = NULL;
714 if(DATEG(tzcache)) {
715 zend_hash_destroy(DATEG(tzcache));
716 FREE_HASHTABLE(DATEG(tzcache));
717 DATEG(tzcache) = NULL;
718 }
719 if (DATEG(last_errors)) {
720 timelib_error_container_dtor(DATEG(last_errors));
721 DATEG(last_errors) = NULL;
722 }
723
724 return SUCCESS;
725 }
726
727
728 #define DATE_TIMEZONEDB php_date_global_timezone_db ? php_date_global_timezone_db : timelib_builtin_db()
729
730
731
732
733
734
735
736
737
738
739
740 #define DATE_FORMAT_RFC822 "D, d M y H:i:s O"
741
742
743
744
745
746
747
748 #define DATE_FORMAT_RFC850 "l, d-M-y H:i:s T"
749
750
751
752
753
754
755
756
757
758 #define DATE_FORMAT_RFC1036 "D, d M y H:i:s O"
759
760
761
762
763
764
765 #define DATE_FORMAT_RFC1123 "D, d M Y H:i:s O"
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787 #define DATE_FORMAT_RFC2822 "D, d M Y H:i:s O"
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808 #define DATE_FORMAT_RFC3339 "Y-m-d\\TH:i:sP"
809
810 #define DATE_FORMAT_ISO8601 "Y-m-d\\TH:i:sO"
811
812
813
814
815
816
817
818
819
820 #define DATE_FORMAT_RFC3339_EXTENDED "Y-m-d\\TH:i:s.vP"
821
822
823
824
825
826
827
828 #define DATE_FORMAT_COOKIE "l, d-M-Y H:i:s T"
829
830 #define SUNFUNCS_RET_TIMESTAMP 0
831 #define SUNFUNCS_RET_STRING 1
832 #define SUNFUNCS_RET_DOUBLE 2
833
834
835 PHP_MINIT_FUNCTION(date)
836 {
837 REGISTER_INI_ENTRIES();
838 date_register_classes();
839
840
841
842
843
844
845
846 REGISTER_STRING_CONSTANT("DATE_ATOM", DATE_FORMAT_RFC3339, CONST_CS | CONST_PERSISTENT);
847
848
849
850
851
852
853 REGISTER_STRING_CONSTANT("DATE_COOKIE", DATE_FORMAT_COOKIE, CONST_CS | CONST_PERSISTENT);
854 REGISTER_STRING_CONSTANT("DATE_ISO8601", DATE_FORMAT_ISO8601, CONST_CS | CONST_PERSISTENT);
855
856 REGISTER_STRING_CONSTANT("DATE_RFC822", DATE_FORMAT_RFC822, CONST_CS | CONST_PERSISTENT);
857 REGISTER_STRING_CONSTANT("DATE_RFC850", DATE_FORMAT_RFC850, CONST_CS | CONST_PERSISTENT);
858 REGISTER_STRING_CONSTANT("DATE_RFC1036", DATE_FORMAT_RFC1036, CONST_CS | CONST_PERSISTENT);
859 REGISTER_STRING_CONSTANT("DATE_RFC1123", DATE_FORMAT_RFC1123, CONST_CS | CONST_PERSISTENT);
860 REGISTER_STRING_CONSTANT("DATE_RFC2822", DATE_FORMAT_RFC2822, CONST_CS | CONST_PERSISTENT);
861 REGISTER_STRING_CONSTANT("DATE_RFC3339", DATE_FORMAT_RFC3339, CONST_CS | CONST_PERSISTENT);
862 REGISTER_STRING_CONSTANT("DATE_RFC3339_EXTENDED", DATE_FORMAT_RFC3339_EXTENDED, CONST_CS | CONST_PERSISTENT);
863
864
865
866
867
868
869 REGISTER_STRING_CONSTANT("DATE_RSS", DATE_FORMAT_RFC1123, CONST_CS | CONST_PERSISTENT);
870 REGISTER_STRING_CONSTANT("DATE_W3C", DATE_FORMAT_RFC3339, CONST_CS | CONST_PERSISTENT);
871
872 REGISTER_LONG_CONSTANT("SUNFUNCS_RET_TIMESTAMP", SUNFUNCS_RET_TIMESTAMP, CONST_CS | CONST_PERSISTENT);
873 REGISTER_LONG_CONSTANT("SUNFUNCS_RET_STRING", SUNFUNCS_RET_STRING, CONST_CS | CONST_PERSISTENT);
874 REGISTER_LONG_CONSTANT("SUNFUNCS_RET_DOUBLE", SUNFUNCS_RET_DOUBLE, CONST_CS | CONST_PERSISTENT);
875
876 php_date_global_timezone_db = NULL;
877 php_date_global_timezone_db_enabled = 0;
878 DATEG(last_errors) = NULL;
879 return SUCCESS;
880 }
881
882
883
884 PHP_MSHUTDOWN_FUNCTION(date)
885 {
886 UNREGISTER_INI_ENTRIES();
887
888 if (DATEG(last_errors)) {
889 timelib_error_container_dtor(DATEG(last_errors));
890 }
891
892 #ifndef ZTS
893 DATEG(default_timezone) = NULL;
894 #endif
895
896 return SUCCESS;
897 }
898
899
900
901 PHP_MINFO_FUNCTION(date)
902 {
903 const timelib_tzdb *tzdb = DATE_TIMEZONEDB;
904
905 php_info_print_table_start();
906 php_info_print_table_row(2, "date/time support", "enabled");
907 php_info_print_table_row(2, "\"Olson\" Timezone Database Version", tzdb->version);
908 php_info_print_table_row(2, "Timezone Database", php_date_global_timezone_db_enabled ? "external" : "internal");
909 php_info_print_table_row(2, "Default timezone", guess_timezone(tzdb));
910 php_info_print_table_end();
911
912 DISPLAY_INI_ENTRIES();
913 }
914
915
916
917 static timelib_tzinfo *php_date_parse_tzfile(char *formal_tzname, const timelib_tzdb *tzdb)
918 {
919 timelib_tzinfo *tzi;
920
921 if(!DATEG(tzcache)) {
922 ALLOC_HASHTABLE(DATEG(tzcache));
923 zend_hash_init(DATEG(tzcache), 4, NULL, _php_date_tzinfo_dtor, 0);
924 }
925
926 if ((tzi = zend_hash_str_find_ptr(DATEG(tzcache), formal_tzname, strlen(formal_tzname))) != NULL) {
927 return tzi;
928 }
929
930 tzi = timelib_parse_tzfile(formal_tzname, tzdb);
931 if (tzi) {
932 zend_hash_str_add_ptr(DATEG(tzcache), formal_tzname, strlen(formal_tzname), tzi);
933 }
934 return tzi;
935 }
936
937 timelib_tzinfo *php_date_parse_tzfile_wrapper(char *formal_tzname, const timelib_tzdb *tzdb)
938 {
939 return php_date_parse_tzfile(formal_tzname, tzdb);
940 }
941
942
943
944
945 static PHP_INI_MH(OnUpdate_date_timezone)
946 {
947 if (OnUpdateString(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage) == FAILURE) {
948 return FAILURE;
949 }
950
951 DATEG(timezone_valid) = 0;
952 if (stage == PHP_INI_STAGE_RUNTIME) {
953 if (!timelib_timezone_id_is_valid(DATEG(default_timezone), DATE_TIMEZONEDB)) {
954 if (DATEG(default_timezone) && *DATEG(default_timezone)) {
955 php_error_docref(NULL, E_WARNING, "Invalid date.timezone value '%s', we selected the timezone 'UTC' for now.", DATEG(default_timezone));
956 }
957 } else {
958 DATEG(timezone_valid) = 1;
959 }
960 }
961
962 return SUCCESS;
963 }
964
965
966
967 static char* guess_timezone(const timelib_tzdb *tzdb)
968 {
969
970 if (DATEG(timezone) && (strlen(DATEG(timezone))) > 0) {
971 return DATEG(timezone);
972 }
973
974 if (!DATEG(default_timezone)) {
975
976 zval *ztz;
977
978 if (NULL != (ztz = cfg_get_entry("date.timezone", sizeof("date.timezone")))
979 && Z_TYPE_P(ztz) == IS_STRING && Z_STRLEN_P(ztz) > 0 && timelib_timezone_id_is_valid(Z_STRVAL_P(ztz), tzdb)) {
980 return Z_STRVAL_P(ztz);
981 }
982 } else if (*DATEG(default_timezone)) {
983 if (DATEG(timezone_valid) == 1) {
984 return DATEG(default_timezone);
985 }
986
987 if (!timelib_timezone_id_is_valid(DATEG(default_timezone), tzdb)) {
988 php_error_docref(NULL, E_WARNING, "Invalid date.timezone value '%s', we selected the timezone 'UTC' for now.", DATEG(default_timezone));
989 return "UTC";
990 }
991
992 DATEG(timezone_valid) = 1;
993 return DATEG(default_timezone);
994 }
995
996 return "UTC";
997 }
998
999 PHPAPI timelib_tzinfo *get_timezone_info(void)
1000 {
1001 char *tz;
1002 timelib_tzinfo *tzi;
1003
1004 tz = guess_timezone(DATE_TIMEZONEDB);
1005 tzi = php_date_parse_tzfile(tz, DATE_TIMEZONEDB);
1006 if (! tzi) {
1007 php_error_docref(NULL, E_ERROR, "Timezone database is corrupt - this should *never* happen!");
1008 }
1009 return tzi;
1010 }
1011
1012
1013
1014
1015 #include "zend_smart_str.h"
1016
1017 static char *mon_full_names[] = {
1018 "January", "February", "March", "April",
1019 "May", "June", "July", "August",
1020 "September", "October", "November", "December"
1021 };
1022
1023 static char *mon_short_names[] = {
1024 "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
1025 };
1026
1027 static char *day_full_names[] = {
1028 "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"
1029 };
1030
1031 static char *day_short_names[] = {
1032 "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
1033 };
1034
1035 static char *english_suffix(timelib_sll number)
1036 {
1037 if (number >= 10 && number <= 19) {
1038 return "th";
1039 } else {
1040 switch (number % 10) {
1041 case 1: return "st";
1042 case 2: return "nd";
1043 case 3: return "rd";
1044 }
1045 }
1046 return "th";
1047 }
1048
1049
1050
1051 char *php_date_full_day_name(timelib_sll y, timelib_sll m, timelib_sll d)
1052 {
1053 timelib_sll day_of_week = timelib_day_of_week(y, m, d);
1054 if (day_of_week < 0) {
1055 return "Unknown";
1056 }
1057 return day_full_names[day_of_week];
1058 }
1059
1060 char *php_date_short_day_name(timelib_sll y, timelib_sll m, timelib_sll d)
1061 {
1062 timelib_sll day_of_week = timelib_day_of_week(y, m, d);
1063 if (day_of_week < 0) {
1064 return "Unknown";
1065 }
1066 return day_short_names[day_of_week];
1067 }
1068
1069
1070
1071 static zend_string *date_format(char *format, size_t format_len, timelib_time *t, int localtime)
1072 {
1073 smart_str string = {0};
1074 int i, length = 0;
1075 char buffer[97];
1076 timelib_time_offset *offset = NULL;
1077 timelib_sll isoweek, isoyear;
1078 int rfc_colon;
1079 int weekYearSet = 0;
1080
1081 if (!format_len) {
1082 return ZSTR_EMPTY_ALLOC();
1083 }
1084
1085 if (localtime) {
1086 if (t->zone_type == TIMELIB_ZONETYPE_ABBR) {
1087 offset = timelib_time_offset_ctor();
1088 offset->offset = (t->z - (t->dst * 60)) * -60;
1089 offset->leap_secs = 0;
1090 offset->is_dst = t->dst;
1091 offset->abbr = timelib_strdup(t->tz_abbr);
1092 } else if (t->zone_type == TIMELIB_ZONETYPE_OFFSET) {
1093 offset = timelib_time_offset_ctor();
1094 offset->offset = (t->z) * -60;
1095 offset->leap_secs = 0;
1096 offset->is_dst = 0;
1097 offset->abbr = timelib_malloc(9);
1098 snprintf(offset->abbr, 9, "GMT%c%02d%02d",
1099 localtime ? ((offset->offset < 0) ? '-' : '+') : '+',
1100 localtime ? abs(offset->offset / 3600) : 0,
1101 localtime ? abs((offset->offset % 3600) / 60) : 0 );
1102 } else {
1103 offset = timelib_get_time_zone_info(t->sse, t->tz_info);
1104 }
1105 }
1106
1107 for (i = 0; i < format_len; i++) {
1108 rfc_colon = 0;
1109 switch (format[i]) {
1110
1111 case 'd': length = slprintf(buffer, 32, "%02d", (int) t->d); break;
1112 case 'D': length = slprintf(buffer, 32, "%s", php_date_short_day_name(t->y, t->m, t->d)); break;
1113 case 'j': length = slprintf(buffer, 32, "%d", (int) t->d); break;
1114 case 'l': length = slprintf(buffer, 32, "%s", php_date_full_day_name(t->y, t->m, t->d)); break;
1115 case 'S': length = slprintf(buffer, 32, "%s", english_suffix(t->d)); break;
1116 case 'w': length = slprintf(buffer, 32, "%d", (int) timelib_day_of_week(t->y, t->m, t->d)); break;
1117 case 'N': length = slprintf(buffer, 32, "%d", (int) timelib_iso_day_of_week(t->y, t->m, t->d)); break;
1118 case 'z': length = slprintf(buffer, 32, "%d", (int) timelib_day_of_year(t->y, t->m, t->d)); break;
1119
1120
1121 case 'W':
1122 if(!weekYearSet) { timelib_isoweek_from_date(t->y, t->m, t->d, &isoweek, &isoyear); weekYearSet = 1; }
1123 length = slprintf(buffer, 32, "%02d", (int) isoweek); break;
1124 case 'o':
1125 if(!weekYearSet) { timelib_isoweek_from_date(t->y, t->m, t->d, &isoweek, &isoyear); weekYearSet = 1; }
1126 length = slprintf(buffer, 32, "%d", (int) isoyear); break;
1127
1128
1129 case 'F': length = slprintf(buffer, 32, "%s", mon_full_names[t->m - 1]); break;
1130 case 'm': length = slprintf(buffer, 32, "%02d", (int) t->m); break;
1131 case 'M': length = slprintf(buffer, 32, "%s", mon_short_names[t->m - 1]); break;
1132 case 'n': length = slprintf(buffer, 32, "%d", (int) t->m); break;
1133 case 't': length = slprintf(buffer, 32, "%d", (int) timelib_days_in_month(t->y, t->m)); break;
1134
1135
1136 case 'L': length = slprintf(buffer, 32, "%d", timelib_is_leap((int) t->y)); break;
1137 case 'y': length = slprintf(buffer, 32, "%02d", (int) t->y % 100); break;
1138 case 'Y': length = slprintf(buffer, 32, "%s%04lld", t->y < 0 ? "-" : "", php_date_llabs((timelib_sll) t->y)); break;
1139
1140
1141 case 'a': length = slprintf(buffer, 32, "%s", t->h >= 12 ? "pm" : "am"); break;
1142 case 'A': length = slprintf(buffer, 32, "%s", t->h >= 12 ? "PM" : "AM"); break;
1143 case 'B': {
1144 int retval = (((((long)t->sse)-(((long)t->sse) - ((((long)t->sse) % 86400) + 3600))) * 10) / 864);
1145 while (retval < 0) {
1146 retval += 1000;
1147 }
1148 retval = retval % 1000;
1149 length = slprintf(buffer, 32, "%03d", retval);
1150 break;
1151 }
1152 case 'g': length = slprintf(buffer, 32, "%d", (t->h % 12) ? (int) t->h % 12 : 12); break;
1153 case 'G': length = slprintf(buffer, 32, "%d", (int) t->h); break;
1154 case 'h': length = slprintf(buffer, 32, "%02d", (t->h % 12) ? (int) t->h % 12 : 12); break;
1155 case 'H': length = slprintf(buffer, 32, "%02d", (int) t->h); break;
1156 case 'i': length = slprintf(buffer, 32, "%02d", (int) t->i); break;
1157 case 's': length = slprintf(buffer, 32, "%02d", (int) t->s); break;
1158 case 'u': length = slprintf(buffer, 32, "%06d", (int) floor(t->f * 1000000 + 0.5)); break;
1159 case 'v': length = slprintf(buffer, 32, "%03d", (int) floor(t->f * 1000 + 0.5)); break;
1160
1161
1162 case 'I': length = slprintf(buffer, 32, "%d", localtime ? offset->is_dst : 0); break;
1163 case 'P': rfc_colon = 1;
1164 case 'O': length = slprintf(buffer, 32, "%c%02d%s%02d",
1165 localtime ? ((offset->offset < 0) ? '-' : '+') : '+',
1166 localtime ? abs(offset->offset / 3600) : 0,
1167 rfc_colon ? ":" : "",
1168 localtime ? abs((offset->offset % 3600) / 60) : 0
1169 );
1170 break;
1171 case 'T': length = slprintf(buffer, 32, "%s", localtime ? offset->abbr : "GMT"); break;
1172 case 'e': if (!localtime) {
1173 length = slprintf(buffer, 32, "%s", "UTC");
1174 } else {
1175 switch (t->zone_type) {
1176 case TIMELIB_ZONETYPE_ID:
1177 length = slprintf(buffer, 32, "%s", t->tz_info->name);
1178 break;
1179 case TIMELIB_ZONETYPE_ABBR:
1180 length = slprintf(buffer, 32, "%s", offset->abbr);
1181 break;
1182 case TIMELIB_ZONETYPE_OFFSET:
1183 length = slprintf(buffer, 32, "%c%02d:%02d",
1184 ((offset->offset < 0) ? '-' : '+'),
1185 abs(offset->offset / 3600),
1186 abs((offset->offset % 3600) / 60)
1187 );
1188 break;
1189 }
1190 }
1191 break;
1192 case 'Z': length = slprintf(buffer, 32, "%d", localtime ? offset->offset : 0); break;
1193
1194
1195 case 'c': length = slprintf(buffer, 96, "%04d-%02d-%02dT%02d:%02d:%02d%c%02d:%02d",
1196 (int) t->y, (int) t->m, (int) t->d,
1197 (int) t->h, (int) t->i, (int) t->s,
1198 localtime ? ((offset->offset < 0) ? '-' : '+') : '+',
1199 localtime ? abs(offset->offset / 3600) : 0,
1200 localtime ? abs((offset->offset % 3600) / 60) : 0
1201 );
1202 break;
1203 case 'r': length = slprintf(buffer, 96, "%3s, %02d %3s %04d %02d:%02d:%02d %c%02d%02d",
1204 php_date_short_day_name(t->y, t->m, t->d),
1205 (int) t->d, mon_short_names[t->m - 1],
1206 (int) t->y, (int) t->h, (int) t->i, (int) t->s,
1207 localtime ? ((offset->offset < 0) ? '-' : '+') : '+',
1208 localtime ? abs(offset->offset / 3600) : 0,
1209 localtime ? abs((offset->offset % 3600) / 60) : 0
1210 );
1211 break;
1212 case 'U': length = slprintf(buffer, 32, "%lld", (timelib_sll) t->sse); break;
1213
1214 case '\\': if (i < format_len) i++;
1215
1216 default: buffer[0] = format[i]; buffer[1] = '\0'; length = 1; break;
1217 }
1218 smart_str_appendl(&string, buffer, length);
1219 }
1220
1221 smart_str_0(&string);
1222
1223 if (localtime) {
1224 timelib_time_offset_dtor(offset);
1225 }
1226
1227 return string.s;
1228 }
1229
1230 static void php_date(INTERNAL_FUNCTION_PARAMETERS, int localtime)
1231 {
1232 char *format;
1233 size_t format_len;
1234 zend_long ts;
1235
1236 if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|l", &format, &format_len, &ts) == FAILURE) {
1237 RETURN_FALSE;
1238 }
1239 if (ZEND_NUM_ARGS() == 1) {
1240 ts = time(NULL);
1241 }
1242
1243 RETURN_STR(php_format_date(format, format_len, ts, localtime));
1244 }
1245
1246
1247 PHPAPI zend_string *php_format_date(char *format, size_t format_len, time_t ts, int localtime)
1248 {
1249 timelib_time *t;
1250 timelib_tzinfo *tzi;
1251 zend_string *string;
1252
1253 t = timelib_time_ctor();
1254
1255 if (localtime) {
1256 tzi = get_timezone_info();
1257 t->tz_info = tzi;
1258 t->zone_type = TIMELIB_ZONETYPE_ID;
1259 timelib_unixtime2local(t, ts);
1260 } else {
1261 tzi = NULL;
1262 timelib_unixtime2gmt(t, ts);
1263 }
1264
1265 string = date_format(format, format_len, t, localtime);
1266
1267 timelib_time_dtor(t);
1268 return string;
1269 }
1270
1271
1272
1273
1274 PHPAPI int php_idate(char format, time_t ts, int localtime)
1275 {
1276 timelib_time *t;
1277 timelib_tzinfo *tzi;
1278 int retval = -1;
1279 timelib_time_offset *offset = NULL;
1280 timelib_sll isoweek, isoyear;
1281
1282 t = timelib_time_ctor();
1283
1284 if (!localtime) {
1285 tzi = get_timezone_info();
1286 t->tz_info = tzi;
1287 t->zone_type = TIMELIB_ZONETYPE_ID;
1288 timelib_unixtime2local(t, ts);
1289 } else {
1290 tzi = NULL;
1291 timelib_unixtime2gmt(t, ts);
1292 }
1293
1294 if (!localtime) {
1295 if (t->zone_type == TIMELIB_ZONETYPE_ABBR) {
1296 offset = timelib_time_offset_ctor();
1297 offset->offset = (t->z - (t->dst * 60)) * -60;
1298 offset->leap_secs = 0;
1299 offset->is_dst = t->dst;
1300 offset->abbr = timelib_strdup(t->tz_abbr);
1301 } else if (t->zone_type == TIMELIB_ZONETYPE_OFFSET) {
1302 offset = timelib_time_offset_ctor();
1303 offset->offset = (t->z - (t->dst * 60)) * -60;
1304 offset->leap_secs = 0;
1305 offset->is_dst = t->dst;
1306 offset->abbr = timelib_malloc(9);
1307 snprintf(offset->abbr, 9, "GMT%c%02d%02d",
1308 !localtime ? ((offset->offset < 0) ? '-' : '+') : '+',
1309 !localtime ? abs(offset->offset / 3600) : 0,
1310 !localtime ? abs((offset->offset % 3600) / 60) : 0 );
1311 } else {
1312 offset = timelib_get_time_zone_info(t->sse, t->tz_info);
1313 }
1314 }
1315
1316 timelib_isoweek_from_date(t->y, t->m, t->d, &isoweek, &isoyear);
1317
1318 switch (format) {
1319
1320 case 'd': case 'j': retval = (int) t->d; break;
1321
1322 case 'w': retval = (int) timelib_day_of_week(t->y, t->m, t->d); break;
1323 case 'z': retval = (int) timelib_day_of_year(t->y, t->m, t->d); break;
1324
1325
1326 case 'W': retval = (int) isoweek; break;
1327
1328
1329 case 'm': case 'n': retval = (int) t->m; break;
1330 case 't': retval = (int) timelib_days_in_month(t->y, t->m); break;
1331
1332
1333 case 'L': retval = (int) timelib_is_leap((int) t->y); break;
1334 case 'y': retval = (int) (t->y % 100); break;
1335 case 'Y': retval = (int) t->y; break;
1336
1337
1338 case 'B':
1339 retval = (((((long)t->sse)-(((long)t->sse) - ((((long)t->sse) % 86400) + 3600))) * 10) / 864);
1340 while (retval < 0) {
1341 retval += 1000;
1342 }
1343 retval = retval % 1000;
1344 break;
1345
1346
1347 case 'g': case 'h': retval = (int) ((t->h % 12) ? (int) t->h % 12 : 12); break;
1348 case 'H': case 'G': retval = (int) t->h; break;
1349 case 'i': retval = (int) t->i; break;
1350 case 's': retval = (int) t->s; break;
1351
1352
1353 case 'I': retval = (int) (!localtime ? offset->is_dst : 0); break;
1354 case 'Z': retval = (int) (!localtime ? offset->offset : 0); break;
1355
1356 case 'U': retval = (int) t->sse; break;
1357 }
1358
1359 if (!localtime) {
1360 timelib_time_offset_dtor(offset);
1361 }
1362 timelib_time_dtor(t);
1363
1364 return retval;
1365 }
1366
1367
1368
1369
1370 PHP_FUNCTION(date)
1371 {
1372 php_date(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
1373 }
1374
1375
1376
1377
1378 PHP_FUNCTION(gmdate)
1379 {
1380 php_date(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
1381 }
1382
1383
1384
1385
1386 PHP_FUNCTION(idate)
1387 {
1388 char *format;
1389 size_t format_len;
1390 zend_long ts = 0;
1391 int ret;
1392
1393 if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|l", &format, &format_len, &ts) == FAILURE) {
1394 RETURN_FALSE;
1395 }
1396
1397 if (format_len != 1) {
1398 php_error_docref(NULL, E_WARNING, "idate format is one char");
1399 RETURN_FALSE;
1400 }
1401
1402 if (ZEND_NUM_ARGS() == 1) {
1403 ts = time(NULL);
1404 }
1405
1406 ret = php_idate(format[0], ts, 0);
1407 if (ret == -1) {
1408 php_error_docref(NULL, E_WARNING, "Unrecognized date format token.");
1409 RETURN_FALSE;
1410 }
1411 RETURN_LONG(ret);
1412 }
1413
1414
1415
1416 PHPAPI void php_date_set_tzdb(timelib_tzdb *tzdb)
1417 {
1418 const timelib_tzdb *builtin = timelib_builtin_db();
1419
1420 if (php_version_compare(tzdb->version, builtin->version) > 0) {
1421 php_date_global_timezone_db = tzdb;
1422 php_date_global_timezone_db_enabled = 1;
1423 }
1424 }
1425
1426
1427
1428 PHPAPI zend_long php_parse_date(char *string, zend_long *now)
1429 {
1430 timelib_time *parsed_time;
1431 timelib_error_container *error = NULL;
1432 int error2;
1433 zend_long retval;
1434
1435 parsed_time = timelib_strtotime(string, strlen(string), &error, DATE_TIMEZONEDB, php_date_parse_tzfile_wrapper);
1436 if (error->error_count) {
1437 timelib_time_dtor(parsed_time);
1438 timelib_error_container_dtor(error);
1439 return -1;
1440 }
1441 timelib_error_container_dtor(error);
1442 timelib_update_ts(parsed_time, NULL);
1443 retval = timelib_date_to_int(parsed_time, &error2);
1444 timelib_time_dtor(parsed_time);
1445 if (error2) {
1446 return -1;
1447 }
1448 return retval;
1449 }
1450
1451
1452
1453
1454 PHP_FUNCTION(strtotime)
1455 {
1456 char *times;
1457 size_t time_len;
1458 int error1, error2;
1459 struct timelib_error_container *error;
1460 zend_long preset_ts = 0, ts;
1461 timelib_time *t, *now;
1462 timelib_tzinfo *tzi;
1463
1464 if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|l", ×, &time_len, &preset_ts) == FAILURE || !time_len) {
1465 RETURN_FALSE;
1466 }
1467
1468 tzi = get_timezone_info();
1469
1470 now = timelib_time_ctor();
1471 now->tz_info = tzi;
1472 now->zone_type = TIMELIB_ZONETYPE_ID;
1473 timelib_unixtime2local(now,
1474 (ZEND_NUM_ARGS() == 2) ? (timelib_sll) preset_ts : (timelib_sll) time(NULL));
1475
1476 t = timelib_strtotime(times, time_len, &error, DATE_TIMEZONEDB, php_date_parse_tzfile_wrapper);
1477 error1 = error->error_count;
1478 timelib_error_container_dtor(error);
1479 timelib_fill_holes(t, now, TIMELIB_NO_CLONE);
1480 timelib_update_ts(t, tzi);
1481 ts = timelib_date_to_int(t, &error2);
1482
1483 timelib_time_dtor(now);
1484 timelib_time_dtor(t);
1485
1486 if (error1 || error2) {
1487 RETURN_FALSE;
1488 } else {
1489 RETURN_LONG(ts);
1490 }
1491 }
1492
1493
1494
1495 PHPAPI void php_mktime(INTERNAL_FUNCTION_PARAMETERS, int gmt)
1496 {
1497 zend_long hou = 0, min = 0, sec = 0, mon = 0, day = 0, yea = 0;
1498 timelib_time *now;
1499 timelib_tzinfo *tzi = NULL;
1500 zend_long ts, adjust_seconds = 0;
1501 int error;
1502
1503 if (zend_parse_parameters(ZEND_NUM_ARGS(), "|llllll", &hou, &min, &sec, &mon, &day, &yea) == FAILURE) {
1504 RETURN_FALSE;
1505 }
1506
1507 now = timelib_time_ctor();
1508 if (gmt) {
1509 timelib_unixtime2gmt(now, (timelib_sll) time(NULL));
1510 } else {
1511 tzi = get_timezone_info();
1512 now->tz_info = tzi;
1513 now->zone_type = TIMELIB_ZONETYPE_ID;
1514 timelib_unixtime2local(now, (timelib_sll) time(NULL));
1515 }
1516
1517 switch (ZEND_NUM_ARGS()) {
1518 case 7:
1519
1520 case 6:
1521 if (yea >= 0 && yea < 70) {
1522 yea += 2000;
1523 } else if (yea >= 70 && yea <= 100) {
1524 yea += 1900;
1525 }
1526 now->y = yea;
1527
1528 case 5:
1529 now->d = day;
1530
1531 case 4:
1532 now->m = mon;
1533
1534 case 3:
1535 now->s = sec;
1536
1537 case 2:
1538 now->i = min;
1539
1540 case 1:
1541 now->h = hou;
1542 break;
1543 default:
1544 php_error_docref(NULL, E_DEPRECATED, "You should be using the time() function instead");
1545 }
1546
1547 if (gmt) {
1548 timelib_update_ts(now, NULL);
1549 } else {
1550 timelib_update_ts(now, tzi);
1551 }
1552
1553
1554 ts = timelib_date_to_int(now, &error);
1555 ts += adjust_seconds;
1556 timelib_time_dtor(now);
1557
1558 if (error) {
1559 RETURN_FALSE;
1560 } else {
1561 RETURN_LONG(ts);
1562 }
1563 }
1564
1565
1566
1567
1568 PHP_FUNCTION(mktime)
1569 {
1570 php_mktime(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
1571 }
1572
1573
1574
1575
1576 PHP_FUNCTION(gmmktime)
1577 {
1578 php_mktime(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
1579 }
1580
1581
1582
1583
1584 PHP_FUNCTION(checkdate)
1585 {
1586 zend_long m, d, y;
1587
1588 if (zend_parse_parameters(ZEND_NUM_ARGS(), "lll", &m, &d, &y) == FAILURE) {
1589 RETURN_FALSE;
1590 }
1591
1592 if (y < 1 || y > 32767 || !timelib_valid_date(y, m, d)) {
1593 RETURN_FALSE;
1594 }
1595 RETURN_TRUE;
1596 }
1597
1598
1599 #ifdef HAVE_STRFTIME
1600
1601 PHPAPI void php_strftime(INTERNAL_FUNCTION_PARAMETERS, int gmt)
1602 {
1603 char *format;
1604 size_t format_len;
1605 zend_long timestamp = 0;
1606 struct tm ta;
1607 int max_reallocs = 5;
1608 size_t buf_len = 256, real_len;
1609 timelib_time *ts;
1610 timelib_tzinfo *tzi;
1611 timelib_time_offset *offset = NULL;
1612 zend_string *buf;
1613
1614 timestamp = (zend_long) time(NULL);
1615
1616 if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|l", &format, &format_len, ×tamp) == FAILURE) {
1617 RETURN_FALSE;
1618 }
1619
1620 if (format_len == 0) {
1621 RETURN_FALSE;
1622 }
1623
1624 ts = timelib_time_ctor();
1625 if (gmt) {
1626 tzi = NULL;
1627 timelib_unixtime2gmt(ts, (timelib_sll) timestamp);
1628 } else {
1629 tzi = get_timezone_info();
1630 ts->tz_info = tzi;
1631 ts->zone_type = TIMELIB_ZONETYPE_ID;
1632 timelib_unixtime2local(ts, (timelib_sll) timestamp);
1633 }
1634 ta.tm_sec = ts->s;
1635 ta.tm_min = ts->i;
1636 ta.tm_hour = ts->h;
1637 ta.tm_mday = ts->d;
1638 ta.tm_mon = ts->m - 1;
1639 ta.tm_year = ts->y - 1900;
1640 ta.tm_wday = timelib_day_of_week(ts->y, ts->m, ts->d);
1641 ta.tm_yday = timelib_day_of_year(ts->y, ts->m, ts->d);
1642 if (gmt) {
1643 ta.tm_isdst = 0;
1644 #if HAVE_TM_GMTOFF
1645 ta.tm_gmtoff = 0;
1646 #endif
1647 #if HAVE_TM_ZONE
1648 ta.tm_zone = "GMT";
1649 #endif
1650 } else {
1651 offset = timelib_get_time_zone_info(timestamp, tzi);
1652
1653 ta.tm_isdst = offset->is_dst;
1654 #if HAVE_TM_GMTOFF
1655 ta.tm_gmtoff = offset->offset;
1656 #endif
1657 #if HAVE_TM_ZONE
1658 ta.tm_zone = offset->abbr;
1659 #endif
1660 }
1661
1662
1663
1664
1665 buf = zend_string_alloc(buf_len, 0);
1666 while ((real_len = strftime(ZSTR_VAL(buf), buf_len, format, &ta)) == buf_len || real_len == 0) {
1667 buf_len *= 2;
1668 buf = zend_string_extend(buf, buf_len, 0);
1669 if (!--max_reallocs) {
1670 break;
1671 }
1672 }
1673 #ifdef PHP_WIN32
1674
1675
1676 if (real_len > 0) {
1677 real_len = strlen(buf->val);
1678 }
1679 #endif
1680
1681 timelib_time_dtor(ts);
1682 if (!gmt) {
1683 timelib_time_offset_dtor(offset);
1684 }
1685
1686 if (real_len && real_len != buf_len) {
1687 buf = zend_string_truncate(buf, real_len, 0);
1688 RETURN_NEW_STR(buf);
1689 }
1690 zend_string_free(buf);
1691 RETURN_FALSE;
1692 }
1693
1694
1695
1696
1697 PHP_FUNCTION(strftime)
1698 {
1699 php_strftime(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
1700 }
1701
1702
1703
1704
1705 PHP_FUNCTION(gmstrftime)
1706 {
1707 php_strftime(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
1708 }
1709
1710 #endif
1711
1712
1713
1714 PHP_FUNCTION(time)
1715 {
1716 RETURN_LONG((zend_long)time(NULL));
1717 }
1718
1719
1720
1721
1722 PHP_FUNCTION(localtime)
1723 {
1724 zend_long timestamp = (zend_long)time(NULL);
1725 zend_bool associative = 0;
1726 timelib_tzinfo *tzi;
1727 timelib_time *ts;
1728
1729 if (zend_parse_parameters(ZEND_NUM_ARGS(), "|lb", ×tamp, &associative) == FAILURE) {
1730 RETURN_FALSE;
1731 }
1732
1733 tzi = get_timezone_info();
1734 ts = timelib_time_ctor();
1735 ts->tz_info = tzi;
1736 ts->zone_type = TIMELIB_ZONETYPE_ID;
1737 timelib_unixtime2local(ts, (timelib_sll) timestamp);
1738
1739 array_init(return_value);
1740
1741 if (associative) {
1742 add_assoc_long(return_value, "tm_sec", ts->s);
1743 add_assoc_long(return_value, "tm_min", ts->i);
1744 add_assoc_long(return_value, "tm_hour", ts->h);
1745 add_assoc_long(return_value, "tm_mday", ts->d);
1746 add_assoc_long(return_value, "tm_mon", ts->m - 1);
1747 add_assoc_long(return_value, "tm_year", ts->y - 1900);
1748 add_assoc_long(return_value, "tm_wday", timelib_day_of_week(ts->y, ts->m, ts->d));
1749 add_assoc_long(return_value, "tm_yday", timelib_day_of_year(ts->y, ts->m, ts->d));
1750 add_assoc_long(return_value, "tm_isdst", ts->dst);
1751 } else {
1752 add_next_index_long(return_value, ts->s);
1753 add_next_index_long(return_value, ts->i);
1754 add_next_index_long(return_value, ts->h);
1755 add_next_index_long(return_value, ts->d);
1756 add_next_index_long(return_value, ts->m - 1);
1757 add_next_index_long(return_value, ts->y- 1900);
1758 add_next_index_long(return_value, timelib_day_of_week(ts->y, ts->m, ts->d));
1759 add_next_index_long(return_value, timelib_day_of_year(ts->y, ts->m, ts->d));
1760 add_next_index_long(return_value, ts->dst);
1761 }
1762
1763 timelib_time_dtor(ts);
1764 }
1765
1766
1767
1768
1769 PHP_FUNCTION(getdate)
1770 {
1771 zend_long timestamp = (zend_long)time(NULL);
1772 timelib_tzinfo *tzi;
1773 timelib_time *ts;
1774
1775 if (zend_parse_parameters(ZEND_NUM_ARGS(), "|l", ×tamp) == FAILURE) {
1776 RETURN_FALSE;
1777 }
1778
1779 tzi = get_timezone_info();
1780 ts = timelib_time_ctor();
1781 ts->tz_info = tzi;
1782 ts->zone_type = TIMELIB_ZONETYPE_ID;
1783 timelib_unixtime2local(ts, (timelib_sll) timestamp);
1784
1785 array_init(return_value);
1786
1787 add_assoc_long(return_value, "seconds", ts->s);
1788 add_assoc_long(return_value, "minutes", ts->i);
1789 add_assoc_long(return_value, "hours", ts->h);
1790 add_assoc_long(return_value, "mday", ts->d);
1791 add_assoc_long(return_value, "wday", timelib_day_of_week(ts->y, ts->m, ts->d));
1792 add_assoc_long(return_value, "mon", ts->m);
1793 add_assoc_long(return_value, "year", ts->y);
1794 add_assoc_long(return_value, "yday", timelib_day_of_year(ts->y, ts->m, ts->d));
1795 add_assoc_string(return_value, "weekday", php_date_full_day_name(ts->y, ts->m, ts->d));
1796 add_assoc_string(return_value, "month", mon_full_names[ts->m - 1]);
1797 add_index_long(return_value, 0, timestamp);
1798
1799 timelib_time_dtor(ts);
1800 }
1801
1802
1803 #define PHP_DATE_TIMEZONE_GROUP_AFRICA 0x0001
1804 #define PHP_DATE_TIMEZONE_GROUP_AMERICA 0x0002
1805 #define PHP_DATE_TIMEZONE_GROUP_ANTARCTICA 0x0004
1806 #define PHP_DATE_TIMEZONE_GROUP_ARCTIC 0x0008
1807 #define PHP_DATE_TIMEZONE_GROUP_ASIA 0x0010
1808 #define PHP_DATE_TIMEZONE_GROUP_ATLANTIC 0x0020
1809 #define PHP_DATE_TIMEZONE_GROUP_AUSTRALIA 0x0040
1810 #define PHP_DATE_TIMEZONE_GROUP_EUROPE 0x0080
1811 #define PHP_DATE_TIMEZONE_GROUP_INDIAN 0x0100
1812 #define PHP_DATE_TIMEZONE_GROUP_PACIFIC 0x0200
1813 #define PHP_DATE_TIMEZONE_GROUP_UTC 0x0400
1814 #define PHP_DATE_TIMEZONE_GROUP_ALL 0x07FF
1815 #define PHP_DATE_TIMEZONE_GROUP_ALL_W_BC 0x0FFF
1816 #define PHP_DATE_TIMEZONE_PER_COUNTRY 0x1000
1817
1818 #define PHP_DATE_PERIOD_EXCLUDE_START_DATE 0x0001
1819
1820
1821
1822 typedef struct {
1823 zend_object_iterator intern;
1824 zval current;
1825 php_period_obj *object;
1826 int current_index;
1827 } date_period_it;
1828
1829
1830 static void date_period_it_invalidate_current(zend_object_iterator *iter)
1831 {
1832 date_period_it *iterator = (date_period_it *)iter;
1833
1834 if (Z_TYPE(iterator->current) != IS_UNDEF) {
1835 zval_ptr_dtor(&iterator->current);
1836 ZVAL_UNDEF(&iterator->current);
1837 }
1838 }
1839
1840
1841
1842 static void date_period_it_dtor(zend_object_iterator *iter)
1843 {
1844 date_period_it *iterator = (date_period_it *)iter;
1845
1846 date_period_it_invalidate_current(iter);
1847
1848 zval_ptr_dtor(&iterator->intern.data);
1849 }
1850
1851
1852
1853 static int date_period_it_has_more(zend_object_iterator *iter)
1854 {
1855 date_period_it *iterator = (date_period_it *)iter;
1856 php_period_obj *object = Z_PHPPERIOD_P(&iterator->intern.data);
1857 timelib_time *it_time = object->current;
1858
1859
1860 if (!object->include_start_date || iterator->current_index > 0) {
1861 it_time->have_relative = 1;
1862 it_time->relative = *object->interval;
1863 it_time->sse_uptodate = 0;
1864 timelib_update_ts(it_time, NULL);
1865 timelib_update_from_sse(it_time);
1866 }
1867
1868 if (object->end) {
1869 return object->current->sse < object->end->sse ? SUCCESS : FAILURE;
1870 } else {
1871 return (iterator->current_index < object->recurrences) ? SUCCESS : FAILURE;
1872 }
1873 }
1874
1875
1876
1877 static zval *date_period_it_current_data(zend_object_iterator *iter)
1878 {
1879 date_period_it *iterator = (date_period_it *)iter;
1880 php_period_obj *object = Z_PHPPERIOD_P(&iterator->intern.data);
1881 timelib_time *it_time = object->current;
1882 php_date_obj *newdateobj;
1883
1884
1885 php_date_instantiate(object->start_ce, &iterator->current);
1886 newdateobj = Z_PHPDATE_P(&iterator->current);
1887 newdateobj->time = timelib_time_ctor();
1888 *newdateobj->time = *it_time;
1889 if (it_time->tz_abbr) {
1890 newdateobj->time->tz_abbr = timelib_strdup(it_time->tz_abbr);
1891 }
1892 if (it_time->tz_info) {
1893 newdateobj->time->tz_info = it_time->tz_info;
1894 }
1895
1896 return &iterator->current;
1897 }
1898
1899
1900
1901 static void date_period_it_current_key(zend_object_iterator *iter, zval *key)
1902 {
1903 date_period_it *iterator = (date_period_it *)iter;
1904 ZVAL_LONG(key, iterator->current_index);
1905 }
1906
1907
1908
1909 static void date_period_it_move_forward(zend_object_iterator *iter)
1910 {
1911 date_period_it *iterator = (date_period_it *)iter;
1912
1913 iterator->current_index++;
1914 date_period_it_invalidate_current(iter);
1915 }
1916
1917
1918
1919 static void date_period_it_rewind(zend_object_iterator *iter)
1920 {
1921 date_period_it *iterator = (date_period_it *)iter;
1922
1923 iterator->current_index = 0;
1924 if (iterator->object->current) {
1925 timelib_time_dtor(iterator->object->current);
1926 }
1927 iterator->object->current = timelib_time_clone(iterator->object->start);
1928 date_period_it_invalidate_current(iter);
1929 }
1930
1931
1932
1933 zend_object_iterator_funcs date_period_it_funcs = {
1934 date_period_it_dtor,
1935 date_period_it_has_more,
1936 date_period_it_current_data,
1937 date_period_it_current_key,
1938 date_period_it_move_forward,
1939 date_period_it_rewind,
1940 date_period_it_invalidate_current
1941 };
1942
1943 zend_object_iterator *date_object_period_get_iterator(zend_class_entry *ce, zval *object, int by_ref)
1944 {
1945 date_period_it *iterator = emalloc(sizeof(date_period_it));
1946
1947 if (by_ref) {
1948 zend_error(E_ERROR, "An iterator cannot be used with foreach by reference");
1949 }
1950
1951 zend_iterator_init((zend_object_iterator*)iterator);
1952
1953 ZVAL_COPY(&iterator->intern.data, object);
1954 iterator->intern.funcs = &date_period_it_funcs;
1955 iterator->object = Z_PHPPERIOD_P(object);
1956 ZVAL_UNDEF(&iterator->current);
1957
1958 return (zend_object_iterator*)iterator;
1959 }
1960
1961 static int implement_date_interface_handler(zend_class_entry *interface, zend_class_entry *implementor)
1962 {
1963 if (implementor->type == ZEND_USER_CLASS &&
1964 !instanceof_function(implementor, date_ce_date) &&
1965 !instanceof_function(implementor, date_ce_immutable)
1966 ) {
1967 zend_error(E_ERROR, "DateTimeInterface can't be implemented by user classes");
1968 }
1969
1970 return SUCCESS;
1971 }
1972
1973 static void date_register_classes(void)
1974 {
1975 zend_class_entry ce_date, ce_immutable, ce_timezone, ce_interval, ce_period, ce_interface;
1976
1977 INIT_CLASS_ENTRY(ce_interface, "DateTimeInterface", date_funcs_interface);
1978 date_ce_interface = zend_register_internal_interface(&ce_interface);
1979 date_ce_interface->interface_gets_implemented = implement_date_interface_handler;
1980
1981 INIT_CLASS_ENTRY(ce_date, "DateTime", date_funcs_date);
1982 ce_date.create_object = date_object_new_date;
1983 date_ce_date = zend_register_internal_class_ex(&ce_date, NULL);
1984 memcpy(&date_object_handlers_date, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
1985 date_object_handlers_date.offset = XtOffsetOf(php_date_obj, std);
1986 date_object_handlers_date.free_obj = date_object_free_storage_date;
1987 date_object_handlers_date.clone_obj = date_object_clone_date;
1988 date_object_handlers_date.compare_objects = date_object_compare_date;
1989 date_object_handlers_date.get_properties = date_object_get_properties;
1990 date_object_handlers_date.get_gc = date_object_get_gc;
1991 zend_class_implements(date_ce_date, 1, date_ce_interface);
1992
1993 #define REGISTER_DATE_CLASS_CONST_STRING(const_name, value) \
1994 zend_declare_class_constant_stringl(date_ce_date, const_name, sizeof(const_name)-1, value, sizeof(value)-1);
1995
1996 REGISTER_DATE_CLASS_CONST_STRING("ATOM", DATE_FORMAT_RFC3339);
1997 REGISTER_DATE_CLASS_CONST_STRING("COOKIE", DATE_FORMAT_COOKIE);
1998 REGISTER_DATE_CLASS_CONST_STRING("ISO8601", DATE_FORMAT_ISO8601);
1999 REGISTER_DATE_CLASS_CONST_STRING("RFC822", DATE_FORMAT_RFC822);
2000 REGISTER_DATE_CLASS_CONST_STRING("RFC850", DATE_FORMAT_RFC850);
2001 REGISTER_DATE_CLASS_CONST_STRING("RFC1036", DATE_FORMAT_RFC1036);
2002 REGISTER_DATE_CLASS_CONST_STRING("RFC1123", DATE_FORMAT_RFC1123);
2003 REGISTER_DATE_CLASS_CONST_STRING("RFC2822", DATE_FORMAT_RFC2822);
2004 REGISTER_DATE_CLASS_CONST_STRING("RFC3339", DATE_FORMAT_RFC3339);
2005 REGISTER_DATE_CLASS_CONST_STRING("RFC3339_EXTENDED", DATE_FORMAT_RFC3339_EXTENDED);
2006 REGISTER_DATE_CLASS_CONST_STRING("RSS", DATE_FORMAT_RFC1123);
2007 REGISTER_DATE_CLASS_CONST_STRING("W3C", DATE_FORMAT_RFC3339);
2008
2009 INIT_CLASS_ENTRY(ce_immutable, "DateTimeImmutable", date_funcs_immutable);
2010 ce_immutable.create_object = date_object_new_date;
2011 date_ce_immutable = zend_register_internal_class_ex(&ce_immutable, NULL);
2012 memcpy(&date_object_handlers_immutable, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
2013 date_object_handlers_immutable.clone_obj = date_object_clone_date;
2014 date_object_handlers_immutable.compare_objects = date_object_compare_date;
2015 date_object_handlers_immutable.get_properties = date_object_get_properties;
2016 zend_class_implements(date_ce_immutable, 1, date_ce_interface);
2017
2018 INIT_CLASS_ENTRY(ce_timezone, "DateTimeZone", date_funcs_timezone);
2019 ce_timezone.create_object = date_object_new_timezone;
2020 date_ce_timezone = zend_register_internal_class_ex(&ce_timezone, NULL);
2021 memcpy(&date_object_handlers_timezone, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
2022 date_object_handlers_timezone.offset = XtOffsetOf(php_timezone_obj, std);
2023 date_object_handlers_timezone.free_obj = date_object_free_storage_timezone;
2024 date_object_handlers_timezone.clone_obj = date_object_clone_timezone;
2025 date_object_handlers_timezone.get_properties = date_object_get_properties_timezone;
2026 date_object_handlers_timezone.get_gc = date_object_get_gc_timezone;
2027
2028 #define REGISTER_TIMEZONE_CLASS_CONST_STRING(const_name, value) \
2029 zend_declare_class_constant_long(date_ce_timezone, const_name, sizeof(const_name)-1, value);
2030
2031 REGISTER_TIMEZONE_CLASS_CONST_STRING("AFRICA", PHP_DATE_TIMEZONE_GROUP_AFRICA);
2032 REGISTER_TIMEZONE_CLASS_CONST_STRING("AMERICA", PHP_DATE_TIMEZONE_GROUP_AMERICA);
2033 REGISTER_TIMEZONE_CLASS_CONST_STRING("ANTARCTICA", PHP_DATE_TIMEZONE_GROUP_ANTARCTICA);
2034 REGISTER_TIMEZONE_CLASS_CONST_STRING("ARCTIC", PHP_DATE_TIMEZONE_GROUP_ARCTIC);
2035 REGISTER_TIMEZONE_CLASS_CONST_STRING("ASIA", PHP_DATE_TIMEZONE_GROUP_ASIA);
2036 REGISTER_TIMEZONE_CLASS_CONST_STRING("ATLANTIC", PHP_DATE_TIMEZONE_GROUP_ATLANTIC);
2037 REGISTER_TIMEZONE_CLASS_CONST_STRING("AUSTRALIA", PHP_DATE_TIMEZONE_GROUP_AUSTRALIA);
2038 REGISTER_TIMEZONE_CLASS_CONST_STRING("EUROPE", PHP_DATE_TIMEZONE_GROUP_EUROPE);
2039 REGISTER_TIMEZONE_CLASS_CONST_STRING("INDIAN", PHP_DATE_TIMEZONE_GROUP_INDIAN);
2040 REGISTER_TIMEZONE_CLASS_CONST_STRING("PACIFIC", PHP_DATE_TIMEZONE_GROUP_PACIFIC);
2041 REGISTER_TIMEZONE_CLASS_CONST_STRING("UTC", PHP_DATE_TIMEZONE_GROUP_UTC);
2042 REGISTER_TIMEZONE_CLASS_CONST_STRING("ALL", PHP_DATE_TIMEZONE_GROUP_ALL);
2043 REGISTER_TIMEZONE_CLASS_CONST_STRING("ALL_WITH_BC", PHP_DATE_TIMEZONE_GROUP_ALL_W_BC);
2044 REGISTER_TIMEZONE_CLASS_CONST_STRING("PER_COUNTRY", PHP_DATE_TIMEZONE_PER_COUNTRY);
2045
2046 INIT_CLASS_ENTRY(ce_interval, "DateInterval", date_funcs_interval);
2047 ce_interval.create_object = date_object_new_interval;
2048 date_ce_interval = zend_register_internal_class_ex(&ce_interval, NULL);
2049 memcpy(&date_object_handlers_interval, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
2050 date_object_handlers_interval.offset = XtOffsetOf(php_interval_obj, std);
2051 date_object_handlers_interval.free_obj = date_object_free_storage_interval;
2052 date_object_handlers_interval.clone_obj = date_object_clone_interval;
2053 date_object_handlers_interval.read_property = date_interval_read_property;
2054 date_object_handlers_interval.write_property = date_interval_write_property;
2055 date_object_handlers_interval.get_properties = date_object_get_properties_interval;
2056 date_object_handlers_interval.get_property_ptr_ptr = NULL;
2057 date_object_handlers_interval.get_gc = date_object_get_gc_interval;
2058
2059 INIT_CLASS_ENTRY(ce_period, "DatePeriod", date_funcs_period);
2060 ce_period.create_object = date_object_new_period;
2061 date_ce_period = zend_register_internal_class_ex(&ce_period, NULL);
2062 date_ce_period->get_iterator = date_object_period_get_iterator;
2063 date_ce_period->iterator_funcs.funcs = &date_period_it_funcs;
2064 zend_class_implements(date_ce_period, 1, zend_ce_traversable);
2065 memcpy(&date_object_handlers_period, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
2066 date_object_handlers_period.offset = XtOffsetOf(php_period_obj, std);
2067 date_object_handlers_period.free_obj = date_object_free_storage_period;
2068 date_object_handlers_period.clone_obj = date_object_clone_period;
2069 date_object_handlers_period.get_properties = date_object_get_properties_period;
2070 date_object_handlers_period.get_property_ptr_ptr = NULL;
2071 date_object_handlers_period.get_gc = date_object_get_gc_period;
2072 date_object_handlers_period.read_property = date_period_read_property;
2073 date_object_handlers_period.write_property = date_period_write_property;
2074
2075 #define REGISTER_PERIOD_CLASS_CONST_STRING(const_name, value) \
2076 zend_declare_class_constant_long(date_ce_period, const_name, sizeof(const_name)-1, value);
2077
2078 REGISTER_PERIOD_CLASS_CONST_STRING("EXCLUDE_START_DATE", PHP_DATE_PERIOD_EXCLUDE_START_DATE);
2079 }
2080
2081 static inline zend_object *date_object_new_date_ex(zend_class_entry *class_type, int init_props)
2082 {
2083 php_date_obj *intern;
2084
2085 intern = ecalloc(1, sizeof(php_date_obj) + zend_object_properties_size(class_type));
2086
2087 zend_object_std_init(&intern->std, class_type);
2088 if (init_props) {
2089 object_properties_init(&intern->std, class_type);
2090 }
2091 intern->std.handlers = &date_object_handlers_date;
2092
2093 return &intern->std;
2094 }
2095
2096 static zend_object *date_object_new_date(zend_class_entry *class_type)
2097 {
2098 return date_object_new_date_ex(class_type, 1);
2099 }
2100
2101 static zend_object *date_object_clone_date(zval *this_ptr)
2102 {
2103 php_date_obj *old_obj = Z_PHPDATE_P(this_ptr);
2104 php_date_obj *new_obj = php_date_obj_from_obj(date_object_new_date_ex(old_obj->std.ce, 0));
2105
2106 zend_objects_clone_members(&new_obj->std, &old_obj->std);
2107 if (!old_obj->time) {
2108 return &new_obj->std;
2109 }
2110
2111
2112 new_obj->time = timelib_time_ctor();
2113 *new_obj->time = *old_obj->time;
2114 if (old_obj->time->tz_abbr) {
2115 new_obj->time->tz_abbr = timelib_strdup(old_obj->time->tz_abbr);
2116 }
2117 if (old_obj->time->tz_info) {
2118 new_obj->time->tz_info = old_obj->time->tz_info;
2119 }
2120
2121 return &new_obj->std;
2122 }
2123
2124 static void date_clone_immutable(zval *object, zval *new_object)
2125 {
2126 ZVAL_OBJ(new_object, date_object_clone_date(object));
2127 }
2128
2129 static int date_object_compare_date(zval *d1, zval *d2)
2130 {
2131 php_date_obj *o1 = Z_PHPDATE_P(d1);
2132 php_date_obj *o2 = Z_PHPDATE_P(d2);
2133
2134 if (!o1->time || !o2->time) {
2135 php_error_docref(NULL, E_WARNING, "Trying to compare an incomplete DateTime or DateTimeImmutable object");
2136 return 1;
2137 }
2138 if (!o1->time->sse_uptodate) {
2139 timelib_update_ts(o1->time, o1->time->tz_info);
2140 }
2141 if (!o2->time->sse_uptodate) {
2142 timelib_update_ts(o2->time, o2->time->tz_info);
2143 }
2144
2145 return timelib_time_compare(o1->time, o2->time);
2146 }
2147
2148 static HashTable *date_object_get_gc(zval *object, zval **table, int *n)
2149 {
2150 *table = NULL;
2151 *n = 0;
2152 return zend_std_get_properties(object);
2153 }
2154
2155 static HashTable *date_object_get_gc_timezone(zval *object, zval **table, int *n)
2156 {
2157 *table = NULL;
2158 *n = 0;
2159 return zend_std_get_properties(object);
2160 }
2161
2162 static HashTable *date_object_get_properties(zval *object)
2163 {
2164 HashTable *props;
2165 zval zv;
2166 php_date_obj *dateobj;
2167
2168
2169 dateobj = Z_PHPDATE_P(object);
2170
2171 props = zend_std_get_properties(object);
2172
2173 if (!dateobj->time || GC_G(gc_active)) {
2174 return props;
2175 }
2176
2177
2178 ZVAL_STR(&zv, date_format("Y-m-d H:i:s.u", sizeof("Y-m-d H:i:s.u")-1, dateobj->time, 1));
2179 zend_hash_str_update(props, "date", sizeof("date")-1, &zv);
2180
2181
2182 if (dateobj->time->is_localtime) {
2183 ZVAL_LONG(&zv, dateobj->time->zone_type);
2184 zend_hash_str_update(props, "timezone_type", sizeof("timezone_type")-1, &zv);
2185
2186 switch (dateobj->time->zone_type) {
2187 case TIMELIB_ZONETYPE_ID:
2188 ZVAL_STRING(&zv, dateobj->time->tz_info->name);
2189 break;
2190 case TIMELIB_ZONETYPE_OFFSET: {
2191 zend_string *tmpstr = zend_string_alloc(sizeof("UTC+05:00")-1, 0);
2192 timelib_sll utc_offset = dateobj->time->z;
2193
2194 ZSTR_LEN(tmpstr) = snprintf(ZSTR_VAL(tmpstr), sizeof("+05:00"), "%c%02d:%02d",
2195 utc_offset > 0 ? '-' : '+',
2196 abs(utc_offset / 60),
2197 abs((utc_offset % 60)));
2198
2199 ZVAL_NEW_STR(&zv, tmpstr);
2200 }
2201 break;
2202 case TIMELIB_ZONETYPE_ABBR:
2203 ZVAL_STRING(&zv, dateobj->time->tz_abbr);
2204 break;
2205 }
2206 zend_hash_str_update(props, "timezone", sizeof("timezone")-1, &zv);
2207 }
2208
2209 return props;
2210 }
2211
2212 static inline zend_object *date_object_new_timezone_ex(zend_class_entry *class_type, int init_props)
2213 {
2214 php_timezone_obj *intern;
2215
2216 intern = ecalloc(1, sizeof(php_timezone_obj) + zend_object_properties_size(class_type));
2217
2218 zend_object_std_init(&intern->std, class_type);
2219 if (init_props) {
2220 object_properties_init(&intern->std, class_type);
2221 }
2222 intern->std.handlers = &date_object_handlers_timezone;
2223
2224 return &intern->std;
2225 }
2226
2227 static zend_object *date_object_new_timezone(zend_class_entry *class_type)
2228 {
2229 return date_object_new_timezone_ex(class_type, 1);
2230 }
2231
2232 static zend_object *date_object_clone_timezone(zval *this_ptr)
2233 {
2234 php_timezone_obj *old_obj = Z_PHPTIMEZONE_P(this_ptr);
2235 php_timezone_obj *new_obj = php_timezone_obj_from_obj(date_object_new_timezone_ex(old_obj->std.ce, 0));
2236
2237 zend_objects_clone_members(&new_obj->std, &old_obj->std);
2238 if (!old_obj->initialized) {
2239 return &new_obj->std;
2240 }
2241
2242 new_obj->type = old_obj->type;
2243 new_obj->initialized = 1;
2244 switch (new_obj->type) {
2245 case TIMELIB_ZONETYPE_ID:
2246 new_obj->tzi.tz = old_obj->tzi.tz;
2247 break;
2248 case TIMELIB_ZONETYPE_OFFSET:
2249 new_obj->tzi.utc_offset = old_obj->tzi.utc_offset;
2250 break;
2251 case TIMELIB_ZONETYPE_ABBR:
2252 new_obj->tzi.z.utc_offset = old_obj->tzi.z.utc_offset;
2253 new_obj->tzi.z.dst = old_obj->tzi.z.dst;
2254 new_obj->tzi.z.abbr = timelib_strdup(old_obj->tzi.z.abbr);
2255 break;
2256 }
2257
2258 return &new_obj->std;
2259 }
2260
2261 static HashTable *date_object_get_properties_timezone(zval *object)
2262 {
2263 HashTable *props;
2264 zval zv;
2265 php_timezone_obj *tzobj;
2266
2267
2268 tzobj = Z_PHPTIMEZONE_P(object);
2269
2270 props = zend_std_get_properties(object);
2271
2272 if (!tzobj->initialized) {
2273 return props;
2274 }
2275
2276 ZVAL_LONG(&zv, tzobj->type);
2277 zend_hash_str_update(props, "timezone_type", sizeof("timezone_type")-1, &zv);
2278
2279 switch (tzobj->type) {
2280 case TIMELIB_ZONETYPE_ID:
2281 ZVAL_STRING(&zv, tzobj->tzi.tz->name);
2282 break;
2283 case TIMELIB_ZONETYPE_OFFSET: {
2284 zend_string *tmpstr = zend_string_alloc(sizeof("UTC+05:00")-1, 0);
2285
2286 ZSTR_LEN(tmpstr) = snprintf(ZSTR_VAL(tmpstr), sizeof("+05:00"), "%c%02d:%02d",
2287 tzobj->tzi.utc_offset > 0 ? '-' : '+',
2288 abs(tzobj->tzi.utc_offset / 60),
2289 abs((tzobj->tzi.utc_offset % 60)));
2290
2291 ZVAL_NEW_STR(&zv, tmpstr);
2292 }
2293 break;
2294 case TIMELIB_ZONETYPE_ABBR:
2295 ZVAL_STRING(&zv, tzobj->tzi.z.abbr);
2296 break;
2297 }
2298 zend_hash_str_update(props, "timezone", sizeof("timezone")-1, &zv);
2299
2300 return props;
2301 }
2302
2303 static inline zend_object *date_object_new_interval_ex(zend_class_entry *class_type, int init_props)
2304 {
2305 php_interval_obj *intern;
2306
2307 intern = ecalloc(1, sizeof(php_interval_obj) + zend_object_properties_size(class_type));
2308
2309 zend_object_std_init(&intern->std, class_type);
2310 if (init_props) {
2311 object_properties_init(&intern->std, class_type);
2312 }
2313 intern->std.handlers = &date_object_handlers_interval;
2314
2315 return &intern->std;
2316 }
2317
2318 static zend_object *date_object_new_interval(zend_class_entry *class_type)
2319 {
2320 return date_object_new_interval_ex(class_type, 1);
2321 }
2322
2323 static zend_object *date_object_clone_interval(zval *this_ptr)
2324 {
2325 php_interval_obj *old_obj = Z_PHPINTERVAL_P(this_ptr);
2326 php_interval_obj *new_obj = php_interval_obj_from_obj(date_object_new_interval_ex(old_obj->std.ce, 0));
2327
2328 zend_objects_clone_members(&new_obj->std, &old_obj->std);
2329
2330
2331 return &new_obj->std;
2332 }
2333
2334 static HashTable *date_object_get_gc_interval(zval *object, zval **table, int *n)
2335 {
2336
2337 *table = NULL;
2338 *n = 0;
2339 return zend_std_get_properties(object);
2340 }
2341
2342 static HashTable *date_object_get_properties_interval(zval *object)
2343 {
2344 HashTable *props;
2345 zval zv;
2346 php_interval_obj *intervalobj;
2347
2348 intervalobj = Z_PHPINTERVAL_P(object);
2349
2350 props = zend_std_get_properties(object);
2351
2352 if (!intervalobj->initialized) {
2353 return props;
2354 }
2355
2356 #define PHP_DATE_INTERVAL_ADD_PROPERTY(n,f) \
2357 ZVAL_LONG(&zv, (zend_long)intervalobj->diff->f); \
2358 zend_hash_str_update(props, n, sizeof(n)-1, &zv);
2359
2360 PHP_DATE_INTERVAL_ADD_PROPERTY("y", y);
2361 PHP_DATE_INTERVAL_ADD_PROPERTY("m", m);
2362 PHP_DATE_INTERVAL_ADD_PROPERTY("d", d);
2363 PHP_DATE_INTERVAL_ADD_PROPERTY("h", h);
2364 PHP_DATE_INTERVAL_ADD_PROPERTY("i", i);
2365 PHP_DATE_INTERVAL_ADD_PROPERTY("s", s);
2366 PHP_DATE_INTERVAL_ADD_PROPERTY("weekday", weekday);
2367 PHP_DATE_INTERVAL_ADD_PROPERTY("weekday_behavior", weekday_behavior);
2368 PHP_DATE_INTERVAL_ADD_PROPERTY("first_last_day_of", first_last_day_of);
2369 PHP_DATE_INTERVAL_ADD_PROPERTY("invert", invert);
2370 if (intervalobj->diff->days != -99999) {
2371 PHP_DATE_INTERVAL_ADD_PROPERTY("days", days);
2372 } else {
2373 ZVAL_FALSE(&zv);
2374 zend_hash_str_update(props, "days", sizeof("days")-1, &zv);
2375 }
2376 PHP_DATE_INTERVAL_ADD_PROPERTY("special_type", special.type);
2377 PHP_DATE_INTERVAL_ADD_PROPERTY("special_amount", special.amount);
2378 PHP_DATE_INTERVAL_ADD_PROPERTY("have_weekday_relative", have_weekday_relative);
2379 PHP_DATE_INTERVAL_ADD_PROPERTY("have_special_relative", have_special_relative);
2380
2381 return props;
2382 }
2383
2384 static inline zend_object *date_object_new_period_ex(zend_class_entry *class_type, int init_props)
2385 {
2386 php_period_obj *intern;
2387
2388 intern = ecalloc(1, sizeof(php_period_obj) + zend_object_properties_size(class_type));
2389
2390 zend_object_std_init(&intern->std, class_type);
2391 if (init_props) {
2392 object_properties_init(&intern->std, class_type);
2393 }
2394
2395 intern->std.handlers = &date_object_handlers_period;
2396
2397 return &intern->std;
2398 }
2399
2400 static zend_object *date_object_new_period(zend_class_entry *class_type)
2401 {
2402 return date_object_new_period_ex(class_type, 1);
2403 }
2404
2405 static zend_object *date_object_clone_period(zval *this_ptr)
2406 {
2407 php_period_obj *old_obj = Z_PHPPERIOD_P(this_ptr);
2408 php_period_obj *new_obj = php_period_obj_from_obj(date_object_new_period_ex(old_obj->std.ce, 0));
2409
2410 zend_objects_clone_members(&new_obj->std, &old_obj->std);
2411
2412
2413 return &new_obj->std;
2414 }
2415
2416 static void date_object_free_storage_date(zend_object *object)
2417 {
2418 php_date_obj *intern = php_date_obj_from_obj(object);
2419
2420 if (intern->time) {
2421 timelib_time_dtor(intern->time);
2422 }
2423
2424 zend_object_std_dtor(&intern->std);
2425 }
2426
2427 static void date_object_free_storage_timezone(zend_object *object)
2428 {
2429 php_timezone_obj *intern = php_timezone_obj_from_obj(object);
2430
2431 if (intern->type == TIMELIB_ZONETYPE_ABBR) {
2432 timelib_free(intern->tzi.z.abbr);
2433 }
2434 zend_object_std_dtor(&intern->std);
2435 }
2436
2437 static void date_object_free_storage_interval(zend_object *object)
2438 {
2439 php_interval_obj *intern = php_interval_obj_from_obj(object);
2440
2441 timelib_rel_time_dtor(intern->diff);
2442 zend_object_std_dtor(&intern->std);
2443 }
2444
2445 static void date_object_free_storage_period(zend_object *object)
2446 {
2447 php_period_obj *intern = php_period_obj_from_obj(object);
2448
2449 if (intern->start) {
2450 timelib_time_dtor(intern->start);
2451 }
2452
2453 if (intern->current) {
2454 timelib_time_dtor(intern->current);
2455 }
2456
2457 if (intern->end) {
2458 timelib_time_dtor(intern->end);
2459 }
2460
2461 timelib_rel_time_dtor(intern->interval);
2462 zend_object_std_dtor(&intern->std);
2463 }
2464
2465
2466 PHPAPI zval *php_date_instantiate(zend_class_entry *pce, zval *object)
2467 {
2468 object_init_ex(object, pce);
2469 return object;
2470 }
2471
2472
2473
2474 static void update_errors_warnings(timelib_error_container *last_errors)
2475 {
2476 if (DATEG(last_errors)) {
2477 timelib_error_container_dtor(DATEG(last_errors));
2478 DATEG(last_errors) = NULL;
2479 }
2480 DATEG(last_errors) = last_errors;
2481 }
2482
2483 PHPAPI int php_date_initialize(php_date_obj *dateobj, char *time_str, size_t time_str_len, char *format, zval *timezone_object, int ctor)
2484 {
2485 timelib_time *now;
2486 timelib_tzinfo *tzi = NULL;
2487 timelib_error_container *err = NULL;
2488 int type = TIMELIB_ZONETYPE_ID, new_dst = 0;
2489 char *new_abbr = NULL;
2490 timelib_sll new_offset = 0;
2491
2492 if (dateobj->time) {
2493 timelib_time_dtor(dateobj->time);
2494 }
2495 if (format) {
2496 dateobj->time = timelib_parse_from_format(format, time_str_len ? time_str : "", time_str_len ? time_str_len : 0, &err, DATE_TIMEZONEDB, php_date_parse_tzfile_wrapper);
2497 } else {
2498 dateobj->time = timelib_strtotime(time_str_len ? time_str : "now", time_str_len ? time_str_len : sizeof("now") -1, &err, DATE_TIMEZONEDB, php_date_parse_tzfile_wrapper);
2499 }
2500
2501
2502 update_errors_warnings(err);
2503
2504
2505 if (ctor && err && err->error_count) {
2506
2507 php_error_docref(NULL, E_WARNING, "Failed to parse time string (%s) at position %d (%c): %s", time_str,
2508 err->error_messages[0].position, err->error_messages[0].character, err->error_messages[0].message);
2509 }
2510 if (err && err->error_count) {
2511 timelib_time_dtor(dateobj->time);
2512 dateobj->time = 0;
2513 return 0;
2514 }
2515
2516 if (timezone_object) {
2517 php_timezone_obj *tzobj;
2518
2519 tzobj = Z_PHPTIMEZONE_P(timezone_object);
2520 switch (tzobj->type) {
2521 case TIMELIB_ZONETYPE_ID:
2522 tzi = tzobj->tzi.tz;
2523 break;
2524 case TIMELIB_ZONETYPE_OFFSET:
2525 new_offset = tzobj->tzi.utc_offset;
2526 break;
2527 case TIMELIB_ZONETYPE_ABBR:
2528 new_offset = tzobj->tzi.z.utc_offset;
2529 new_dst = tzobj->tzi.z.dst;
2530 new_abbr = timelib_strdup(tzobj->tzi.z.abbr);
2531 break;
2532 }
2533 type = tzobj->type;
2534 } else if (dateobj->time->tz_info) {
2535 tzi = dateobj->time->tz_info;
2536 } else {
2537 tzi = get_timezone_info();
2538 }
2539
2540 now = timelib_time_ctor();
2541 now->zone_type = type;
2542 switch (type) {
2543 case TIMELIB_ZONETYPE_ID:
2544 now->tz_info = tzi;
2545 break;
2546 case TIMELIB_ZONETYPE_OFFSET:
2547 now->z = new_offset;
2548 break;
2549 case TIMELIB_ZONETYPE_ABBR:
2550 now->z = new_offset;
2551 now->dst = new_dst;
2552 now->tz_abbr = new_abbr;
2553 break;
2554 }
2555 timelib_unixtime2local(now, (timelib_sll) time(NULL));
2556
2557 timelib_fill_holes(dateobj->time, now, TIMELIB_NO_CLONE);
2558 timelib_update_ts(dateobj->time, tzi);
2559 timelib_update_from_sse(dateobj->time);
2560
2561 dateobj->time->have_relative = 0;
2562
2563 timelib_time_dtor(now);
2564
2565 return 1;
2566 }
2567
2568
2569
2570
2571 PHP_FUNCTION(date_create)
2572 {
2573 zval *timezone_object = NULL;
2574 char *time_str = NULL;
2575 size_t time_str_len = 0;
2576
2577 if (zend_parse_parameters(ZEND_NUM_ARGS(), "|sO!", &time_str, &time_str_len, &timezone_object, date_ce_timezone) == FAILURE) {
2578 RETURN_FALSE;
2579 }
2580
2581 php_date_instantiate(date_ce_date, return_value);
2582 if (!php_date_initialize(Z_PHPDATE_P(return_value), time_str, time_str_len, NULL, timezone_object, 0)) {
2583 zval_ptr_dtor(return_value);
2584 RETURN_FALSE;
2585 }
2586 }
2587
2588
2589
2590
2591
2592 PHP_FUNCTION(date_create_immutable)
2593 {
2594 zval *timezone_object = NULL;
2595 char *time_str = NULL;
2596 size_t time_str_len = 0;
2597
2598 if (zend_parse_parameters(ZEND_NUM_ARGS(), "|sO!", &time_str, &time_str_len, &timezone_object, date_ce_timezone) == FAILURE) {
2599 RETURN_FALSE;
2600 }
2601
2602 php_date_instantiate(date_ce_immutable, return_value);
2603 if (!php_date_initialize(Z_PHPDATE_P(return_value), time_str, time_str_len, NULL, timezone_object, 0)) {
2604 zval_ptr_dtor(return_value);
2605 RETURN_FALSE;
2606 }
2607 }
2608
2609
2610
2611
2612
2613 PHP_FUNCTION(date_create_from_format)
2614 {
2615 zval *timezone_object = NULL;
2616 char *time_str = NULL, *format_str = NULL;
2617 size_t time_str_len = 0, format_str_len = 0;
2618
2619 if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss|O!", &format_str, &format_str_len, &time_str, &time_str_len, &timezone_object, date_ce_timezone) == FAILURE) {
2620 RETURN_FALSE;
2621 }
2622
2623 php_date_instantiate(date_ce_date, return_value);
2624 if (!php_date_initialize(Z_PHPDATE_P(return_value), time_str, time_str_len, format_str, timezone_object, 0)) {
2625 zval_ptr_dtor(return_value);
2626 RETURN_FALSE;
2627 }
2628 }
2629
2630
2631
2632
2633
2634 PHP_FUNCTION(date_create_immutable_from_format)
2635 {
2636 zval *timezone_object = NULL;
2637 char *time_str = NULL, *format_str = NULL;
2638 size_t time_str_len = 0, format_str_len = 0;
2639
2640 if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss|O!", &format_str, &format_str_len, &time_str, &time_str_len, &timezone_object, date_ce_timezone) == FAILURE) {
2641 RETURN_FALSE;
2642 }
2643
2644 php_date_instantiate(date_ce_immutable, return_value);
2645 if (!php_date_initialize(Z_PHPDATE_P(return_value), time_str, time_str_len, format_str, timezone_object, 0)) {
2646 zval_ptr_dtor(return_value);
2647 RETURN_FALSE;
2648 }
2649 }
2650
2651
2652
2653
2654
2655 PHP_METHOD(DateTime, __construct)
2656 {
2657 zval *timezone_object = NULL;
2658 char *time_str = NULL;
2659 size_t time_str_len = 0;
2660 zend_error_handling error_handling;
2661
2662 if (FAILURE == zend_parse_parameters_throw(ZEND_NUM_ARGS(), "|sO!", &time_str, &time_str_len, &timezone_object, date_ce_timezone)) {
2663 return;
2664 }
2665
2666 zend_replace_error_handling(EH_THROW, NULL, &error_handling);
2667 php_date_initialize(Z_PHPDATE_P(getThis()), time_str, time_str_len, NULL, timezone_object, 1);
2668 zend_restore_error_handling(&error_handling);
2669 }
2670
2671
2672
2673
2674
2675 PHP_METHOD(DateTimeImmutable, __construct)
2676 {
2677 zval *timezone_object = NULL;
2678 char *time_str = NULL;
2679 size_t time_str_len = 0;
2680 zend_error_handling error_handling;
2681
2682 if (FAILURE == zend_parse_parameters_throw(ZEND_NUM_ARGS(), "|sO!", &time_str, &time_str_len, &timezone_object, date_ce_timezone)) {
2683 return;
2684 }
2685
2686 zend_replace_error_handling(EH_THROW, NULL, &error_handling);
2687 php_date_initialize(Z_PHPDATE_P(getThis()), time_str, time_str_len, NULL, timezone_object, 1);
2688 zend_restore_error_handling(&error_handling);
2689 }
2690
2691
2692
2693
2694
2695 PHP_METHOD(DateTimeImmutable, createFromMutable)
2696 {
2697 zval *datetime_object = NULL;
2698 php_date_obj *new_obj = NULL;
2699 php_date_obj *old_obj = NULL;
2700
2701 if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &datetime_object, date_ce_date) == FAILURE) {
2702 return;
2703 }
2704
2705 php_date_instantiate(date_ce_immutable, return_value);
2706 old_obj = Z_PHPDATE_P(datetime_object);
2707 new_obj = Z_PHPDATE_P(return_value);
2708
2709 new_obj->time = timelib_time_ctor();
2710 *new_obj->time = *old_obj->time;
2711 if (old_obj->time->tz_abbr) {
2712 new_obj->time->tz_abbr = timelib_strdup(old_obj->time->tz_abbr);
2713 }
2714 if (old_obj->time->tz_info) {
2715 new_obj->time->tz_info = old_obj->time->tz_info;
2716 }
2717 }
2718
2719
2720 static int php_date_initialize_from_hash(php_date_obj **dateobj, HashTable *myht)
2721 {
2722 zval *z_date;
2723 zval *z_timezone;
2724 zval *z_timezone_type;
2725 zval tmp_obj;
2726 timelib_tzinfo *tzi;
2727 php_timezone_obj *tzobj;
2728
2729 z_date = zend_hash_str_find(myht, "date", sizeof("data")-1);
2730 if (z_date && Z_TYPE_P(z_date) == IS_STRING) {
2731 z_timezone_type = zend_hash_str_find(myht, "timezone_type", sizeof("timezone_type")-1);
2732 if (z_timezone_type && Z_TYPE_P(z_timezone_type) == IS_LONG) {
2733 z_timezone = zend_hash_str_find(myht, "timezone", sizeof("timezone")-1);
2734 if (z_timezone && Z_TYPE_P(z_timezone) == IS_STRING) {
2735 switch (Z_LVAL_P(z_timezone_type)) {
2736 case TIMELIB_ZONETYPE_OFFSET:
2737 case TIMELIB_ZONETYPE_ABBR: {
2738 char *tmp = emalloc(Z_STRLEN_P(z_date) + Z_STRLEN_P(z_timezone) + 2);
2739 int ret;
2740 snprintf(tmp, Z_STRLEN_P(z_date) + Z_STRLEN_P(z_timezone) + 2, "%s %s", Z_STRVAL_P(z_date), Z_STRVAL_P(z_timezone));
2741 ret = php_date_initialize(*dateobj, tmp, Z_STRLEN_P(z_date) + Z_STRLEN_P(z_timezone) + 1, NULL, NULL, 0);
2742 efree(tmp);
2743 return 1 == ret;
2744 }
2745
2746 case TIMELIB_ZONETYPE_ID: {
2747 int ret;
2748
2749 tzi = php_date_parse_tzfile(Z_STRVAL_P(z_timezone), DATE_TIMEZONEDB);
2750
2751 if (tzi == NULL) {
2752 return 0;
2753 }
2754
2755 tzobj = Z_PHPTIMEZONE_P(php_date_instantiate(date_ce_timezone, &tmp_obj));
2756 tzobj->type = TIMELIB_ZONETYPE_ID;
2757 tzobj->tzi.tz = tzi;
2758 tzobj->initialized = 1;
2759
2760 ret = php_date_initialize(*dateobj, Z_STRVAL_P(z_date), Z_STRLEN_P(z_date), NULL, &tmp_obj, 0);
2761 zval_ptr_dtor(&tmp_obj);
2762 return 1 == ret;
2763 }
2764 }
2765 }
2766 }
2767 }
2768 return 0;
2769 }
2770
2771
2772
2773 PHP_METHOD(DateTime, __set_state)
2774 {
2775 php_date_obj *dateobj;
2776 zval *array;
2777 HashTable *myht;
2778
2779 if (zend_parse_parameters(ZEND_NUM_ARGS(), "a", &array) == FAILURE) {
2780 RETURN_FALSE;
2781 }
2782
2783 myht = Z_ARRVAL_P(array);
2784
2785 php_date_instantiate(date_ce_date, return_value);
2786 dateobj = Z_PHPDATE_P(return_value);
2787 if (!php_date_initialize_from_hash(&dateobj, myht)) {
2788 php_error(E_ERROR, "Invalid serialization data for DateTime object");
2789 }
2790 }
2791
2792
2793
2794
2795 PHP_METHOD(DateTimeImmutable, __set_state)
2796 {
2797 php_date_obj *dateobj;
2798 zval *array;
2799 HashTable *myht;
2800
2801 if (zend_parse_parameters(ZEND_NUM_ARGS(), "a", &array) == FAILURE) {
2802 RETURN_FALSE;
2803 }
2804
2805 myht = Z_ARRVAL_P(array);
2806
2807 php_date_instantiate(date_ce_immutable, return_value);
2808 dateobj = Z_PHPDATE_P(return_value);
2809 if (!php_date_initialize_from_hash(&dateobj, myht)) {
2810 php_error(E_ERROR, "Invalid serialization data for DateTimeImmutable object");
2811 }
2812 }
2813
2814
2815
2816
2817 PHP_METHOD(DateTime, __wakeup)
2818 {
2819 zval *object = getThis();
2820 php_date_obj *dateobj;
2821 HashTable *myht;
2822
2823 dateobj = Z_PHPDATE_P(object);
2824
2825 myht = Z_OBJPROP_P(object);
2826
2827 if (!php_date_initialize_from_hash(&dateobj, myht)) {
2828 php_error(E_ERROR, "Invalid serialization data for DateTime object");
2829 }
2830 }
2831
2832
2833
2834 static void zval_from_error_container(zval *z, timelib_error_container *error)
2835 {
2836 int i;
2837 zval element;
2838
2839 add_assoc_long(z, "warning_count", error->warning_count);
2840 array_init(&element);
2841 for (i = 0; i < error->warning_count; i++) {
2842 add_index_string(&element, error->warning_messages[i].position, error->warning_messages[i].message);
2843 }
2844 add_assoc_zval(z, "warnings", &element);
2845
2846 add_assoc_long(z, "error_count", error->error_count);
2847 array_init(&element);
2848 for (i = 0; i < error->error_count; i++) {
2849 add_index_string(&element, error->error_messages[i].position, error->error_messages[i].message);
2850 }
2851 add_assoc_zval(z, "errors", &element);
2852 }
2853
2854
2855
2856
2857 PHP_FUNCTION(date_get_last_errors)
2858 {
2859 if (DATEG(last_errors)) {
2860 array_init(return_value);
2861 zval_from_error_container(return_value, DATEG(last_errors));
2862 } else {
2863 RETURN_FALSE;
2864 }
2865 }
2866
2867
2868 void php_date_do_return_parsed_time(INTERNAL_FUNCTION_PARAMETERS, timelib_time *parsed_time, struct timelib_error_container *error)
2869 {
2870 zval element;
2871
2872 array_init(return_value);
2873 #define PHP_DATE_PARSE_DATE_SET_TIME_ELEMENT(name, elem) \
2874 if (parsed_time->elem == -99999) { \
2875 add_assoc_bool(return_value, #name, 0); \
2876 } else { \
2877 add_assoc_long(return_value, #name, parsed_time->elem); \
2878 }
2879 PHP_DATE_PARSE_DATE_SET_TIME_ELEMENT(year, y);
2880 PHP_DATE_PARSE_DATE_SET_TIME_ELEMENT(month, m);
2881 PHP_DATE_PARSE_DATE_SET_TIME_ELEMENT(day, d);
2882 PHP_DATE_PARSE_DATE_SET_TIME_ELEMENT(hour, h);
2883 PHP_DATE_PARSE_DATE_SET_TIME_ELEMENT(minute, i);
2884 PHP_DATE_PARSE_DATE_SET_TIME_ELEMENT(second, s);
2885
2886 if (parsed_time->f == -99999) {
2887 add_assoc_bool(return_value, "fraction", 0);
2888 } else {
2889 add_assoc_double(return_value, "fraction", parsed_time->f);
2890 }
2891
2892 zval_from_error_container(return_value, error);
2893
2894 timelib_error_container_dtor(error);
2895
2896 add_assoc_bool(return_value, "is_localtime", parsed_time->is_localtime);
2897
2898 if (parsed_time->is_localtime) {
2899 PHP_DATE_PARSE_DATE_SET_TIME_ELEMENT(zone_type, zone_type);
2900 switch (parsed_time->zone_type) {
2901 case TIMELIB_ZONETYPE_OFFSET:
2902 PHP_DATE_PARSE_DATE_SET_TIME_ELEMENT(zone, z);
2903 add_assoc_bool(return_value, "is_dst", parsed_time->dst);
2904 break;
2905 case TIMELIB_ZONETYPE_ID:
2906 if (parsed_time->tz_abbr) {
2907 add_assoc_string(return_value, "tz_abbr", parsed_time->tz_abbr);
2908 }
2909 if (parsed_time->tz_info) {
2910 add_assoc_string(return_value, "tz_id", parsed_time->tz_info->name);
2911 }
2912 break;
2913 case TIMELIB_ZONETYPE_ABBR:
2914 PHP_DATE_PARSE_DATE_SET_TIME_ELEMENT(zone, z);
2915 add_assoc_bool(return_value, "is_dst", parsed_time->dst);
2916 add_assoc_string(return_value, "tz_abbr", parsed_time->tz_abbr);
2917 break;
2918 }
2919 }
2920 if (parsed_time->have_relative) {
2921 array_init(&element);
2922 add_assoc_long(&element, "year", parsed_time->relative.y);
2923 add_assoc_long(&element, "month", parsed_time->relative.m);
2924 add_assoc_long(&element, "day", parsed_time->relative.d);
2925 add_assoc_long(&element, "hour", parsed_time->relative.h);
2926 add_assoc_long(&element, "minute", parsed_time->relative.i);
2927 add_assoc_long(&element, "second", parsed_time->relative.s);
2928 if (parsed_time->relative.have_weekday_relative) {
2929 add_assoc_long(&element, "weekday", parsed_time->relative.weekday);
2930 }
2931 if (parsed_time->relative.have_special_relative && (parsed_time->relative.special.type == TIMELIB_SPECIAL_WEEKDAY)) {
2932 add_assoc_long(&element, "weekdays", parsed_time->relative.special.amount);
2933 }
2934 if (parsed_time->relative.first_last_day_of) {
2935 add_assoc_bool(&element, parsed_time->relative.first_last_day_of == TIMELIB_SPECIAL_FIRST_DAY_OF_MONTH ? "first_day_of_month" : "last_day_of_month", 1);
2936 }
2937 add_assoc_zval(return_value, "relative", &element);
2938 }
2939 timelib_time_dtor(parsed_time);
2940 }
2941
2942
2943
2944
2945 PHP_FUNCTION(date_parse)
2946 {
2947 char *date;
2948 size_t date_len;
2949 struct timelib_error_container *error;
2950 timelib_time *parsed_time;
2951
2952 if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &date, &date_len) == FAILURE) {
2953 RETURN_FALSE;
2954 }
2955
2956 parsed_time = timelib_strtotime(date, date_len, &error, DATE_TIMEZONEDB, php_date_parse_tzfile_wrapper);
2957 php_date_do_return_parsed_time(INTERNAL_FUNCTION_PARAM_PASSTHRU, parsed_time, error);
2958 }
2959
2960
2961
2962
2963
2964 PHP_FUNCTION(date_parse_from_format)
2965 {
2966 char *date, *format;
2967 size_t date_len, format_len;
2968 struct timelib_error_container *error;
2969 timelib_time *parsed_time;
2970
2971 if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss", &format, &format_len, &date, &date_len) == FAILURE) {
2972 RETURN_FALSE;
2973 }
2974
2975 parsed_time = timelib_parse_from_format(format, date, date_len, &error, DATE_TIMEZONEDB, php_date_parse_tzfile_wrapper);
2976 php_date_do_return_parsed_time(INTERNAL_FUNCTION_PARAM_PASSTHRU, parsed_time, error);
2977 }
2978
2979
2980
2981
2982
2983 PHP_FUNCTION(date_format)
2984 {
2985 zval *object;
2986 php_date_obj *dateobj;
2987 char *format;
2988 size_t format_len;
2989
2990 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Os", &object, date_ce_interface, &format, &format_len) == FAILURE) {
2991 RETURN_FALSE;
2992 }
2993 dateobj = Z_PHPDATE_P(object);
2994 DATE_CHECK_INITIALIZED(dateobj->time, DateTime);
2995 RETURN_STR(date_format(format, format_len, dateobj->time, dateobj->time->is_localtime));
2996 }
2997
2998
2999 static int php_date_modify(zval *object, char *modify, size_t modify_len)
3000 {
3001 php_date_obj *dateobj;
3002 timelib_time *tmp_time;
3003 timelib_error_container *err = NULL;
3004
3005 dateobj = Z_PHPDATE_P(object);
3006
3007 if (!(dateobj->time)) {
3008 php_error_docref(NULL, E_WARNING, "The DateTime object has not been correctly initialized by its constructor");
3009 return 0;
3010 }
3011
3012 tmp_time = timelib_strtotime(modify, modify_len, &err, DATE_TIMEZONEDB, php_date_parse_tzfile_wrapper);
3013
3014
3015 update_errors_warnings(err);
3016 if (err && err->error_count) {
3017
3018 php_error_docref(NULL, E_WARNING, "Failed to parse time string (%s) at position %d (%c): %s", modify,
3019 err->error_messages[0].position, err->error_messages[0].character, err->error_messages[0].message);
3020 timelib_time_dtor(tmp_time);
3021 return 0;
3022 }
3023
3024 memcpy(&dateobj->time->relative, &tmp_time->relative, sizeof(struct timelib_rel_time));
3025 dateobj->time->have_relative = tmp_time->have_relative;
3026 dateobj->time->sse_uptodate = 0;
3027
3028 if (tmp_time->y != -99999) {
3029 dateobj->time->y = tmp_time->y;
3030 }
3031 if (tmp_time->m != -99999) {
3032 dateobj->time->m = tmp_time->m;
3033 }
3034 if (tmp_time->d != -99999) {
3035 dateobj->time->d = tmp_time->d;
3036 }
3037
3038 if (tmp_time->h != -99999) {
3039 dateobj->time->h = tmp_time->h;
3040 if (tmp_time->i != -99999) {
3041 dateobj->time->i = tmp_time->i;
3042 if (tmp_time->s != -99999) {
3043 dateobj->time->s = tmp_time->s;
3044 } else {
3045 dateobj->time->s = 0;
3046 }
3047 } else {
3048 dateobj->time->i = 0;
3049 dateobj->time->s = 0;
3050 }
3051 }
3052 timelib_time_dtor(tmp_time);
3053
3054 timelib_update_ts(dateobj->time, NULL);
3055 timelib_update_from_sse(dateobj->time);
3056 dateobj->time->have_relative = 0;
3057 memset(&dateobj->time->relative, 0, sizeof(dateobj->time->relative));
3058
3059 return 1;
3060 }
3061
3062
3063
3064
3065 PHP_FUNCTION(date_modify)
3066 {
3067 zval *object;
3068 char *modify;
3069 size_t modify_len;
3070
3071 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Os", &object, date_ce_date, &modify, &modify_len) == FAILURE) {
3072 RETURN_FALSE;
3073 }
3074
3075 if (!php_date_modify(object, modify, modify_len)) {
3076 RETURN_FALSE;
3077 }
3078
3079 Z_ADDREF_P(object);
3080 ZVAL_COPY_VALUE(return_value, object);
3081 }
3082
3083
3084
3085
3086 PHP_METHOD(DateTimeImmutable, modify)
3087 {
3088 zval *object, new_object;
3089 char *modify;
3090 size_t modify_len;
3091
3092 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Os", &object, date_ce_immutable, &modify, &modify_len) == FAILURE) {
3093 RETURN_FALSE;
3094 }
3095
3096 date_clone_immutable(object, &new_object);
3097 if (!php_date_modify(&new_object, modify, modify_len)) {
3098 RETURN_FALSE;
3099 }
3100
3101 ZVAL_COPY_VALUE(return_value, &new_object);
3102 }
3103
3104
3105 static void php_date_add(zval *object, zval *interval, zval *return_value)
3106 {
3107 php_date_obj *dateobj;
3108 php_interval_obj *intobj;
3109 timelib_time *new_time;
3110
3111 dateobj = Z_PHPDATE_P(object);
3112 DATE_CHECK_INITIALIZED(dateobj->time, DateTime);
3113 intobj = Z_PHPINTERVAL_P(interval);
3114 DATE_CHECK_INITIALIZED(intobj->initialized, DateInterval);
3115
3116 new_time = timelib_add(dateobj->time, intobj->diff);
3117 timelib_time_dtor(dateobj->time);
3118 dateobj->time = new_time;
3119 }
3120
3121
3122
3123
3124 PHP_FUNCTION(date_add)
3125 {
3126 zval *object, *interval;
3127
3128 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "OO", &object, date_ce_date, &interval, date_ce_interval) == FAILURE) {
3129 RETURN_FALSE;
3130 }
3131
3132 php_date_add(object, interval, return_value);
3133
3134 Z_ADDREF_P(object);
3135 ZVAL_COPY_VALUE(return_value, object);
3136 }
3137
3138
3139
3140
3141 PHP_METHOD(DateTimeImmutable, add)
3142 {
3143 zval *object, *interval, new_object;
3144
3145 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "OO", &object, date_ce_immutable, &interval, date_ce_interval) == FAILURE) {
3146 RETURN_FALSE;
3147 }
3148
3149 date_clone_immutable(object, &new_object);
3150 php_date_add(&new_object, interval, return_value);
3151
3152 ZVAL_COPY_VALUE(return_value, &new_object);
3153 }
3154
3155
3156 static void php_date_sub(zval *object, zval *interval, zval *return_value)
3157 {
3158 php_date_obj *dateobj;
3159 php_interval_obj *intobj;
3160 timelib_time *new_time;
3161
3162 dateobj = Z_PHPDATE_P(object);
3163 DATE_CHECK_INITIALIZED(dateobj->time, DateTime);
3164 intobj = Z_PHPINTERVAL_P(interval);
3165 DATE_CHECK_INITIALIZED(intobj->initialized, DateInterval);
3166
3167 if (intobj->diff->have_special_relative) {
3168 php_error_docref(NULL, E_WARNING, "Only non-special relative time specifications are supported for subtraction");
3169 return;
3170 }
3171
3172 new_time = timelib_sub(dateobj->time, intobj->diff);
3173 timelib_time_dtor(dateobj->time);
3174 dateobj->time = new_time;
3175 }
3176
3177
3178
3179
3180 PHP_FUNCTION(date_sub)
3181 {
3182 zval *object, *interval;
3183
3184 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "OO", &object, date_ce_date, &interval, date_ce_interval) == FAILURE) {
3185 RETURN_FALSE;
3186 }
3187
3188 php_date_sub(object, interval, return_value);
3189
3190 Z_ADDREF_P(object);
3191 ZVAL_COPY_VALUE(return_value, object);
3192 }
3193
3194
3195
3196
3197 PHP_METHOD(DateTimeImmutable, sub)
3198 {
3199 zval *object, *interval, new_object;
3200
3201 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "OO", &object, date_ce_immutable, &interval, date_ce_interval) == FAILURE) {
3202 RETURN_FALSE;
3203 }
3204
3205 date_clone_immutable(object, &new_object);
3206 php_date_sub(&new_object, interval, return_value);
3207
3208 ZVAL_COPY_VALUE(return_value, &new_object);
3209 }
3210
3211
3212 static void set_timezone_from_timelib_time(php_timezone_obj *tzobj, timelib_time *t)
3213 {
3214 tzobj->initialized = 1;
3215 tzobj->type = t->zone_type;
3216 switch (t->zone_type) {
3217 case TIMELIB_ZONETYPE_ID:
3218 tzobj->tzi.tz = t->tz_info;
3219 break;
3220 case TIMELIB_ZONETYPE_OFFSET:
3221 tzobj->tzi.utc_offset = t->z;
3222 break;
3223 case TIMELIB_ZONETYPE_ABBR:
3224 tzobj->tzi.z.utc_offset = t->z;
3225 tzobj->tzi.z.dst = t->dst;
3226 tzobj->tzi.z.abbr = timelib_strdup(t->tz_abbr);
3227 break;
3228 }
3229 }
3230
3231
3232
3233
3234
3235 PHP_FUNCTION(date_timezone_get)
3236 {
3237 zval *object;
3238 php_date_obj *dateobj;
3239 php_timezone_obj *tzobj;
3240
3241 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &object, date_ce_interface) == FAILURE) {
3242 RETURN_FALSE;
3243 }
3244 dateobj = Z_PHPDATE_P(object);
3245 DATE_CHECK_INITIALIZED(dateobj->time, DateTime);
3246 if (dateobj->time->is_localtime) {
3247 php_date_instantiate(date_ce_timezone, return_value);
3248 tzobj = Z_PHPTIMEZONE_P(return_value);
3249 set_timezone_from_timelib_time(tzobj, dateobj->time);
3250 } else {
3251 RETURN_FALSE;
3252 }
3253 }
3254
3255
3256 static void php_date_timezone_set(zval *object, zval *timezone_object, zval *return_value)
3257 {
3258 php_date_obj *dateobj;
3259 php_timezone_obj *tzobj;
3260
3261 dateobj = Z_PHPDATE_P(object);
3262 DATE_CHECK_INITIALIZED(dateobj->time, DateTime);
3263 tzobj = Z_PHPTIMEZONE_P(timezone_object);
3264
3265 switch (tzobj->type) {
3266 case TIMELIB_ZONETYPE_OFFSET:
3267 timelib_set_timezone_from_offset(dateobj->time, tzobj->tzi.utc_offset);
3268 break;
3269 case TIMELIB_ZONETYPE_ABBR:
3270 timelib_set_timezone_from_abbr(dateobj->time, tzobj->tzi.z);
3271 break;
3272 case TIMELIB_ZONETYPE_ID:
3273 timelib_set_timezone(dateobj->time, tzobj->tzi.tz);
3274 break;
3275 }
3276 timelib_unixtime2local(dateobj->time, dateobj->time->sse);
3277 }
3278
3279
3280
3281
3282 PHP_FUNCTION(date_timezone_set)
3283 {
3284 zval *object;
3285 zval *timezone_object;
3286
3287 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "OO", &object, date_ce_date, &timezone_object, date_ce_timezone) == FAILURE) {
3288 RETURN_FALSE;
3289 }
3290
3291 php_date_timezone_set(object, timezone_object, return_value);
3292
3293 Z_ADDREF_P(object);
3294 ZVAL_COPY_VALUE(return_value, object);
3295 }
3296
3297
3298
3299
3300 PHP_METHOD(DateTimeImmutable, setTimezone)
3301 {
3302 zval *object, new_object;
3303 zval *timezone_object;
3304
3305 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "OO", &object, date_ce_immutable, &timezone_object, date_ce_timezone) == FAILURE) {
3306 RETURN_FALSE;
3307 }
3308
3309 date_clone_immutable(object, &new_object);
3310 php_date_timezone_set(&new_object, timezone_object, return_value);
3311
3312 ZVAL_COPY_VALUE(return_value, &new_object);
3313 }
3314
3315
3316
3317
3318
3319 PHP_FUNCTION(date_offset_get)
3320 {
3321 zval *object;
3322 php_date_obj *dateobj;
3323 timelib_time_offset *offset;
3324
3325 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &object, date_ce_interface) == FAILURE) {
3326 RETURN_FALSE;
3327 }
3328 dateobj = Z_PHPDATE_P(object);
3329 DATE_CHECK_INITIALIZED(dateobj->time, DateTime);
3330 if (dateobj->time->is_localtime) {
3331 switch (dateobj->time->zone_type) {
3332 case TIMELIB_ZONETYPE_ID:
3333 offset = timelib_get_time_zone_info(dateobj->time->sse, dateobj->time->tz_info);
3334 RETVAL_LONG(offset->offset);
3335 timelib_time_offset_dtor(offset);
3336 break;
3337 case TIMELIB_ZONETYPE_OFFSET:
3338 RETVAL_LONG(dateobj->time->z * -60);
3339 break;
3340 case TIMELIB_ZONETYPE_ABBR:
3341 RETVAL_LONG((dateobj->time->z - (60 * dateobj->time->dst)) * -60);
3342 break;
3343 }
3344 return;
3345 } else {
3346 RETURN_LONG(0);
3347 }
3348 }
3349
3350
3351 static void php_date_time_set(zval *object, zend_long h, zend_long i, zend_long s, zval *return_value)
3352 {
3353 php_date_obj *dateobj;
3354
3355 dateobj = Z_PHPDATE_P(object);
3356 DATE_CHECK_INITIALIZED(dateobj->time, DateTime);
3357 dateobj->time->h = h;
3358 dateobj->time->i = i;
3359 dateobj->time->s = s;
3360 timelib_update_ts(dateobj->time, NULL);
3361 }
3362
3363
3364
3365
3366 PHP_FUNCTION(date_time_set)
3367 {
3368 zval *object;
3369 zend_long h, i, s = 0;
3370
3371 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Oll|l", &object, date_ce_date, &h, &i, &s) == FAILURE) {
3372 RETURN_FALSE;
3373 }
3374
3375 php_date_time_set(object, h, i, s, return_value);
3376
3377 Z_ADDREF_P(object);
3378 ZVAL_COPY_VALUE(return_value, object);
3379 }
3380
3381
3382
3383
3384 PHP_METHOD(DateTimeImmutable, setTime)
3385 {
3386 zval *object, new_object;
3387 zend_long h, i, s = 0;
3388
3389 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Oll|l", &object, date_ce_immutable, &h, &i, &s) == FAILURE) {
3390 RETURN_FALSE;
3391 }
3392
3393 date_clone_immutable(object, &new_object);
3394 php_date_time_set(&new_object, h, i, s, return_value);
3395
3396 ZVAL_COPY_VALUE(return_value, &new_object);
3397 }
3398
3399
3400 static void php_date_date_set(zval *object, zend_long y, zend_long m, zend_long d, zval *return_value)
3401 {
3402 php_date_obj *dateobj;
3403
3404 dateobj = Z_PHPDATE_P(object);
3405 DATE_CHECK_INITIALIZED(dateobj->time, DateTime);
3406 dateobj->time->y = y;
3407 dateobj->time->m = m;
3408 dateobj->time->d = d;
3409 timelib_update_ts(dateobj->time, NULL);
3410 }
3411
3412
3413
3414
3415 PHP_FUNCTION(date_date_set)
3416 {
3417 zval *object;
3418 zend_long y, m, d;
3419
3420 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Olll", &object, date_ce_date, &y, &m, &d) == FAILURE) {
3421 RETURN_FALSE;
3422 }
3423
3424 php_date_date_set(object, y, m, d, return_value);
3425
3426 Z_ADDREF_P(object);
3427 ZVAL_COPY_VALUE(return_value, object);
3428 }
3429
3430
3431
3432
3433 PHP_METHOD(DateTimeImmutable, setDate)
3434 {
3435 zval *object, new_object;
3436 zend_long y, m, d;
3437
3438 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Olll", &object, date_ce_immutable, &y, &m, &d) == FAILURE) {
3439 RETURN_FALSE;
3440 }
3441
3442 date_clone_immutable(object, &new_object);
3443 php_date_date_set(&new_object, y, m, d, return_value);
3444
3445 ZVAL_COPY_VALUE(return_value, &new_object);
3446 }
3447
3448
3449 static void php_date_isodate_set(zval *object, zend_long y, zend_long w, zend_long d, zval *return_value)
3450 {
3451 php_date_obj *dateobj;
3452
3453 dateobj = Z_PHPDATE_P(object);
3454 DATE_CHECK_INITIALIZED(dateobj->time, DateTime);
3455 dateobj->time->y = y;
3456 dateobj->time->m = 1;
3457 dateobj->time->d = 1;
3458 memset(&dateobj->time->relative, 0, sizeof(dateobj->time->relative));
3459 dateobj->time->relative.d = timelib_daynr_from_weeknr(y, w, d);
3460 dateobj->time->have_relative = 1;
3461
3462 timelib_update_ts(dateobj->time, NULL);
3463 }
3464
3465
3466
3467
3468 PHP_FUNCTION(date_isodate_set)
3469 {
3470 zval *object;
3471 zend_long y, w, d = 1;
3472
3473 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Oll|l", &object, date_ce_date, &y, &w, &d) == FAILURE) {
3474 RETURN_FALSE;
3475 }
3476
3477 php_date_isodate_set(object, y, w, d, return_value);
3478
3479 Z_ADDREF_P(object);
3480 ZVAL_COPY_VALUE(return_value, object);
3481 }
3482
3483
3484
3485
3486 PHP_METHOD(DateTimeImmutable, setISODate)
3487 {
3488 zval *object, new_object;
3489 zend_long y, w, d = 1;
3490
3491 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Oll|l", &object, date_ce_immutable, &y, &w, &d) == FAILURE) {
3492 RETURN_FALSE;
3493 }
3494
3495 date_clone_immutable(object, &new_object);
3496 php_date_isodate_set(&new_object, y, w, d, return_value);
3497
3498 ZVAL_COPY_VALUE(return_value, &new_object);
3499 }
3500
3501
3502 static void php_date_timestamp_set(zval *object, zend_long timestamp, zval *return_value)
3503 {
3504 php_date_obj *dateobj;
3505
3506 dateobj = Z_PHPDATE_P(object);
3507 DATE_CHECK_INITIALIZED(dateobj->time, DateTime);
3508 timelib_unixtime2local(dateobj->time, (timelib_sll)timestamp);
3509 timelib_update_ts(dateobj->time, NULL);
3510 }
3511
3512
3513
3514
3515 PHP_FUNCTION(date_timestamp_set)
3516 {
3517 zval *object;
3518 zend_long timestamp;
3519
3520 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Ol", &object, date_ce_date, ×tamp) == FAILURE) {
3521 RETURN_FALSE;
3522 }
3523
3524 php_date_timestamp_set(object, timestamp, return_value);
3525
3526 Z_ADDREF_P(object);
3527 ZVAL_COPY_VALUE(return_value, object);
3528 }
3529
3530
3531
3532
3533 PHP_METHOD(DateTimeImmutable, setTimestamp)
3534 {
3535 zval *object, new_object;
3536 zend_long timestamp;
3537
3538 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Ol", &object, date_ce_immutable, ×tamp) == FAILURE) {
3539 RETURN_FALSE;
3540 }
3541
3542 date_clone_immutable(object, &new_object);
3543 php_date_timestamp_set(&new_object, timestamp, return_value);
3544
3545 ZVAL_COPY_VALUE(return_value, &new_object);
3546 }
3547
3548
3549
3550
3551
3552 PHP_FUNCTION(date_timestamp_get)
3553 {
3554 zval *object;
3555 php_date_obj *dateobj;
3556 zend_long timestamp;
3557 int error;
3558
3559 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &object, date_ce_interface) == FAILURE) {
3560 RETURN_FALSE;
3561 }
3562 dateobj = Z_PHPDATE_P(object);
3563 DATE_CHECK_INITIALIZED(dateobj->time, DateTime);
3564 timelib_update_ts(dateobj->time, NULL);
3565
3566 timestamp = timelib_date_to_int(dateobj->time, &error);
3567 if (error) {
3568 RETURN_FALSE;
3569 } else {
3570 RETVAL_LONG(timestamp);
3571 }
3572 }
3573
3574
3575
3576
3577
3578 PHP_FUNCTION(date_diff)
3579 {
3580 zval *object1, *object2;
3581 php_date_obj *dateobj1, *dateobj2;
3582 php_interval_obj *interval;
3583 zend_bool absolute = 0;
3584
3585 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "OO|b", &object1, date_ce_interface, &object2, date_ce_interface, &absolute) == FAILURE) {
3586 RETURN_FALSE;
3587 }
3588 dateobj1 = Z_PHPDATE_P(object1);
3589 dateobj2 = Z_PHPDATE_P(object2);
3590 DATE_CHECK_INITIALIZED(dateobj1->time, DateTimeInterface);
3591 DATE_CHECK_INITIALIZED(dateobj2->time, DateTimeInterface);
3592 timelib_update_ts(dateobj1->time, NULL);
3593 timelib_update_ts(dateobj2->time, NULL);
3594
3595 php_date_instantiate(date_ce_interval, return_value);
3596 interval = Z_PHPINTERVAL_P(return_value);
3597 interval->diff = timelib_diff(dateobj1->time, dateobj2->time);
3598 if (absolute) {
3599 interval->diff->invert = 0;
3600 }
3601 interval->initialized = 1;
3602 }
3603
3604
3605 static int timezone_initialize(php_timezone_obj *tzobj, char *tz, size_t tz_len)
3606 {
3607 timelib_time *dummy_t = ecalloc(1, sizeof(timelib_time));
3608 int dst, not_found;
3609 char *orig_tz = tz;
3610
3611 if (strlen(tz) != tz_len) {
3612 php_error_docref(NULL, E_WARNING, "Timezone must not contain null bytes");
3613 return FAILURE;
3614 }
3615
3616 dummy_t->z = timelib_parse_zone(&tz, &dst, dummy_t, ¬_found, DATE_TIMEZONEDB, php_date_parse_tzfile_wrapper);
3617 if (not_found) {
3618 php_error_docref(NULL, E_WARNING, "Unknown or bad timezone (%s)", orig_tz);
3619 efree(dummy_t);
3620 return FAILURE;
3621 } else {
3622 set_timezone_from_timelib_time(tzobj, dummy_t);
3623 timelib_free(dummy_t->tz_abbr);
3624 efree(dummy_t);
3625 return SUCCESS;
3626 }
3627 }
3628
3629
3630
3631
3632 PHP_FUNCTION(timezone_open)
3633 {
3634 char *tz;
3635 size_t tz_len;
3636 php_timezone_obj *tzobj;
3637
3638 if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &tz, &tz_len) == FAILURE) {
3639 RETURN_FALSE;
3640 }
3641 tzobj = Z_PHPTIMEZONE_P(php_date_instantiate(date_ce_timezone, return_value));
3642 if (SUCCESS != timezone_initialize(tzobj, tz, tz_len)) {
3643 zval_ptr_dtor(return_value);
3644 RETURN_FALSE;
3645 }
3646 }
3647
3648
3649
3650
3651
3652 PHP_METHOD(DateTimeZone, __construct)
3653 {
3654 char *tz;
3655 size_t tz_len;
3656 php_timezone_obj *tzobj;
3657 zend_error_handling error_handling;
3658
3659 if (FAILURE == zend_parse_parameters_throw(ZEND_NUM_ARGS(), "s", &tz, &tz_len)) {
3660 return;
3661 }
3662
3663 zend_replace_error_handling(EH_THROW, NULL, &error_handling);
3664 tzobj = Z_PHPTIMEZONE_P(getThis());
3665 timezone_initialize(tzobj, tz, tz_len);
3666 zend_restore_error_handling(&error_handling);
3667 }
3668
3669
3670 static int php_date_timezone_initialize_from_hash(zval **return_value, php_timezone_obj **tzobj, HashTable *myht)
3671 {
3672 zval *z_timezone;
3673 zval *z_timezone_type;
3674
3675 if ((z_timezone_type = zend_hash_str_find(myht, "timezone_type", sizeof("timezone_type") - 1)) != NULL) {
3676 if ((z_timezone = zend_hash_str_find(myht, "timezone", sizeof("timezone") - 1)) != NULL) {
3677 if (Z_TYPE_P(z_timezone_type) != IS_LONG) {
3678 return FAILURE;
3679 }
3680 if (Z_TYPE_P(z_timezone) != IS_STRING) {
3681 return FAILURE;
3682 }
3683 if (SUCCESS == timezone_initialize(*tzobj, Z_STRVAL_P(z_timezone), Z_STRLEN_P(z_timezone))) {
3684 return SUCCESS;
3685 }
3686 }
3687 }
3688 return FAILURE;
3689 }
3690
3691
3692
3693 PHP_METHOD(DateTimeZone, __set_state)
3694 {
3695 php_timezone_obj *tzobj;
3696 zval *array;
3697 HashTable *myht;
3698
3699 if (zend_parse_parameters(ZEND_NUM_ARGS(), "a", &array) == FAILURE) {
3700 RETURN_FALSE;
3701 }
3702
3703 myht = Z_ARRVAL_P(array);
3704
3705 php_date_instantiate(date_ce_timezone, return_value);
3706 tzobj = Z_PHPTIMEZONE_P(return_value);
3707 if(php_date_timezone_initialize_from_hash(&return_value, &tzobj, myht) != SUCCESS) {
3708 php_error_docref(NULL, E_ERROR, "Timezone initialization failed");
3709 }
3710 }
3711
3712
3713
3714
3715 PHP_METHOD(DateTimeZone, __wakeup)
3716 {
3717 zval *object = getThis();
3718 php_timezone_obj *tzobj;
3719 HashTable *myht;
3720
3721 tzobj = Z_PHPTIMEZONE_P(object);
3722
3723 myht = Z_OBJPROP_P(object);
3724
3725 if(php_date_timezone_initialize_from_hash(&return_value, &tzobj, myht) != SUCCESS) {
3726 php_error_docref(NULL, E_ERROR, "Timezone initialization failed");
3727 }
3728 }
3729
3730
3731
3732
3733
3734 PHP_FUNCTION(timezone_name_get)
3735 {
3736 zval *object;
3737 php_timezone_obj *tzobj;
3738
3739 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &object, date_ce_timezone) == FAILURE) {
3740 RETURN_FALSE;
3741 }
3742 tzobj = Z_PHPTIMEZONE_P(object);
3743 DATE_CHECK_INITIALIZED(tzobj->initialized, DateTimeZone);
3744
3745 switch (tzobj->type) {
3746 case TIMELIB_ZONETYPE_ID:
3747 RETURN_STRING(tzobj->tzi.tz->name);
3748 break;
3749 case TIMELIB_ZONETYPE_OFFSET: {
3750 zend_string *tmpstr = zend_string_alloc(sizeof("UTC+05:00")-1, 0);
3751 timelib_sll utc_offset = tzobj->tzi.utc_offset;
3752
3753 ZSTR_LEN(tmpstr) = snprintf(ZSTR_VAL(tmpstr), sizeof("+05:00"), "%c%02d:%02d",
3754 utc_offset > 0 ? '-' : '+',
3755 abs(utc_offset / 60),
3756 abs((utc_offset % 60)));
3757
3758 RETURN_NEW_STR(tmpstr);
3759 }
3760 break;
3761 case TIMELIB_ZONETYPE_ABBR:
3762 RETURN_STRING(tzobj->tzi.z.abbr);
3763 break;
3764 }
3765 }
3766
3767
3768
3769
3770
3771 PHP_FUNCTION(timezone_name_from_abbr)
3772 {
3773 char *abbr;
3774 char *tzid;
3775 size_t abbr_len;
3776 zend_long gmtoffset = -1;
3777 zend_long isdst = -1;
3778
3779 if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|ll", &abbr, &abbr_len, &gmtoffset, &isdst) == FAILURE) {
3780 RETURN_FALSE;
3781 }
3782 tzid = timelib_timezone_id_from_abbr(abbr, gmtoffset, isdst);
3783
3784 if (tzid) {
3785 RETURN_STRING(tzid);
3786 } else {
3787 RETURN_FALSE;
3788 }
3789 }
3790
3791
3792
3793
3794
3795 PHP_FUNCTION(timezone_offset_get)
3796 {
3797 zval *object, *dateobject;
3798 php_timezone_obj *tzobj;
3799 php_date_obj *dateobj;
3800 timelib_time_offset *offset;
3801
3802 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "OO", &object, date_ce_timezone, &dateobject, date_ce_interface) == FAILURE) {
3803 RETURN_FALSE;
3804 }
3805 tzobj = Z_PHPTIMEZONE_P(object);
3806 DATE_CHECK_INITIALIZED(tzobj->initialized, DateTimeZone);
3807 dateobj = Z_PHPDATE_P(dateobject);
3808 DATE_CHECK_INITIALIZED(dateobj->time, DateTimeInterface);
3809
3810 switch (tzobj->type) {
3811 case TIMELIB_ZONETYPE_ID:
3812 offset = timelib_get_time_zone_info(dateobj->time->sse, tzobj->tzi.tz);
3813 RETVAL_LONG(offset->offset);
3814 timelib_time_offset_dtor(offset);
3815 break;
3816 case TIMELIB_ZONETYPE_OFFSET:
3817 RETURN_LONG(tzobj->tzi.utc_offset * -60);
3818 break;
3819 case TIMELIB_ZONETYPE_ABBR:
3820 RETURN_LONG((tzobj->tzi.z.utc_offset - (tzobj->tzi.z.dst*60)) * -60);
3821 break;
3822 }
3823 }
3824
3825
3826
3827
3828
3829 PHP_FUNCTION(timezone_transitions_get)
3830 {
3831 zval *object, element;
3832 php_timezone_obj *tzobj;
3833 unsigned int i, begin = 0, found;
3834 zend_long timestamp_begin = ZEND_LONG_MIN, timestamp_end = ZEND_LONG_MAX;
3835
3836 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O|ll", &object, date_ce_timezone, ×tamp_begin, ×tamp_end) == FAILURE) {
3837 RETURN_FALSE;
3838 }
3839 tzobj = Z_PHPTIMEZONE_P(object);
3840 DATE_CHECK_INITIALIZED(tzobj->initialized, DateTimeZone);
3841 if (tzobj->type != TIMELIB_ZONETYPE_ID) {
3842 RETURN_FALSE;
3843 }
3844
3845 #define add_nominal() \
3846 array_init(&element); \
3847 add_assoc_long(&element, "ts", timestamp_begin); \
3848 add_assoc_str(&element, "time", php_format_date(DATE_FORMAT_ISO8601, 13, timestamp_begin, 0)); \
3849 add_assoc_long(&element, "offset", tzobj->tzi.tz->type[0].offset); \
3850 add_assoc_bool(&element, "isdst", tzobj->tzi.tz->type[0].isdst); \
3851 add_assoc_string(&element, "abbr", &tzobj->tzi.tz->timezone_abbr[tzobj->tzi.tz->type[0].abbr_idx]); \
3852 add_next_index_zval(return_value, &element);
3853
3854 #define add(i,ts) \
3855 array_init(&element); \
3856 add_assoc_long(&element, "ts", ts); \
3857 add_assoc_str(&element, "time", php_format_date(DATE_FORMAT_ISO8601, 13, ts, 0)); \
3858 add_assoc_long(&element, "offset", tzobj->tzi.tz->type[tzobj->tzi.tz->trans_idx[i]].offset); \
3859 add_assoc_bool(&element, "isdst", tzobj->tzi.tz->type[tzobj->tzi.tz->trans_idx[i]].isdst); \
3860 add_assoc_string(&element, "abbr", &tzobj->tzi.tz->timezone_abbr[tzobj->tzi.tz->type[tzobj->tzi.tz->trans_idx[i]].abbr_idx]); \
3861 add_next_index_zval(return_value, &element);
3862
3863 #define add_last() add(tzobj->tzi.tz->bit32.timecnt - 1, timestamp_begin)
3864
3865 array_init(return_value);
3866
3867 if (timestamp_begin == ZEND_LONG_MIN) {
3868 add_nominal();
3869 begin = 0;
3870 found = 1;
3871 } else {
3872 begin = 0;
3873 found = 0;
3874 if (tzobj->tzi.tz->bit32.timecnt > 0) {
3875 do {
3876 if (tzobj->tzi.tz->trans[begin] > timestamp_begin) {
3877 if (begin > 0) {
3878 add(begin - 1, timestamp_begin);
3879 } else {
3880 add_nominal();
3881 }
3882 found = 1;
3883 break;
3884 }
3885 begin++;
3886 } while (begin < tzobj->tzi.tz->bit32.timecnt);
3887 }
3888 }
3889
3890 if (!found) {
3891 if (tzobj->tzi.tz->bit32.timecnt > 0) {
3892 add_last();
3893 } else {
3894 add_nominal();
3895 }
3896 } else {
3897 for (i = begin; i < tzobj->tzi.tz->bit32.timecnt; ++i) {
3898 if (tzobj->tzi.tz->trans[i] < timestamp_end) {
3899 add(i, tzobj->tzi.tz->trans[i]);
3900 }
3901 }
3902 }
3903 }
3904
3905
3906
3907
3908
3909 PHP_FUNCTION(timezone_location_get)
3910 {
3911 zval *object;
3912 php_timezone_obj *tzobj;
3913
3914 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &object, date_ce_timezone) == FAILURE) {
3915 RETURN_FALSE;
3916 }
3917 tzobj = Z_PHPTIMEZONE_P(object);
3918 DATE_CHECK_INITIALIZED(tzobj->initialized, DateTimeZone);
3919 if (tzobj->type != TIMELIB_ZONETYPE_ID) {
3920 RETURN_FALSE;
3921 }
3922
3923 array_init(return_value);
3924 add_assoc_string(return_value, "country_code", tzobj->tzi.tz->location.country_code);
3925 add_assoc_double(return_value, "latitude", tzobj->tzi.tz->location.latitude);
3926 add_assoc_double(return_value, "longitude", tzobj->tzi.tz->location.longitude);
3927 add_assoc_string(return_value, "comments", tzobj->tzi.tz->location.comments);
3928 }
3929
3930
3931 static int date_interval_initialize(timelib_rel_time **rt, char *format, size_t format_length)
3932 {
3933 timelib_time *b = NULL, *e = NULL;
3934 timelib_rel_time *p = NULL;
3935 int r = 0;
3936 int retval = 0;
3937 struct timelib_error_container *errors;
3938
3939 timelib_strtointerval(format, format_length, &b, &e, &p, &r, &errors);
3940
3941 if (errors->error_count > 0) {
3942 php_error_docref(NULL, E_WARNING, "Unknown or bad format (%s)", format);
3943 retval = FAILURE;
3944 } else {
3945 if(p) {
3946 *rt = p;
3947 retval = SUCCESS;
3948 } else {
3949 if(b && e) {
3950 timelib_update_ts(b, NULL);
3951 timelib_update_ts(e, NULL);
3952 *rt = timelib_diff(b, e);
3953 retval = SUCCESS;
3954 } else {
3955 php_error_docref(NULL, E_WARNING, "Failed to parse interval (%s)", format);
3956 retval = FAILURE;
3957 }
3958 }
3959 }
3960 timelib_error_container_dtor(errors);
3961 timelib_free(b);
3962 timelib_free(e);
3963 return retval;
3964 }
3965
3966
3967 zval *date_interval_read_property(zval *object, zval *member, int type, void **cache_slot, zval *rv)
3968 {
3969 php_interval_obj *obj;
3970 zval *retval;
3971 zval tmp_member;
3972 timelib_sll value = -1;
3973
3974 if (Z_TYPE_P(member) != IS_STRING) {
3975 tmp_member = *member;
3976 zval_copy_ctor(&tmp_member);
3977 convert_to_string(&tmp_member);
3978 member = &tmp_member;
3979 cache_slot = NULL;
3980 }
3981
3982 obj = Z_PHPINTERVAL_P(object);
3983
3984 if (!obj->initialized) {
3985 retval = (zend_get_std_object_handlers())->read_property(object, member, type, cache_slot, rv);
3986 if (member == &tmp_member) {
3987 zval_dtor(member);
3988 }
3989 return retval;
3990 }
3991
3992 #define GET_VALUE_FROM_STRUCT(n,m) \
3993 if (strcmp(Z_STRVAL_P(member), m) == 0) { \
3994 value = obj->diff->n; \
3995 break; \
3996 }
3997 do {
3998 GET_VALUE_FROM_STRUCT(y, "y");
3999 GET_VALUE_FROM_STRUCT(m, "m");
4000 GET_VALUE_FROM_STRUCT(d, "d");
4001 GET_VALUE_FROM_STRUCT(h, "h");
4002 GET_VALUE_FROM_STRUCT(i, "i");
4003 GET_VALUE_FROM_STRUCT(s, "s");
4004 GET_VALUE_FROM_STRUCT(invert, "invert");
4005 GET_VALUE_FROM_STRUCT(days, "days");
4006
4007 retval = (zend_get_std_object_handlers())->read_property(object, member, type, cache_slot, rv);
4008
4009 if (member == &tmp_member) {
4010 zval_dtor(member);
4011 }
4012
4013 return retval;
4014 } while(0);
4015
4016 retval = rv;
4017
4018 if (value != -99999) {
4019 ZVAL_LONG(retval, value);
4020 } else {
4021 ZVAL_FALSE(retval);
4022 }
4023
4024 if (member == &tmp_member) {
4025 zval_dtor(member);
4026 }
4027
4028 return retval;
4029 }
4030
4031
4032
4033 void date_interval_write_property(zval *object, zval *member, zval *value, void **cache_slot)
4034 {
4035 php_interval_obj *obj;
4036 zval tmp_member;
4037
4038 if (Z_TYPE_P(member) != IS_STRING) {
4039 tmp_member = *member;
4040 zval_copy_ctor(&tmp_member);
4041 convert_to_string(&tmp_member);
4042 member = &tmp_member;
4043 cache_slot = NULL;
4044 }
4045
4046 obj = Z_PHPINTERVAL_P(object);
4047
4048 if (!obj->initialized) {
4049 (zend_get_std_object_handlers())->write_property(object, member, value, cache_slot);
4050 if (member == &tmp_member) {
4051 zval_dtor(member);
4052 }
4053 return;
4054 }
4055
4056 #define SET_VALUE_FROM_STRUCT(n,m) \
4057 if (strcmp(Z_STRVAL_P(member), m) == 0) { \
4058 obj->diff->n = zval_get_long(value); \
4059 break; \
4060 }
4061
4062 do {
4063 SET_VALUE_FROM_STRUCT(y, "y");
4064 SET_VALUE_FROM_STRUCT(m, "m");
4065 SET_VALUE_FROM_STRUCT(d, "d");
4066 SET_VALUE_FROM_STRUCT(h, "h");
4067 SET_VALUE_FROM_STRUCT(i, "i");
4068 SET_VALUE_FROM_STRUCT(s, "s");
4069 SET_VALUE_FROM_STRUCT(invert, "invert");
4070
4071 (zend_get_std_object_handlers())->write_property(object, member, value, cache_slot);
4072 } while(0);
4073
4074 if (member == &tmp_member) {
4075 zval_dtor(member);
4076 }
4077 }
4078
4079
4080
4081
4082
4083
4084 PHP_METHOD(DateInterval, __construct)
4085 {
4086 char *interval_string = NULL;
4087 size_t interval_string_length;
4088 php_interval_obj *diobj;
4089 timelib_rel_time *reltime;
4090 zend_error_handling error_handling;
4091
4092 if (zend_parse_parameters_throw(ZEND_NUM_ARGS(), "s", &interval_string, &interval_string_length) == FAILURE) {
4093 return;
4094 }
4095
4096 zend_replace_error_handling(EH_THROW, NULL, &error_handling);
4097 if (date_interval_initialize(&reltime, interval_string, interval_string_length) == SUCCESS) {
4098 diobj = Z_PHPINTERVAL_P(getThis());
4099 diobj->diff = reltime;
4100 diobj->initialized = 1;
4101 }
4102 zend_restore_error_handling(&error_handling);
4103 }
4104
4105
4106
4107 static int php_date_interval_initialize_from_hash(zval **return_value, php_interval_obj **intobj, HashTable *myht)
4108 {
4109 (*intobj)->diff = timelib_rel_time_ctor();
4110
4111 #define PHP_DATE_INTERVAL_READ_PROPERTY(element, member, itype, def) \
4112 do { \
4113 zval *z_arg = zend_hash_str_find(myht, element, sizeof(element) - 1); \
4114 if (z_arg) { \
4115 (*intobj)->diff->member = (itype)zval_get_long(z_arg); \
4116 } else { \
4117 (*intobj)->diff->member = (itype)def; \
4118 } \
4119 } while (0);
4120
4121 #define PHP_DATE_INTERVAL_READ_PROPERTY_I64(element, member) \
4122 do { \
4123 zval *z_arg = zend_hash_str_find(myht, element, sizeof(element) - 1); \
4124 if (z_arg) { \
4125 zend_string *str = zval_get_string(z_arg); \
4126 DATE_A64I((*intobj)->diff->member, ZSTR_VAL(str)); \
4127 zend_string_release(str); \
4128 } else { \
4129 (*intobj)->diff->member = -1LL; \
4130 } \
4131 } while (0);
4132
4133 PHP_DATE_INTERVAL_READ_PROPERTY("y", y, timelib_sll, -1)
4134 PHP_DATE_INTERVAL_READ_PROPERTY("m", m, timelib_sll, -1)
4135 PHP_DATE_INTERVAL_READ_PROPERTY("d", d, timelib_sll, -1)
4136 PHP_DATE_INTERVAL_READ_PROPERTY("h", h, timelib_sll, -1)
4137 PHP_DATE_INTERVAL_READ_PROPERTY("i", i, timelib_sll, -1)
4138 PHP_DATE_INTERVAL_READ_PROPERTY("s", s, timelib_sll, -1)
4139 PHP_DATE_INTERVAL_READ_PROPERTY("weekday", weekday, int, -1)
4140 PHP_DATE_INTERVAL_READ_PROPERTY("weekday_behavior", weekday_behavior, int, -1)
4141 PHP_DATE_INTERVAL_READ_PROPERTY("first_last_day_of", first_last_day_of, int, -1)
4142 PHP_DATE_INTERVAL_READ_PROPERTY("invert", invert, int, 0);
4143 PHP_DATE_INTERVAL_READ_PROPERTY_I64("days", days);
4144 PHP_DATE_INTERVAL_READ_PROPERTY("special_type", special.type, unsigned int, 0);
4145 PHP_DATE_INTERVAL_READ_PROPERTY_I64("special_amount", special.amount);
4146 PHP_DATE_INTERVAL_READ_PROPERTY("have_weekday_relative", have_weekday_relative, unsigned int, 0);
4147 PHP_DATE_INTERVAL_READ_PROPERTY("have_special_relative", have_special_relative, unsigned int, 0);
4148 (*intobj)->initialized = 1;
4149
4150 return 0;
4151 }
4152
4153
4154
4155 PHP_METHOD(DateInterval, __set_state)
4156 {
4157 php_interval_obj *intobj;
4158 zval *array;
4159 HashTable *myht;
4160
4161 if (zend_parse_parameters(ZEND_NUM_ARGS(), "a", &array) == FAILURE) {
4162 RETURN_FALSE;
4163 }
4164
4165 myht = Z_ARRVAL_P(array);
4166
4167 php_date_instantiate(date_ce_interval, return_value);
4168 intobj = Z_PHPINTERVAL_P(return_value);
4169 php_date_interval_initialize_from_hash(&return_value, &intobj, myht);
4170 }
4171
4172
4173
4174
4175 PHP_METHOD(DateInterval, __wakeup)
4176 {
4177 zval *object = getThis();
4178 php_interval_obj *intobj;
4179 HashTable *myht;
4180
4181 intobj = Z_PHPINTERVAL_P(object);
4182
4183 myht = Z_OBJPROP_P(object);
4184
4185 php_date_interval_initialize_from_hash(&return_value, &intobj, myht);
4186 }
4187
4188
4189
4190
4191
4192 PHP_FUNCTION(date_interval_create_from_date_string)
4193 {
4194 char *time_str = NULL;
4195 size_t time_str_len = 0;
4196 timelib_time *time;
4197 timelib_error_container *err = NULL;
4198 php_interval_obj *diobj;
4199
4200 if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &time_str, &time_str_len) == FAILURE) {
4201 RETURN_FALSE;
4202 }
4203
4204 php_date_instantiate(date_ce_interval, return_value);
4205
4206 time = timelib_strtotime(time_str, time_str_len, &err, DATE_TIMEZONEDB, php_date_parse_tzfile_wrapper);
4207 diobj = Z_PHPINTERVAL_P(return_value);
4208 diobj->diff = timelib_rel_time_clone(&time->relative);
4209 diobj->initialized = 1;
4210 timelib_time_dtor(time);
4211 timelib_error_container_dtor(err);
4212 }
4213
4214
4215
4216 static zend_string *date_interval_format(char *format, size_t format_len, timelib_rel_time *t)
4217 {
4218 smart_str string = {0};
4219 int i, length, have_format_spec = 0;
4220 char buffer[33];
4221
4222 if (!format_len) {
4223 return ZSTR_EMPTY_ALLOC();
4224 }
4225
4226 for (i = 0; i < format_len; i++) {
4227 if (have_format_spec) {
4228 switch (format[i]) {
4229 case 'Y': length = slprintf(buffer, 32, "%02d", (int) t->y); break;
4230 case 'y': length = slprintf(buffer, 32, "%d", (int) t->y); break;
4231
4232 case 'M': length = slprintf(buffer, 32, "%02d", (int) t->m); break;
4233 case 'm': length = slprintf(buffer, 32, "%d", (int) t->m); break;
4234
4235 case 'D': length = slprintf(buffer, 32, "%02d", (int) t->d); break;
4236 case 'd': length = slprintf(buffer, 32, "%d", (int) t->d); break;
4237
4238 case 'H': length = slprintf(buffer, 32, "%02d", (int) t->h); break;
4239 case 'h': length = slprintf(buffer, 32, "%d", (int) t->h); break;
4240
4241 case 'I': length = slprintf(buffer, 32, "%02d", (int) t->i); break;
4242 case 'i': length = slprintf(buffer, 32, "%d", (int) t->i); break;
4243
4244 case 'S': length = slprintf(buffer, 32, "%02" ZEND_LONG_FMT_SPEC, (zend_long) t->s); break;
4245 case 's': length = slprintf(buffer, 32, ZEND_LONG_FMT, (zend_long) t->s); break;
4246
4247 case 'a': {
4248 if ((int) t->days != -99999) {
4249 length = slprintf(buffer, 32, "%d", (int) t->days);
4250 } else {
4251 length = slprintf(buffer, 32, "(unknown)");
4252 }
4253 } break;
4254 case 'r': length = slprintf(buffer, 32, "%s", t->invert ? "-" : ""); break;
4255 case 'R': length = slprintf(buffer, 32, "%c", t->invert ? '-' : '+'); break;
4256
4257 case '%': length = slprintf(buffer, 32, "%%"); break;
4258 default: buffer[0] = '%'; buffer[1] = format[i]; buffer[2] = '\0'; length = 2; break;
4259 }
4260 smart_str_appendl(&string, buffer, length);
4261 have_format_spec = 0;
4262 } else {
4263 if (format[i] == '%') {
4264 have_format_spec = 1;
4265 } else {
4266 smart_str_appendc(&string, format[i]);
4267 }
4268 }
4269 }
4270
4271 smart_str_0(&string);
4272
4273 return string.s;
4274 }
4275
4276
4277
4278
4279
4280 PHP_FUNCTION(date_interval_format)
4281 {
4282 zval *object;
4283 php_interval_obj *diobj;
4284 char *format;
4285 size_t format_len;
4286
4287 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Os", &object, date_ce_interval, &format, &format_len) == FAILURE) {
4288 RETURN_FALSE;
4289 }
4290 diobj = Z_PHPINTERVAL_P(object);
4291 DATE_CHECK_INITIALIZED(diobj->initialized, DateInterval);
4292
4293 RETURN_STR(date_interval_format(format, format_len, diobj->diff));
4294 }
4295
4296
4297 static int date_period_initialize(timelib_time **st, timelib_time **et, timelib_rel_time **d, zend_long *recurrences, char *format, size_t format_length)
4298 {
4299 timelib_time *b = NULL, *e = NULL;
4300 timelib_rel_time *p = NULL;
4301 int r = 0;
4302 int retval = 0;
4303 struct timelib_error_container *errors;
4304
4305 timelib_strtointerval(format, format_length, &b, &e, &p, &r, &errors);
4306
4307 if (errors->error_count > 0) {
4308 php_error_docref(NULL, E_WARNING, "Unknown or bad format (%s)", format);
4309 retval = FAILURE;
4310 } else {
4311 *st = b;
4312 *et = e;
4313 *d = p;
4314 *recurrences = r;
4315 retval = SUCCESS;
4316 }
4317 timelib_error_container_dtor(errors);
4318 return retval;
4319 }
4320
4321
4322
4323
4324 PHP_METHOD(DatePeriod, __construct)
4325 {
4326 php_period_obj *dpobj;
4327 php_date_obj *dateobj;
4328 php_interval_obj *intobj;
4329 zval *start, *end = NULL, *interval;
4330 zend_long recurrences = 0, options = 0;
4331 char *isostr = NULL;
4332 size_t isostr_len = 0;
4333 timelib_time *clone;
4334 zend_error_handling error_handling;
4335
4336 zend_replace_error_handling(EH_THROW, NULL, &error_handling);
4337 if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), "OOl|l", &start, date_ce_interface, &interval, date_ce_interval, &recurrences, &options) == FAILURE) {
4338 if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), "OOO|l", &start, date_ce_interface, &interval, date_ce_interval, &end, date_ce_interface, &options) == FAILURE) {
4339 if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), "s|l", &isostr, &isostr_len, &options) == FAILURE) {
4340 php_error_docref(NULL, E_WARNING, "This constructor accepts either (DateTimeInterface, DateInterval, int) OR (DateTimeInterface, DateInterval, DateTime) OR (string) as arguments.");
4341 zend_restore_error_handling(&error_handling);
4342 return;
4343 }
4344 }
4345 }
4346
4347 dpobj = Z_PHPPERIOD_P(getThis());
4348 dpobj->current = NULL;
4349
4350 if (isostr) {
4351 date_period_initialize(&(dpobj->start), &(dpobj->end), &(dpobj->interval), &recurrences, isostr, isostr_len);
4352 if (dpobj->start == NULL) {
4353 php_error_docref(NULL, E_WARNING, "The ISO interval '%s' did not contain a start date.", isostr);
4354 }
4355 if (dpobj->interval == NULL) {
4356 php_error_docref(NULL, E_WARNING, "The ISO interval '%s' did not contain an interval.", isostr);
4357 }
4358 if (dpobj->end == NULL && recurrences == 0) {
4359 php_error_docref(NULL, E_WARNING, "The ISO interval '%s' did not contain an end date or a recurrence count.", isostr);
4360 }
4361
4362 if (dpobj->start) {
4363 timelib_update_ts(dpobj->start, NULL);
4364 }
4365 if (dpobj->end) {
4366 timelib_update_ts(dpobj->end, NULL);
4367 }
4368 dpobj->start_ce = date_ce_date;
4369 } else {
4370
4371 intobj = Z_PHPINTERVAL_P(interval);
4372
4373
4374 dateobj = Z_PHPDATE_P(start);
4375 clone = timelib_time_ctor();
4376 memcpy(clone, dateobj->time, sizeof(timelib_time));
4377 if (dateobj->time->tz_abbr) {
4378 clone->tz_abbr = timelib_strdup(dateobj->time->tz_abbr);
4379 }
4380 if (dateobj->time->tz_info) {
4381 clone->tz_info = dateobj->time->tz_info;
4382 }
4383 dpobj->start = clone;
4384 dpobj->start_ce = Z_OBJCE_P(start);
4385
4386
4387 dpobj->interval = timelib_rel_time_clone(intobj->diff);
4388
4389
4390 if (end) {
4391 dateobj = Z_PHPDATE_P(end);
4392 clone = timelib_time_clone(dateobj->time);
4393 dpobj->end = clone;
4394 }
4395 }
4396
4397
4398 dpobj->include_start_date = !(options & PHP_DATE_PERIOD_EXCLUDE_START_DATE);
4399
4400
4401 dpobj->recurrences = recurrences + dpobj->include_start_date;
4402
4403 dpobj->initialized = 1;
4404
4405 zend_restore_error_handling(&error_handling);
4406 }
4407
4408
4409
4410
4411
4412 PHP_METHOD(DatePeriod, getStartDate)
4413 {
4414 php_period_obj *dpobj;
4415 php_date_obj *dateobj;
4416
4417 if (zend_parse_parameters_none() == FAILURE) {
4418 return;
4419 }
4420
4421 dpobj = Z_PHPPERIOD_P(getThis());
4422
4423 php_date_instantiate(dpobj->start_ce, return_value);
4424 dateobj = Z_PHPDATE_P(return_value);
4425 dateobj->time = timelib_time_ctor();
4426 *dateobj->time = *dpobj->start;
4427 if (dpobj->start->tz_abbr) {
4428 dateobj->time->tz_abbr = timelib_strdup(dpobj->start->tz_abbr);
4429 }
4430 if (dpobj->start->tz_info) {
4431 dateobj->time->tz_info = dpobj->start->tz_info;
4432 }
4433 }
4434
4435
4436
4437
4438
4439 PHP_METHOD(DatePeriod, getEndDate)
4440 {
4441 php_period_obj *dpobj;
4442 php_date_obj *dateobj;
4443
4444 if (zend_parse_parameters_none() == FAILURE) {
4445 return;
4446 }
4447
4448 dpobj = Z_PHPPERIOD_P(getThis());
4449
4450 if (!dpobj->end) {
4451 return;
4452 }
4453
4454 php_date_instantiate(dpobj->start_ce, return_value);
4455 dateobj = Z_PHPDATE_P(return_value);
4456 dateobj->time = timelib_time_ctor();
4457 *dateobj->time = *dpobj->end;
4458 if (dpobj->end->tz_abbr) {
4459 dateobj->time->tz_abbr = timelib_strdup(dpobj->end->tz_abbr);
4460 }
4461 if (dpobj->end->tz_info) {
4462 dateobj->time->tz_info = dpobj->end->tz_info;
4463 }
4464 }
4465
4466
4467
4468
4469
4470 PHP_METHOD(DatePeriod, getDateInterval)
4471 {
4472 php_period_obj *dpobj;
4473 php_interval_obj *diobj;
4474
4475 if (zend_parse_parameters_none() == FAILURE) {
4476 return;
4477 }
4478
4479 dpobj = Z_PHPPERIOD_P(getThis());
4480
4481 php_date_instantiate(date_ce_interval, return_value);
4482 diobj = Z_PHPINTERVAL_P(return_value);
4483 diobj->diff = timelib_rel_time_clone(dpobj->interval);
4484 diobj->initialized = 1;
4485 }
4486
4487
4488 static int check_id_allowed(char *id, zend_long what)
4489 {
4490 if (what & PHP_DATE_TIMEZONE_GROUP_AFRICA && strncasecmp(id, "Africa/", 7) == 0) return 1;
4491 if (what & PHP_DATE_TIMEZONE_GROUP_AMERICA && strncasecmp(id, "America/", 8) == 0) return 1;
4492 if (what & PHP_DATE_TIMEZONE_GROUP_ANTARCTICA && strncasecmp(id, "Antarctica/", 11) == 0) return 1;
4493 if (what & PHP_DATE_TIMEZONE_GROUP_ARCTIC && strncasecmp(id, "Arctic/", 7) == 0) return 1;
4494 if (what & PHP_DATE_TIMEZONE_GROUP_ASIA && strncasecmp(id, "Asia/", 5) == 0) return 1;
4495 if (what & PHP_DATE_TIMEZONE_GROUP_ATLANTIC && strncasecmp(id, "Atlantic/", 9) == 0) return 1;
4496 if (what & PHP_DATE_TIMEZONE_GROUP_AUSTRALIA && strncasecmp(id, "Australia/", 10) == 0) return 1;
4497 if (what & PHP_DATE_TIMEZONE_GROUP_EUROPE && strncasecmp(id, "Europe/", 7) == 0) return 1;
4498 if (what & PHP_DATE_TIMEZONE_GROUP_INDIAN && strncasecmp(id, "Indian/", 7) == 0) return 1;
4499 if (what & PHP_DATE_TIMEZONE_GROUP_PACIFIC && strncasecmp(id, "Pacific/", 8) == 0) return 1;
4500 if (what & PHP_DATE_TIMEZONE_GROUP_UTC && strncasecmp(id, "UTC", 3) == 0) return 1;
4501 return 0;
4502 }
4503
4504
4505
4506
4507 PHP_FUNCTION(timezone_identifiers_list)
4508 {
4509 const timelib_tzdb *tzdb;
4510 const timelib_tzdb_index_entry *table;
4511 int i, item_count;
4512 zend_long what = PHP_DATE_TIMEZONE_GROUP_ALL;
4513 char *option = NULL;
4514 size_t option_len = 0;
4515
4516 if (zend_parse_parameters(ZEND_NUM_ARGS(), "|ls", &what, &option, &option_len) == FAILURE) {
4517 RETURN_FALSE;
4518 }
4519
4520
4521 if (what == PHP_DATE_TIMEZONE_PER_COUNTRY && option_len != 2) {
4522 php_error_docref(NULL, E_NOTICE, "A two-letter ISO 3166-1 compatible country code is expected");
4523 RETURN_FALSE;
4524 }
4525
4526 tzdb = DATE_TIMEZONEDB;
4527 item_count = tzdb->index_size;
4528 table = tzdb->index;
4529
4530 array_init(return_value);
4531
4532 for (i = 0; i < item_count; ++i) {
4533 if (what == PHP_DATE_TIMEZONE_PER_COUNTRY) {
4534 if (tzdb->data[table[i].pos + 5] == option[0] && tzdb->data[table[i].pos + 6] == option[1]) {
4535 add_next_index_string(return_value, table[i].id);
4536 }
4537 } else if (what == PHP_DATE_TIMEZONE_GROUP_ALL_W_BC || (check_id_allowed(table[i].id, what) && (tzdb->data[table[i].pos + 4] == '\1'))) {
4538 add_next_index_string(return_value, table[i].id);
4539 }
4540 };
4541 }
4542
4543
4544
4545
4546
4547 PHP_FUNCTION(timezone_version_get)
4548 {
4549 const timelib_tzdb *tzdb;
4550
4551 tzdb = DATE_TIMEZONEDB;
4552 RETURN_STRING(tzdb->version);
4553 }
4554
4555
4556
4557
4558
4559 PHP_FUNCTION(timezone_abbreviations_list)
4560 {
4561 const timelib_tz_lookup_table *table, *entry;
4562 zval element, *abbr_array_p, abbr_array;
4563
4564 table = timelib_timezone_abbreviations_list();
4565 array_init(return_value);
4566 entry = table;
4567
4568 do {
4569 array_init(&element);
4570 add_assoc_bool_ex(&element, "dst", sizeof("dst") -1, entry->type);
4571 add_assoc_long_ex(&element, "offset", sizeof("offset") - 1, entry->gmtoffset);
4572 if (entry->full_tz_name) {
4573 add_assoc_string_ex(&element, "timezone_id", sizeof("timezone_id") - 1, entry->full_tz_name);
4574 } else {
4575 add_assoc_null_ex(&element, "timezone_id", sizeof("timezone_id") - 1);
4576 }
4577
4578 abbr_array_p = zend_hash_str_find(Z_ARRVAL_P(return_value), entry->name, strlen(entry->name));
4579 if (!abbr_array_p) {
4580 array_init(&abbr_array);
4581 add_assoc_zval(return_value, entry->name, &abbr_array);
4582 } else {
4583 ZVAL_COPY_VALUE(&abbr_array, abbr_array_p);
4584 }
4585 add_next_index_zval(&abbr_array, &element);
4586 entry++;
4587 } while (entry->name);
4588 }
4589
4590
4591
4592
4593 PHP_FUNCTION(date_default_timezone_set)
4594 {
4595 char *zone;
4596 size_t zone_len;
4597
4598 if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &zone, &zone_len) == FAILURE) {
4599 RETURN_FALSE;
4600 }
4601 if (!timelib_timezone_id_is_valid(zone, DATE_TIMEZONEDB)) {
4602 php_error_docref(NULL, E_NOTICE, "Timezone ID '%s' is invalid", zone);
4603 RETURN_FALSE;
4604 }
4605 if (DATEG(timezone)) {
4606 efree(DATEG(timezone));
4607 DATEG(timezone) = NULL;
4608 }
4609 DATEG(timezone) = estrndup(zone, zone_len);
4610 RETURN_TRUE;
4611 }
4612
4613
4614
4615
4616 PHP_FUNCTION(date_default_timezone_get)
4617 {
4618 timelib_tzinfo *default_tz;
4619
4620 default_tz = get_timezone_info();
4621 RETVAL_STRING(default_tz->name);
4622 }
4623
4624
4625
4626
4627
4628 static void php_do_date_sunrise_sunset(INTERNAL_FUNCTION_PARAMETERS, int calc_sunset)
4629 {
4630 double latitude = 0.0, longitude = 0.0, zenith = 0.0, gmt_offset = 0, altitude;
4631 double h_rise, h_set, N;
4632 timelib_sll rise, set, transit;
4633 zend_long time, retformat = 0;
4634 int rs;
4635 timelib_time *t;
4636 timelib_tzinfo *tzi;
4637 zend_string *retstr;
4638
4639 if (zend_parse_parameters(ZEND_NUM_ARGS(), "l|ldddd", &time, &retformat, &latitude, &longitude, &zenith, &gmt_offset) == FAILURE) {
4640 RETURN_FALSE;
4641 }
4642
4643 switch (ZEND_NUM_ARGS()) {
4644 case 1:
4645 retformat = SUNFUNCS_RET_STRING;
4646 case 2:
4647 latitude = INI_FLT("date.default_latitude");
4648 case 3:
4649 longitude = INI_FLT("date.default_longitude");
4650 case 4:
4651 if (calc_sunset) {
4652 zenith = INI_FLT("date.sunset_zenith");
4653 } else {
4654 zenith = INI_FLT("date.sunrise_zenith");
4655 }
4656 case 5:
4657 case 6:
4658 break;
4659 default:
4660 php_error_docref(NULL, E_WARNING, "invalid format");
4661 RETURN_FALSE;
4662 break;
4663 }
4664 if (retformat != SUNFUNCS_RET_TIMESTAMP &&
4665 retformat != SUNFUNCS_RET_STRING &&
4666 retformat != SUNFUNCS_RET_DOUBLE)
4667 {
4668 php_error_docref(NULL, E_WARNING, "Wrong return format given, pick one of SUNFUNCS_RET_TIMESTAMP, SUNFUNCS_RET_STRING or SUNFUNCS_RET_DOUBLE");
4669 RETURN_FALSE;
4670 }
4671 altitude = 90 - zenith;
4672
4673
4674 t = timelib_time_ctor();
4675 tzi = get_timezone_info();
4676 t->tz_info = tzi;
4677 t->zone_type = TIMELIB_ZONETYPE_ID;
4678
4679 if (ZEND_NUM_ARGS() <= 5) {
4680 gmt_offset = timelib_get_current_offset(t) / 3600;
4681 }
4682
4683 timelib_unixtime2local(t, time);
4684 rs = timelib_astro_rise_set_altitude(t, longitude, latitude, altitude, 1, &h_rise, &h_set, &rise, &set, &transit);
4685 timelib_time_dtor(t);
4686
4687 if (rs != 0) {
4688 RETURN_FALSE;
4689 }
4690
4691 if (retformat == SUNFUNCS_RET_TIMESTAMP) {
4692 RETURN_LONG(calc_sunset ? set : rise);
4693 }
4694 N = (calc_sunset ? h_set : h_rise) + gmt_offset;
4695
4696 if (N > 24 || N < 0) {
4697 N -= floor(N / 24) * 24;
4698 }
4699
4700 switch (retformat) {
4701 case SUNFUNCS_RET_STRING:
4702 retstr = strpprintf(0, "%02d:%02d", (int) N, (int) (60 * (N - (int) N)));
4703 RETURN_NEW_STR(retstr);
4704 break;
4705 case SUNFUNCS_RET_DOUBLE:
4706 RETURN_DOUBLE(N);
4707 break;
4708 }
4709 }
4710
4711
4712
4713
4714 PHP_FUNCTION(date_sunrise)
4715 {
4716 php_do_date_sunrise_sunset(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
4717 }
4718
4719
4720
4721
4722 PHP_FUNCTION(date_sunset)
4723 {
4724 php_do_date_sunrise_sunset(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
4725 }
4726
4727
4728
4729
4730 PHP_FUNCTION(date_sun_info)
4731 {
4732 zend_long time;
4733 double latitude, longitude;
4734 timelib_time *t, *t2;
4735 timelib_tzinfo *tzi;
4736 int rs;
4737 timelib_sll rise, set, transit;
4738 int dummy;
4739 double ddummy;
4740
4741 if (zend_parse_parameters(ZEND_NUM_ARGS(), "ldd", &time, &latitude, &longitude) == FAILURE) {
4742 RETURN_FALSE;
4743 }
4744
4745 t = timelib_time_ctor();
4746 tzi = get_timezone_info();
4747 t->tz_info = tzi;
4748 t->zone_type = TIMELIB_ZONETYPE_ID;
4749 timelib_unixtime2local(t, time);
4750
4751
4752 t2 = timelib_time_ctor();
4753 array_init(return_value);
4754
4755
4756 rs = timelib_astro_rise_set_altitude(t, longitude, latitude, -35.0/60, 1, &ddummy, &ddummy, &rise, &set, &transit);
4757 switch (rs) {
4758 case -1:
4759 add_assoc_bool(return_value, "sunrise", 0);
4760 add_assoc_bool(return_value, "sunset", 0);
4761 break;
4762 case 1:
4763 add_assoc_bool(return_value, "sunrise", 1);
4764 add_assoc_bool(return_value, "sunset", 1);
4765 break;
4766 default:
4767 t2->sse = rise;
4768 add_assoc_long(return_value, "sunrise", timelib_date_to_int(t2, &dummy));
4769 t2->sse = set;
4770 add_assoc_long(return_value, "sunset", timelib_date_to_int(t2, &dummy));
4771 }
4772 t2->sse = transit;
4773 add_assoc_long(return_value, "transit", timelib_date_to_int(t2, &dummy));
4774
4775
4776 rs = timelib_astro_rise_set_altitude(t, longitude, latitude, -6.0, 0, &ddummy, &ddummy, &rise, &set, &transit);
4777 switch (rs) {
4778 case -1:
4779 add_assoc_bool(return_value, "civil_twilight_begin", 0);
4780 add_assoc_bool(return_value, "civil_twilight_end", 0);
4781 break;
4782 case 1:
4783 add_assoc_bool(return_value, "civil_twilight_begin", 1);
4784 add_assoc_bool(return_value, "civil_twilight_end", 1);
4785 break;
4786 default:
4787 t2->sse = rise;
4788 add_assoc_long(return_value, "civil_twilight_begin", timelib_date_to_int(t2, &dummy));
4789 t2->sse = set;
4790 add_assoc_long(return_value, "civil_twilight_end", timelib_date_to_int(t2, &dummy));
4791 }
4792
4793
4794 rs = timelib_astro_rise_set_altitude(t, longitude, latitude, -12.0, 0, &ddummy, &ddummy, &rise, &set, &transit);
4795 switch (rs) {
4796 case -1:
4797 add_assoc_bool(return_value, "nautical_twilight_begin", 0);
4798 add_assoc_bool(return_value, "nautical_twilight_end", 0);
4799 break;
4800 case 1:
4801 add_assoc_bool(return_value, "nautical_twilight_begin", 1);
4802 add_assoc_bool(return_value, "nautical_twilight_end", 1);
4803 break;
4804 default:
4805 t2->sse = rise;
4806 add_assoc_long(return_value, "nautical_twilight_begin", timelib_date_to_int(t2, &dummy));
4807 t2->sse = set;
4808 add_assoc_long(return_value, "nautical_twilight_end", timelib_date_to_int(t2, &dummy));
4809 }
4810
4811
4812 rs = timelib_astro_rise_set_altitude(t, longitude, latitude, -18.0, 0, &ddummy, &ddummy, &rise, &set, &transit);
4813 switch (rs) {
4814 case -1:
4815 add_assoc_bool(return_value, "astronomical_twilight_begin", 0);
4816 add_assoc_bool(return_value, "astronomical_twilight_end", 0);
4817 break;
4818 case 1:
4819 add_assoc_bool(return_value, "astronomical_twilight_begin", 1);
4820 add_assoc_bool(return_value, "astronomical_twilight_end", 1);
4821 break;
4822 default:
4823 t2->sse = rise;
4824 add_assoc_long(return_value, "astronomical_twilight_begin", timelib_date_to_int(t2, &dummy));
4825 t2->sse = set;
4826 add_assoc_long(return_value, "astronomical_twilight_end", timelib_date_to_int(t2, &dummy));
4827 }
4828 timelib_time_dtor(t);
4829 timelib_time_dtor(t2);
4830 }
4831
4832
4833 static HashTable *date_object_get_gc_period(zval *object, zval **table, int *n)
4834 {
4835 *table = NULL;
4836 *n = 0;
4837 return zend_std_get_properties(object);
4838 }
4839
4840 static HashTable *date_object_get_properties_period(zval *object)
4841 {
4842 HashTable *props;
4843 zval zv;
4844 php_period_obj *period_obj;
4845
4846 period_obj = Z_PHPPERIOD_P(object);
4847
4848 props = zend_std_get_properties(object);
4849
4850 if (!period_obj->start || GC_G(gc_active)) {
4851 return props;
4852 }
4853
4854 if (period_obj->start) {
4855 php_date_obj *date_obj;
4856 object_init_ex(&zv, date_ce_date);
4857 date_obj = Z_PHPDATE_P(&zv);
4858 date_obj->time = timelib_time_clone(period_obj->start);
4859 } else {
4860 ZVAL_NULL(&zv);
4861 }
4862 zend_hash_str_update(props, "start", sizeof("start")-1, &zv);
4863
4864 if (period_obj->current) {
4865 php_date_obj *date_obj;
4866 object_init_ex(&zv, date_ce_date);
4867 date_obj = Z_PHPDATE_P(&zv);
4868 date_obj->time = timelib_time_clone(period_obj->current);
4869 } else {
4870 ZVAL_NULL(&zv);
4871 }
4872 zend_hash_str_update(props, "current", sizeof("current")-1, &zv);
4873
4874 if (period_obj->end) {
4875 php_date_obj *date_obj;
4876 object_init_ex(&zv, date_ce_date);
4877 date_obj = Z_PHPDATE_P(&zv);
4878 date_obj->time = timelib_time_clone(period_obj->end);
4879 } else {
4880 ZVAL_NULL(&zv);
4881 }
4882 zend_hash_str_update(props, "end", sizeof("end")-1, &zv);
4883
4884 if (period_obj->interval) {
4885 php_interval_obj *interval_obj;
4886 object_init_ex(&zv, date_ce_interval);
4887 interval_obj = Z_PHPINTERVAL_P(&zv);
4888 interval_obj->diff = timelib_rel_time_clone(period_obj->interval);
4889 interval_obj->initialized = 1;
4890 } else {
4891 ZVAL_NULL(&zv);
4892 }
4893 zend_hash_str_update(props, "interval", sizeof("interval")-1, &zv);
4894
4895
4896 ZVAL_LONG(&zv, (zend_long) period_obj->recurrences);
4897 zend_hash_str_update(props, "recurrences", sizeof("recurrences")-1, &zv);
4898
4899 ZVAL_BOOL(&zv, period_obj->include_start_date);
4900 zend_hash_str_update(props, "include_start_date", sizeof("include_start_date")-1, &zv);
4901
4902 return props;
4903 }
4904
4905 static int php_date_period_initialize_from_hash(php_period_obj *period_obj, HashTable *myht)
4906 {
4907 zval *ht_entry;
4908
4909
4910
4911 ht_entry = zend_hash_str_find(myht, "start", sizeof("start")-1);
4912 if (ht_entry) {
4913 if (Z_TYPE_P(ht_entry) == IS_OBJECT && Z_OBJCE_P(ht_entry) == date_ce_date) {
4914 php_date_obj *date_obj;
4915 date_obj = Z_PHPDATE_P(ht_entry);
4916 period_obj->start = timelib_time_clone(date_obj->time);
4917 period_obj->start_ce = Z_OBJCE_P(ht_entry);
4918 } else if (Z_TYPE_P(ht_entry) != IS_NULL) {
4919 return 0;
4920 }
4921 } else {
4922 return 0;
4923 }
4924
4925 ht_entry = zend_hash_str_find(myht, "end", sizeof("end")-1);
4926 if (ht_entry) {
4927 if (Z_TYPE_P(ht_entry) == IS_OBJECT && Z_OBJCE_P(ht_entry) == date_ce_date) {
4928 php_date_obj *date_obj;
4929 date_obj = Z_PHPDATE_P(ht_entry);
4930 period_obj->end = timelib_time_clone(date_obj->time);
4931 } else if (Z_TYPE_P(ht_entry) != IS_NULL) {
4932 return 0;
4933 }
4934 } else {
4935 return 0;
4936 }
4937
4938 ht_entry = zend_hash_str_find(myht, "current", sizeof("current")-1);
4939 if (ht_entry) {
4940 if (Z_TYPE_P(ht_entry) == IS_OBJECT && Z_OBJCE_P(ht_entry) == date_ce_date) {
4941 php_date_obj *date_obj;
4942 date_obj = Z_PHPDATE_P(ht_entry);
4943 period_obj->current = timelib_time_clone(date_obj->time);
4944 } else if (Z_TYPE_P(ht_entry) != IS_NULL) {
4945 return 0;
4946 }
4947 } else {
4948 return 0;
4949 }
4950
4951 ht_entry = zend_hash_str_find(myht, "interval", sizeof("interval")-1);
4952 if (ht_entry) {
4953 if (Z_TYPE_P(ht_entry) == IS_OBJECT && Z_OBJCE_P(ht_entry) == date_ce_interval) {
4954 php_interval_obj *interval_obj;
4955 interval_obj = Z_PHPINTERVAL_P(ht_entry);
4956 period_obj->interval = timelib_rel_time_clone(interval_obj->diff);
4957 } else {
4958 return 0;
4959 }
4960 } else {
4961 return 0;
4962 }
4963
4964 ht_entry = zend_hash_str_find(myht, "recurrences", sizeof("recurrences")-1);
4965 if (ht_entry &&
4966 Z_TYPE_P(ht_entry) == IS_LONG && Z_LVAL_P(ht_entry) >= 0 && Z_LVAL_P(ht_entry) <= INT_MAX) {
4967 period_obj->recurrences = Z_LVAL_P(ht_entry);
4968 } else {
4969 return 0;
4970 }
4971
4972 ht_entry = zend_hash_str_find(myht, "include_start_date", sizeof("include_start_date")-1);
4973 if (ht_entry &&
4974 (Z_TYPE_P(ht_entry) == IS_FALSE || Z_TYPE_P(ht_entry) == IS_TRUE)) {
4975 period_obj->include_start_date = (Z_TYPE_P(ht_entry) == IS_TRUE);
4976 } else {
4977 return 0;
4978 }
4979
4980 period_obj->initialized = 1;
4981
4982 return 1;
4983 }
4984
4985
4986
4987 PHP_METHOD(DatePeriod, __set_state)
4988 {
4989 php_period_obj *period_obj;
4990 zval *array;
4991 HashTable *myht;
4992
4993 if (zend_parse_parameters(ZEND_NUM_ARGS(), "a", &array) == FAILURE) {
4994 RETURN_FALSE;
4995 }
4996
4997 myht = Z_ARRVAL_P(array);
4998
4999 object_init_ex(return_value, date_ce_period);
5000 period_obj = Z_PHPPERIOD_P(return_value);
5001 if (!php_date_period_initialize_from_hash(period_obj, myht)) {
5002 php_error(E_ERROR, "Invalid serialization data for DatePeriod object");
5003 }
5004 }
5005
5006
5007
5008
5009 PHP_METHOD(DatePeriod, __wakeup)
5010 {
5011 zval *object = getThis();
5012 php_period_obj *period_obj;
5013 HashTable *myht;
5014
5015 period_obj = Z_PHPPERIOD_P(object);
5016
5017 myht = Z_OBJPROP_P(object);
5018
5019 if (!php_date_period_initialize_from_hash(period_obj, myht)) {
5020 php_error(E_ERROR, "Invalid serialization data for DatePeriod object");
5021 }
5022 }
5023
5024
5025
5026 static zval *date_period_read_property(zval *object, zval *member, int type, void **cache_slot, zval *rv)
5027 {
5028 zval *zv;
5029 if (type != BP_VAR_IS && type != BP_VAR_R) {
5030 php_error_docref(NULL, E_ERROR, "Retrieval of DatePeriod properties for modification is unsupported");
5031 }
5032
5033 Z_OBJPROP_P(object);
5034
5035 zv = std_object_handlers.read_property(object, member, type, cache_slot, rv);
5036 if (Z_TYPE_P(zv) == IS_OBJECT && Z_OBJ_HANDLER_P(zv, clone_obj)) {
5037
5038 ZVAL_OBJ(zv, Z_OBJ_HANDLER_P(zv, clone_obj)(zv));
5039 }
5040
5041 return zv;
5042 }
5043
5044
5045
5046 static void date_period_write_property(zval *object, zval *member, zval *value, void **cache_slot)
5047 {
5048 php_error_docref(NULL, E_ERROR, "Writing to DatePeriod properties is unsupported");
5049 }
5050
5051
5052
5053
5054
5055
5056
5057
5058
5059