php-internal-docs 8.4.8
Unofficial docs for php/php-src
Loading...
Searching...
No Matches
php_date.c
Go to the documentation of this file.
1/*
2 +----------------------------------------------------------------------+
3 | Copyright (c) The PHP Group |
4 +----------------------------------------------------------------------+
5 | This source file is subject to version 3.01 of the PHP license, |
6 | that is bundled with this package in the file LICENSE, and is |
7 | available through the world-wide-web at the following url: |
8 | https://www.php.net/license/3_01.txt |
9 | If you did not receive a copy of the PHP license and are unable to |
10 | obtain it through the world-wide-web, please send a note to |
11 | license@php.net so we can mail you a copy immediately. |
12 +----------------------------------------------------------------------+
13 | Authors: Derick Rethans <derick@derickrethans.nl> |
14 +----------------------------------------------------------------------+
15 */
16
17#include "php.h"
18#include "php_main.h"
19#include "php_ini.h"
20#include "ext/standard/info.h"
22#include "php_date.h"
23#include "zend_attributes.h"
24#include "zend_interfaces.h"
25#include "zend_exceptions.h"
26#include "lib/timelib.h"
27#include "lib/timelib_private.h"
28#ifndef PHP_WIN32
29#include <time.h>
30#else
31#include "win32/time.h"
32#endif
33
34#ifdef PHP_WIN32
35static __inline __int64 php_date_llabs( __int64 i ) { return i >= 0? i: -i; }
36#elif defined(__GNUC__) && __GNUC__ < 3
37static __inline __int64_t php_date_llabs( __int64_t i ) { return i >= 0 ? i : -i; }
38#else
39static 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#define DATE_A64I(i, s) i = strtoll(s, NULL, 10)
54#endif
55
56PHPAPI time_t php_time(void)
57{
58#ifdef HAVE_GETTIMEOFDAY
59 struct timeval tm;
60
61 if (UNEXPECTED(gettimeofday(&tm, NULL) != SUCCESS)) {
62 /* fallback, can't reasonably happen */
63 return time(NULL);
64 }
65
66 return tm.tv_sec;
67#else
68 return time(NULL);
69#endif
70}
71
72/*
73 * RFC822, Section 5.1: http://www.ietf.org/rfc/rfc822.txt
74 * date-time = [ day "," ] date time ; dd mm yy hh:mm:ss zzz
75 * day = "Mon" / "Tue" / "Wed" / "Thu" / "Fri" / "Sat" / "Sun"
76 * date = 1*2DIGIT month 2DIGIT ; day month year e.g. 20 Jun 82
77 * month = "Jan" / "Feb" / "Mar" / "Apr" / "May" / "Jun" / "Jul" / "Aug" / "Sep" / "Oct" / "Nov" / "Dec"
78 * time = hour zone ; ANSI and Military
79 * hour = 2DIGIT ":" 2DIGIT [":" 2DIGIT] ; 00:00:00 - 23:59:59
80 * zone = "UT" / "GMT" / "EST" / "EDT" / "CST" / "CDT" / "MST" / "MDT" / "PST" / "PDT" / 1ALPHA / ( ("+" / "-") 4DIGIT )
81 */
82#define DATE_FORMAT_RFC822 "D, d M y H:i:s O"
83
84/*
85 * RFC850, Section 2.1.4: http://www.ietf.org/rfc/rfc850.txt
86 * Format must be acceptable both to the ARPANET and to the getdate routine.
87 * One format that is acceptable to both is Weekday, DD-Mon-YY HH:MM:SS TIMEZONE
88 * TIMEZONE can be any timezone name (3 or more letters)
89 */
90#define DATE_FORMAT_RFC850 "l, d-M-y H:i:s T"
91
92/*
93 * RFC1036, Section 2.1.2: http://www.ietf.org/rfc/rfc1036.txt
94 * Its format must be acceptable both in RFC-822 and to the getdate(3)
95 * Wdy, DD Mon YY HH:MM:SS TIMEZONE
96 * There is no hope of having a complete list of timezones. Universal
97 * Time (GMT), the North American timezones (PST, PDT, MST, MDT, CST,
98 * CDT, EST, EDT) and the +/-hhmm offset specified in RFC-822 should be supported.
99 */
100#define DATE_FORMAT_RFC1036 "D, d M y H:i:s O"
101
102/*
103 * RFC1123, Section 5.2.14: http://www.ietf.org/rfc/rfc1123.txt
104 * RFC-822 Date and Time Specification: RFC-822 Section 5
105 * The syntax for the date is hereby changed to: date = 1*2DIGIT month 2*4DIGIT
106 */
107#define DATE_FORMAT_RFC1123 "D, d M Y H:i:s O"
108
109/*
110 * RFC7231, Section 7.1.1: http://tools.ietf.org/html/rfc7231
111 */
112#define DATE_FORMAT_RFC7231 "D, d M Y H:i:s \\G\\M\\T"
113
114/*
115 * RFC2822, Section 3.3: http://www.ietf.org/rfc/rfc2822.txt
116 * FWS = ([*WSP CRLF] 1*WSP) / ; Folding white space
117 * CFWS = *([FWS] comment) (([FWS] comment) / FWS)
118 *
119 * date-time = [ day-of-week "," ] date FWS time [CFWS]
120 * day-of-week = ([FWS] day-name)
121 * day-name = "Mon" / "Tue" / "Wed" / "Thu" / "Fri" / "Sat" / "Sun"
122 * date = day month year
123 * year = 4*DIGIT
124 * month = (FWS month-name FWS)
125 * month-name = "Jan" / "Feb" / "Mar" / "Apr" / "May" / "Jun" / "Jul" / "Aug" / "Sep" / "Oct" / "Nov" / "Dec"
126 * day = ([FWS] 1*2DIGIT)
127 * time = time-of-day FWS zone
128 * time-of-day = hour ":" minute [ ":" second ]
129 * hour = 2DIGIT
130 * minute = 2DIGIT
131 * second = 2DIGIT
132 * zone = (( "+" / "-" ) 4DIGIT)
133 */
134#define DATE_FORMAT_RFC2822 "D, d M Y H:i:s O"
135
136/*
137 * RFC3339, Section 5.6: http://www.ietf.org/rfc/rfc3339.txt
138 * date-fullyear = 4DIGIT
139 * date-month = 2DIGIT ; 01-12
140 * date-mday = 2DIGIT ; 01-28, 01-29, 01-30, 01-31 based on month/year
141 *
142 * time-hour = 2DIGIT ; 00-23
143 * time-minute = 2DIGIT ; 00-59
144 * time-second = 2DIGIT ; 00-58, 00-59, 00-60 based on leap second rules
145 *
146 * time-secfrac = "." 1*DIGIT
147 * time-numoffset = ("+" / "-") time-hour ":" time-minute
148 * time-offset = "Z" / time-numoffset
149 *
150 * partial-time = time-hour ":" time-minute ":" time-second [time-secfrac]
151 * full-date = date-fullyear "-" date-month "-" date-mday
152 * full-time = partial-time time-offset
153 *
154 * date-time = full-date "T" full-time
155 */
156#define DATE_FORMAT_RFC3339 "Y-m-d\\TH:i:sP"
157
158/*
159 * This format does not technically match the ISO 8601 standard, as it does not
160 * use : in the UTC offset format specifier. This is kept for BC reasons. The
161 * DATE_FORMAT_ISO8601_EXPANDED format does correct this, as well as adding
162 * support for years out side of the traditional 0000-9999 range.
163 */
164#define DATE_FORMAT_ISO8601 "Y-m-d\\TH:i:sO"
165
166/* ISO 8601:2004(E)
167 *
168 * Section 3.5 Expansion:
169 * By mutual agreement of the partners in information interchange, it is
170 * permitted to expand the component identifying the calendar year, which is
171 * otherwise limited to four digits. This enables reference to dates and times
172 * in calendar years outside the range supported by complete representations,
173 * i.e. before the start of the year [0000] or after the end of the year
174 * [9999]."
175 *
176 * Section 4.1.2.4 Expanded representations:
177 * If, by agreement, expanded representations are used, the formats shall be as
178 * specified below. The interchange parties shall agree the additional number of
179 * digits in the time element year. In the examples below it has been agreed to
180 * expand the time element year with two digits.
181 * Extended format: ±YYYYY-MM-DD
182 * Example: +001985-04-12
183 *
184 * PHP's year expansion digits are variable.
185 */
186#define DATE_FORMAT_ISO8601_EXPANDED "X-m-d\\TH:i:sP"
187
188/* Internal Only
189 * This format only extends the year when needed, keeping the 'P' format with
190 * colon for UTC offsets
191 */
192#define DATE_FORMAT_ISO8601_LARGE_YEAR "x-m-d\\TH:i:sP"
193
194/*
195 * RFC3339, Appendix A: http://www.ietf.org/rfc/rfc3339.txt
196 * ISO 8601 also requires (in section 5.3.1.3) that a decimal fraction
197 * be proceeded by a "0" if less than unity. Annex B.2 of ISO 8601
198 * gives examples where the decimal fractions are not preceded by a "0".
199 * This grammar assumes section 5.3.1.3 is correct and that Annex B.2 is
200 * in error.
201 */
202#define DATE_FORMAT_RFC3339_EXTENDED "Y-m-d\\TH:i:s.vP"
203
204/*
205 * This comes from various sources that like to contradict. I'm going with the
206 * format here because of:
207 * http://msdn.microsoft.com/en-us/library/windows/desktop/aa384321%28v=vs.85%29.aspx
208 * and http://curl.haxx.se/rfc/cookie_spec.html
209 */
210#define DATE_FORMAT_COOKIE "l, d-M-Y H:i:s T"
211
212#define SUNFUNCS_RET_TIMESTAMP 0
213#define SUNFUNCS_RET_STRING 1
214#define SUNFUNCS_RET_DOUBLE 2
215
216#define PHP_DATE_TIMEZONE_GROUP_AFRICA 0x0001
217#define PHP_DATE_TIMEZONE_GROUP_AMERICA 0x0002
218#define PHP_DATE_TIMEZONE_GROUP_ANTARCTICA 0x0004
219#define PHP_DATE_TIMEZONE_GROUP_ARCTIC 0x0008
220#define PHP_DATE_TIMEZONE_GROUP_ASIA 0x0010
221#define PHP_DATE_TIMEZONE_GROUP_ATLANTIC 0x0020
222#define PHP_DATE_TIMEZONE_GROUP_AUSTRALIA 0x0040
223#define PHP_DATE_TIMEZONE_GROUP_EUROPE 0x0080
224#define PHP_DATE_TIMEZONE_GROUP_INDIAN 0x0100
225#define PHP_DATE_TIMEZONE_GROUP_PACIFIC 0x0200
226#define PHP_DATE_TIMEZONE_GROUP_UTC 0x0400
227#define PHP_DATE_TIMEZONE_GROUP_ALL 0x07FF
228#define PHP_DATE_TIMEZONE_GROUP_ALL_W_BC 0x0FFF
229#define PHP_DATE_TIMEZONE_PER_COUNTRY 0x1000
230
231#define PHP_DATE_PERIOD_EXCLUDE_START_DATE 0x0001
232#define PHP_DATE_PERIOD_INCLUDE_END_DATE 0x0002
233
234#include "php_date_arginfo.h"
235
236static const char* guess_timezone(const timelib_tzdb *tzdb);
237static void date_register_classes(void);
238/* }}} */
239
242
243/* True global */
246
247#define DATE_DEFAULT_LATITUDE "31.7667"
248#define DATE_DEFAULT_LONGITUDE "35.2333"
249
250/* on 90'50; common sunset declaration (start of sun body appear) */
251#define DATE_SUNSET_ZENITH "90.833333"
252
253/* on 90'50; common sunrise declaration (sun body disappeared) */
254#define DATE_SUNRISE_ZENITH "90.833333"
255
256static PHP_INI_MH(OnUpdate_date_timezone);
257
258/* {{{ INI Settings */
260 STD_PHP_INI_ENTRY("date.timezone", "UTC", PHP_INI_ALL, OnUpdate_date_timezone, default_timezone, zend_date_globals, date_globals)
261 PHP_INI_ENTRY("date.default_latitude", DATE_DEFAULT_LATITUDE, PHP_INI_ALL, NULL)
262 PHP_INI_ENTRY("date.default_longitude", DATE_DEFAULT_LONGITUDE, PHP_INI_ALL, NULL)
263 PHP_INI_ENTRY("date.sunset_zenith", DATE_SUNSET_ZENITH, PHP_INI_ALL, NULL)
264 PHP_INI_ENTRY("date.sunrise_zenith", DATE_SUNRISE_ZENITH, PHP_INI_ALL, NULL)
266/* }}} */
267
268static zend_class_entry *date_ce_date, *date_ce_timezone, *date_ce_interval, *date_ce_period;
269static zend_class_entry *date_ce_immutable, *date_ce_interface;
270static zend_class_entry *date_ce_date_error, *date_ce_date_object_error, *date_ce_date_range_error;
271static zend_class_entry *date_ce_date_exception, *date_ce_date_invalid_timezone_exception, *date_ce_date_invalid_operation_exception, *date_ce_date_malformed_string_exception, *date_ce_date_malformed_interval_string_exception, *date_ce_date_malformed_period_string_exception;
272
273
275{
276 return date_ce_date;
277}
278
280{
281 return date_ce_immutable;
282}
283
285{
286 return date_ce_interface;
287}
288
290{
291 return date_ce_timezone;
292}
293
295{
296 return date_ce_interval;
297}
298
300{
301 return date_ce_period;
302}
303
304static zend_object_handlers date_object_handlers_date;
305static zend_object_handlers date_object_handlers_immutable;
306static zend_object_handlers date_object_handlers_timezone;
307static zend_object_handlers date_object_handlers_interval;
308static zend_object_handlers date_object_handlers_period;
309
310static void date_throw_uninitialized_error(zend_class_entry *ce)
311{
312 if (ce->type == ZEND_INTERNAL_CLASS) {
313 zend_throw_error(date_ce_date_object_error, "Object of type %s has not been correctly initialized by calling parent::__construct() in its constructor", ZSTR_VAL(ce->name));
314 } else {
315 zend_class_entry *ce_ptr = ce;
316 while (ce_ptr && ce_ptr->parent && ce_ptr->type == ZEND_USER_CLASS) {
317 ce_ptr = ce_ptr->parent;
318 }
319 if (ce_ptr->type != ZEND_INTERNAL_CLASS) {
320 zend_throw_error(date_ce_date_object_error, "Object of type %s not been correctly initialized by calling parent::__construct() in its constructor", ZSTR_VAL(ce->name));
321 return;
322 }
323 zend_throw_error(date_ce_date_object_error, "Object of type %s (inheriting %s) has not been correctly initialized by calling parent::__construct() in its constructor", ZSTR_VAL(ce->name), ZSTR_VAL(ce_ptr->name));
324 }
325}
326
327#define DATE_CHECK_INITIALIZED(member, ce) \
328 if (UNEXPECTED(!member)) { \
329 date_throw_uninitialized_error(ce); \
330 RETURN_THROWS(); \
331 }
332
333static void date_object_free_storage_date(zend_object *object);
334static void date_object_free_storage_timezone(zend_object *object);
335static void date_object_free_storage_interval(zend_object *object);
336static void date_object_free_storage_period(zend_object *object);
337
338static zend_object *date_object_new_date(zend_class_entry *class_type);
339static zend_object *date_object_new_timezone(zend_class_entry *class_type);
340static zend_object *date_object_new_interval(zend_class_entry *class_type);
341static zend_object *date_object_new_period(zend_class_entry *class_type);
342
343static zend_object *date_object_clone_date(zend_object *this_ptr);
344static zend_object *date_object_clone_timezone(zend_object *this_ptr);
345static zend_object *date_object_clone_interval(zend_object *this_ptr);
346static zend_object *date_object_clone_period(zend_object *this_ptr);
347
348static int date_object_compare_date(zval *d1, zval *d2);
349static HashTable *date_object_get_gc(zend_object *object, zval **table, int *n);
350static HashTable *date_object_get_properties_for(zend_object *object, zend_prop_purpose purpose);
351static HashTable *date_object_get_gc_interval(zend_object *object, zval **table, int *n);
352static HashTable *date_object_get_properties_interval(zend_object *object);
353static HashTable *date_object_get_gc_period(zend_object *object, zval **table, int *n);
354static HashTable *date_object_get_properties_for_timezone(zend_object *object, zend_prop_purpose purpose);
355static HashTable *date_object_get_gc_timezone(zend_object *object, zval **table, int *n);
356static HashTable *date_object_get_debug_info_timezone(zend_object *object, int *is_temp);
357static void php_timezone_to_string(php_timezone_obj *tzobj, zval *zv);
358
359static int date_interval_compare_objects(zval *o1, zval *o2);
360static zval *date_interval_read_property(zend_object *object, zend_string *member, int type, void **cache_slot, zval *rv);
361static zval *date_interval_write_property(zend_object *object, zend_string *member, zval *value, void **cache_slot);
362static zval *date_interval_get_property_ptr_ptr(zend_object *object, zend_string *member, int type, void **cache_slot);
363static zval *date_period_read_property(zend_object *object, zend_string *name, int type, void **cache_slot, zval *rv);
364static zval *date_period_write_property(zend_object *object, zend_string *name, zval *value, void **cache_slot);
365static zval *date_period_get_property_ptr_ptr(zend_object *object, zend_string *name, int type, void **cache_slot);
366
367static int date_object_compare_timezone(zval *tz1, zval *tz2);
368
369/* {{{ Module struct */
372 NULL,
373 NULL,
374 "date", /* extension name */
375 ext_functions, /* function list */
376 PHP_MINIT(date), /* process startup */
377 PHP_MSHUTDOWN(date), /* process shutdown */
378 PHP_RINIT(date), /* request startup */
379 PHP_RSHUTDOWN(date), /* request shutdown */
380 PHP_MINFO(date), /* extension info */
381 PHP_DATE_VERSION, /* extension version */
382 PHP_MODULE_GLOBALS(date), /* globals descriptor */
383 PHP_GINIT(date), /* globals ctor */
384 NULL, /* globals dtor */
385 ZEND_MODULE_POST_ZEND_DEACTIVATE_N(date), /* post deactivate */
387};
388/* }}} */
389
390
391/* {{{ PHP_GINIT_FUNCTION */
393{
394 date_globals->default_timezone = NULL;
395 date_globals->timezone = NULL;
396 date_globals->tzcache = NULL;
397}
398/* }}} */
399
400
401static void _php_date_tzinfo_dtor(zval *zv) /* {{{ */
402{
404
406} /* }}} */
407
408/* {{{ PHP_RINIT_FUNCTION */
410{
411 if (DATEG(timezone)) {
413 }
415 DATEG(tzcache) = NULL;
417
418 return SUCCESS;
419}
420/* }}} */
421
422/* {{{ PHP_RSHUTDOWN_FUNCTION */
424{
425 if (DATEG(timezone)) {
427 }
429
430 return SUCCESS;
431}
432/* }}} */
433
449
450#define DATE_TIMEZONEDB php_date_global_timezone_db ? php_date_global_timezone_db : timelib_builtin_db()
451
452/* {{{ PHP_MINIT_FUNCTION */
454{
456 date_register_classes();
457 register_php_date_symbols(module_number);
458
462 return SUCCESS;
463}
464/* }}} */
465
466/* {{{ PHP_MSHUTDOWN_FUNCTION */
468{
470
471 if (DATEG(last_errors)) {
473 }
474
475#ifndef ZTS
477#endif
478
479 return SUCCESS;
480}
481/* }}} */
482
483/* {{{ PHP_MINFO_FUNCTION */
485{
486 const timelib_tzdb *tzdb = DATE_TIMEZONEDB;
487
489 php_info_print_table_row(2, "date/time support", "enabled");
490 php_info_print_table_row(2, "timelib version", TIMELIB_ASCII_VERSION);
491 php_info_print_table_row(2, "\"Olson\" Timezone Database Version", tzdb->version);
492 php_info_print_table_row(2, "Timezone Database", php_date_global_timezone_db_enabled ? "external" : "internal");
493 php_info_print_table_row(2, "Default timezone", guess_timezone(tzdb));
495
497}
498/* }}} */
499
500/* {{{ Timezone Cache functions */
501static timelib_tzinfo *php_date_parse_tzfile(const char *formal_tzname, const timelib_tzdb *tzdb)
502{
503 timelib_tzinfo *tzi;
504 int dummy_error_code;
505
506 if(!DATEG(tzcache)) {
508 zend_hash_init(DATEG(tzcache), 4, NULL, _php_date_tzinfo_dtor, 0);
509 }
510
511 if ((tzi = zend_hash_str_find_ptr(DATEG(tzcache), formal_tzname, strlen(formal_tzname))) != NULL) {
512 return tzi;
513 }
514
515 tzi = timelib_parse_tzfile(formal_tzname, tzdb, &dummy_error_code);
516 if (tzi) {
517 zend_hash_str_add_ptr(DATEG(tzcache), formal_tzname, strlen(formal_tzname), tzi);
518 }
519 return tzi;
520}
521
522static timelib_tzinfo *php_date_parse_tzfile_wrapper(const char *formal_tzname, const timelib_tzdb *tzdb, int *dummy_error_code)
523{
524 return php_date_parse_tzfile(formal_tzname, tzdb);
525}
526/* }}} */
527
528/* Callback to check the date.timezone only when changed increases performance */
529/* {{{ static PHP_INI_MH(OnUpdate_date_timezone) */
530static PHP_INI_MH(OnUpdate_date_timezone)
531{
532 if (new_value && !timelib_timezone_id_is_valid(ZSTR_VAL(new_value), DATE_TIMEZONEDB)) {
535 "Invalid date.timezone value '%s', using '%s' instead",
536 ZSTR_VAL(new_value),
538 );
539 return FAILURE;
540 }
541
542 if (OnUpdateString(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage) == FAILURE) {
543 return FAILURE;
544 }
545
546 return SUCCESS;
547}
548/* }}} */
549
550/* {{{ Helper functions */
551static const char* guess_timezone(const timelib_tzdb *tzdb)
552{
553 /* Checking whether timezone has been set with date_default_timezone_set() */
554 if (DATEG(timezone) && (strlen(DATEG(timezone))) > 0) {
555 return DATEG(timezone);
556 }
557 /* Check config setting for default timezone */
558 if (!DATEG(default_timezone)) {
559 /* Special case: ext/date wasn't initialized yet */
560 zval *ztz;
561
562 if (NULL != (ztz = cfg_get_entry("date.timezone", sizeof("date.timezone")))
563 && Z_TYPE_P(ztz) == IS_STRING && Z_STRLEN_P(ztz) > 0 && timelib_timezone_id_is_valid(Z_STRVAL_P(ztz), tzdb)) {
564 return Z_STRVAL_P(ztz);
565 }
566 } else if (*DATEG(default_timezone)) {
567 return DATEG(default_timezone);
568 }
569 /* Fallback to UTC */
570 return "UTC";
571}
572
574{
575 timelib_tzinfo *tzi;
576
577 const char *tz = guess_timezone(DATE_TIMEZONEDB);
578 tzi = php_date_parse_tzfile(tz, DATE_TIMEZONEDB);
579 if (! tzi) {
580 zend_throw_error(date_ce_date_error, "Timezone database is corrupt. Please file a bug report as this should never happen");
581 }
582 return tzi;
583}
584
585static void update_property(zend_object *object, zend_string *key, zval *prop_val)
586{
587 if (ZSTR_LEN(key) > 0 && ZSTR_VAL(key)[0] == '\0') { // not public
588 const char *class_name, *prop_name;
589 size_t prop_name_len;
590
591 if (zend_unmangle_property_name_ex(key, &class_name, &prop_name, &prop_name_len) == SUCCESS) {
592 if (class_name[0] != '*') { // private
593 zend_string *cname;
595
596 cname = zend_string_init(class_name, strlen(class_name), 0);
597 ce = zend_lookup_class(cname);
598
599 if (ce) {
600 zend_update_property(ce, object, prop_name, prop_name_len, prop_val);
601 }
602
603 zend_string_release_ex(cname, 0);
604 } else { // protected
605 zend_update_property(object->ce, object, prop_name, prop_name_len, prop_val);
606 }
607 }
608 return;
609 }
610
611 // public
612 zend_update_property(object->ce, object, ZSTR_VAL(key), ZSTR_LEN(key), prop_val);
613}
614/* }}} */
615
616
617/* {{{ date() and gmdate() data */
618#include "zend_smart_str.h"
619
620static const char * const mon_full_names[] = {
621 "January", "February", "March", "April",
622 "May", "June", "July", "August",
623 "September", "October", "November", "December"
624};
625
626static const char * const mon_short_names[] = {
627 "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
628};
629
630static const char * const day_full_names[] = {
631 "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"
632};
633
634static const char * const day_short_names[] = {
635 "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
636};
637
638static const char *english_suffix(timelib_sll number)
639{
640 if (number >= 10 && number <= 19) {
641 return "th";
642 } else {
643 switch (number % 10) {
644 case 1: return "st";
645 case 2: return "nd";
646 case 3: return "rd";
647 }
648 }
649 return "th";
650}
651/* }}} */
652
653/* {{{ day of week helpers */
654static const char *php_date_full_day_name(timelib_sll y, timelib_sll m, timelib_sll d)
655{
656 timelib_sll day_of_week = timelib_day_of_week(y, m, d);
657 if (day_of_week < 0) {
658 return "Unknown";
659 }
660 return day_full_names[day_of_week];
661}
662
663static const char *php_date_short_day_name(timelib_sll y, timelib_sll m, timelib_sll d)
664{
665 timelib_sll day_of_week = timelib_day_of_week(y, m, d);
666 if (day_of_week < 0) {
667 return "Unknown";
668 }
669 return day_short_names[day_of_week];
670}
671/* }}} */
672
673/* {{{ date_format - (gm)date helper */
674static zend_string *date_format(const char *format, size_t format_len, timelib_time *t, bool localtime)
675{
676 smart_str string = {0};
677 size_t i;
678 int length = 0;
679 char buffer[97];
681 timelib_sll isoweek, isoyear;
682 bool rfc_colon;
683 int weekYearSet = 0;
684
685 if (!format_len) {
686 return ZSTR_EMPTY_ALLOC();
687 }
688
689 if (localtime) {
692 offset->offset = (t->z + (t->dst * 3600));
693 offset->leap_secs = 0;
694 offset->is_dst = t->dst;
695 offset->abbr = timelib_strdup(t->tz_abbr);
696 } else if (t->zone_type == TIMELIB_ZONETYPE_OFFSET) {
698 offset->offset = (t->z);
699 offset->leap_secs = 0;
700 offset->is_dst = 0;
701 offset->abbr = timelib_malloc(9); /* GMT±xxxx\0 */
702 snprintf(offset->abbr, 9, "GMT%c%02d%02d",
703 (offset->offset < 0) ? '-' : '+',
704 abs(offset->offset / 3600),
705 abs((offset->offset % 3600) / 60));
706 } else if (t->zone_type == TIMELIB_ZONETYPE_ID) {
708 } else {
709 /* Shouldn't happen, but code defensively */
711 }
712 }
713
714 for (i = 0; i < format_len; i++) {
715 rfc_colon = 0;
716 switch (format[i]) {
717 /* day */
718 case 'd': length = slprintf(buffer, sizeof(buffer), "%02d", (int) t->d); break;
719 case 'D': length = slprintf(buffer, sizeof(buffer), "%s", php_date_short_day_name(t->y, t->m, t->d)); break;
720 case 'j': length = slprintf(buffer, sizeof(buffer), "%d", (int) t->d); break;
721 case 'l': length = slprintf(buffer, sizeof(buffer), "%s", php_date_full_day_name(t->y, t->m, t->d)); break;
722 case 'S': length = slprintf(buffer, sizeof(buffer), "%s", english_suffix(t->d)); break;
723 case 'w': length = slprintf(buffer, sizeof(buffer), "%d", (int) timelib_day_of_week(t->y, t->m, t->d)); break;
724 case 'N': length = slprintf(buffer, sizeof(buffer), "%d", (int) timelib_iso_day_of_week(t->y, t->m, t->d)); break;
725 case 'z': length = slprintf(buffer, sizeof(buffer), "%d", (int) timelib_day_of_year(t->y, t->m, t->d)); break;
726
727 /* week */
728 case 'W':
729 if(!weekYearSet) { timelib_isoweek_from_date(t->y, t->m, t->d, &isoweek, &isoyear); weekYearSet = 1; }
730 length = slprintf(buffer, sizeof(buffer), "%02d", (int) isoweek); break; /* iso weeknr */
731 case 'o':
732 if(!weekYearSet) { timelib_isoweek_from_date(t->y, t->m, t->d, &isoweek, &isoyear); weekYearSet = 1; }
733 length = slprintf(buffer, sizeof(buffer), ZEND_LONG_FMT, (zend_long) isoyear); break; /* iso year */
734
735 /* month */
736 case 'F': length = slprintf(buffer, sizeof(buffer), "%s", mon_full_names[t->m - 1]); break;
737 case 'm': length = slprintf(buffer, sizeof(buffer), "%02d", (int) t->m); break;
738 case 'M': length = slprintf(buffer, sizeof(buffer), "%s", mon_short_names[t->m - 1]); break;
739 case 'n': length = slprintf(buffer, sizeof(buffer), "%d", (int) t->m); break;
740 case 't': length = slprintf(buffer, sizeof(buffer), "%d", (int) timelib_days_in_month(t->y, t->m)); break;
741
742 /* year */
743 case 'L': length = slprintf(buffer, sizeof(buffer), "%d", timelib_is_leap((int) t->y)); break;
744 case 'y': length = slprintf(buffer, sizeof(buffer), "%02d", (int) (t->y % 100)); break;
745 case 'Y': length = slprintf(buffer, sizeof(buffer), "%s%04lld", t->y < 0 ? "-" : "", php_date_llabs((timelib_sll) t->y)); break;
746 case 'x': length = slprintf(buffer, sizeof(buffer), "%s%04lld", t->y < 0 ? "-" : (t->y >= 10000 ? "+" : ""), php_date_llabs((timelib_sll) t->y)); break;
747 case 'X': length = slprintf(buffer, sizeof(buffer), "%s%04lld", t->y < 0 ? "-" : "+", php_date_llabs((timelib_sll) t->y)); break;
748
749 /* time */
750 case 'a': length = slprintf(buffer, sizeof(buffer), "%s", t->h >= 12 ? "pm" : "am"); break;
751 case 'A': length = slprintf(buffer, sizeof(buffer), "%s", t->h >= 12 ? "PM" : "AM"); break;
752 case 'B': {
753 int retval = ((((long)t->sse)-(((long)t->sse) - ((((long)t->sse) % 86400) + 3600))) * 10);
754 if (retval < 0) {
755 retval += 864000;
756 }
757 /* Make sure to do this on a positive int to avoid rounding errors */
758 retval = (retval / 864) % 1000;
759 length = slprintf(buffer, sizeof(buffer), "%03d", retval);
760 break;
761 }
762 case 'g': length = slprintf(buffer, sizeof(buffer), "%d", (t->h % 12) ? (int) t->h % 12 : 12); break;
763 case 'G': length = slprintf(buffer, sizeof(buffer), "%d", (int) t->h); break;
764 case 'h': length = slprintf(buffer, sizeof(buffer), "%02d", (t->h % 12) ? (int) t->h % 12 : 12); break;
765 case 'H': length = slprintf(buffer, sizeof(buffer), "%02d", (int) t->h); break;
766 case 'i': length = slprintf(buffer, sizeof(buffer), "%02d", (int) t->i); break;
767 case 's': length = slprintf(buffer, sizeof(buffer), "%02d", (int) t->s); break;
768 case 'u': length = slprintf(buffer, sizeof(buffer), "%06d", (int) floor(t->us)); break;
769 case 'v': length = slprintf(buffer, sizeof(buffer), "%03d", (int) floor(t->us / 1000)); break;
770
771 /* timezone */
772 case 'I': length = slprintf(buffer, sizeof(buffer), "%d", localtime ? offset->is_dst : 0); break;
773 case 'p':
774 if (!localtime || strcmp(offset->abbr, "UTC") == 0 || strcmp(offset->abbr, "Z") == 0 || strcmp(offset->abbr, "GMT+0000") == 0) {
775 length = slprintf(buffer, sizeof(buffer), "%s", "Z");
776 break;
777 }
779 case 'P': rfc_colon = 1; ZEND_FALLTHROUGH;
780 case 'O': length = slprintf(buffer, sizeof(buffer), "%c%02d%s%02d",
781 localtime ? ((offset->offset < 0) ? '-' : '+') : '+',
782 localtime ? abs(offset->offset / 3600) : 0,
783 rfc_colon ? ":" : "",
784 localtime ? abs((offset->offset % 3600) / 60) : 0
785 );
786 break;
787 case 'T': length = slprintf(buffer, sizeof(buffer), "%s", localtime ? offset->abbr : "GMT"); break;
788 case 'e': if (!localtime) {
789 length = slprintf(buffer, sizeof(buffer), "%s", "UTC");
790 } else {
791 switch (t->zone_type) {
793 length = slprintf(buffer, sizeof(buffer), "%s", t->tz_info->name);
794 break;
796 length = slprintf(buffer, sizeof(buffer), "%s", offset->abbr);
797 break;
799 length = slprintf(buffer, sizeof(buffer), "%c%02d:%02d",
800 ((offset->offset < 0) ? '-' : '+'),
801 abs(offset->offset / 3600),
802 abs((offset->offset % 3600) / 60)
803 );
804 break;
805 }
806 }
807 break;
808 case 'Z': length = slprintf(buffer, sizeof(buffer), "%d", localtime ? offset->offset : 0); break;
809
810 /* full date/time */
811 case 'c': length = slprintf(buffer, sizeof(buffer), "%04" ZEND_LONG_FMT_SPEC "-%02d-%02dT%02d:%02d:%02d%c%02d:%02d",
812 (zend_long) t->y, (int) t->m, (int) t->d,
813 (int) t->h, (int) t->i, (int) t->s,
814 localtime ? ((offset->offset < 0) ? '-' : '+') : '+',
815 localtime ? abs(offset->offset / 3600) : 0,
816 localtime ? abs((offset->offset % 3600) / 60) : 0
817 );
818 break;
819 case 'r': length = slprintf(buffer, sizeof(buffer), "%3s, %02d %3s %04" ZEND_LONG_FMT_SPEC " %02d:%02d:%02d %c%02d%02d",
820 php_date_short_day_name(t->y, t->m, t->d),
821 (int) t->d, mon_short_names[t->m - 1],
822 (zend_long) t->y, (int) t->h, (int) t->i, (int) t->s,
823 localtime ? ((offset->offset < 0) ? '-' : '+') : '+',
824 localtime ? abs(offset->offset / 3600) : 0,
825 localtime ? abs((offset->offset % 3600) / 60) : 0
826 );
827 break;
828 case 'U': length = slprintf(buffer, sizeof(buffer), "%lld", (timelib_sll) t->sse); break;
829
830 case '\\': if (i < format_len) i++; ZEND_FALLTHROUGH;
831
832 default: buffer[0] = format[i]; buffer[1] = '\0'; length = 1; break;
833 }
834 smart_str_appendl(&string, buffer, length);
835 }
836
837 smart_str_0(&string);
838
839 if (localtime) {
841 }
842
843 return string.s;
844}
845
846PHPAPI zend_string *php_format_date_obj(const char *format, size_t format_len, php_date_obj *date_obj)
847{
848 if (!date_obj->time) {
849 return NULL;
850 }
851
852 return date_format(format, format_len, date_obj->time, date_obj->time->is_localtime);
853}
854
855static void php_date(INTERNAL_FUNCTION_PARAMETERS, bool localtime)
856{
857 zend_string *format;
858 zend_long ts;
859 bool ts_is_null = 1;
860
862 Z_PARAM_STR(format)
864 Z_PARAM_LONG_OR_NULL(ts, ts_is_null)
866
867 if (ts_is_null) {
868 ts = php_time();
869 }
870
871 RETURN_STR(php_format_date(ZSTR_VAL(format), ZSTR_LEN(format), ts, localtime));
872}
873/* }}} */
874
875PHPAPI zend_string *php_format_date(const char *format, size_t format_len, time_t ts, bool localtime) /* {{{ */
876{
877 timelib_time *t;
878 timelib_tzinfo *tzi;
879 zend_string *string;
880
881 t = timelib_time_ctor();
882
883 if (localtime) {
884 tzi = get_timezone_info();
885 t->tz_info = tzi;
888 } else {
889 tzi = NULL;
891 }
892
893 string = date_format(format, format_len, t, localtime);
894
896 return string;
897}
898/* }}} */
899
900/* {{{ php_idate */
901PHPAPI int php_idate(char format, time_t ts, bool localtime)
902{
903 timelib_time *t;
904 timelib_tzinfo *tzi;
905 int retval = -1;
907 timelib_sll isoweek, isoyear;
908
909 t = timelib_time_ctor();
910
911 if (!localtime) {
912 tzi = get_timezone_info();
913 t->tz_info = tzi;
916 } else {
917 tzi = NULL;
919 }
920
921 if (!localtime) {
924 offset->offset = (t->z + (t->dst * 3600));
925 offset->leap_secs = 0;
926 offset->is_dst = t->dst;
927 offset->abbr = timelib_strdup(t->tz_abbr);
928 } else if (t->zone_type == TIMELIB_ZONETYPE_OFFSET) {
930 offset->offset = (t->z + (t->dst * 3600));
931 offset->leap_secs = 0;
932 offset->is_dst = t->dst;
933 offset->abbr = timelib_malloc(9); /* GMT±xxxx\0 */
934 snprintf(offset->abbr, 9, "GMT%c%02d%02d",
935 (offset->offset < 0) ? '-' : '+',
936 abs(offset->offset / 3600),
937 abs((offset->offset % 3600) / 60));
938 } else {
940 }
941 }
942
943 timelib_isoweek_from_date(t->y, t->m, t->d, &isoweek, &isoyear);
944
945 switch (format) {
946 /* day */
947 case 'd': case 'j': retval = (int) t->d; break;
948
949 case 'N': retval = (int) timelib_iso_day_of_week(t->y, t->m, t->d); break;
950 case 'w': retval = (int) timelib_day_of_week(t->y, t->m, t->d); break;
951 case 'z': retval = (int) timelib_day_of_year(t->y, t->m, t->d); break;
952
953 /* week */
954 case 'W': retval = (int) isoweek; break; /* iso weeknr */
955
956 /* month */
957 case 'm': case 'n': retval = (int) t->m; break;
958 case 't': retval = (int) timelib_days_in_month(t->y, t->m); break;
959
960 /* year */
961 case 'L': retval = (int) timelib_is_leap((int) t->y); break;
962 case 'y': retval = (int) (t->y % 100); break;
963 case 'Y': retval = (int) t->y; break;
964 case 'o': retval = (int) isoyear; break; /* iso year */
965
966 /* Swatch Beat a.k.a. Internet Time */
967 case 'B':
968 retval = ((((long)t->sse)-(((long)t->sse) - ((((long)t->sse) % 86400) + 3600))) * 10);
969 if (retval < 0) {
970 retval += 864000;
971 }
972 /* Make sure to do this on a positive int to avoid rounding errors */
973 retval = (retval / 864) % 1000;
974 break;
975
976 /* time */
977 case 'g': case 'h': retval = (int) ((t->h % 12) ? (int) t->h % 12 : 12); break;
978 case 'H': case 'G': retval = (int) t->h; break;
979 case 'i': retval = (int) t->i; break;
980 case 's': retval = (int) t->s; break;
981
982 /* timezone */
983 case 'I': retval = (int) (!localtime ? offset->is_dst : 0); break;
984 case 'Z': retval = (int) (!localtime ? offset->offset : 0); break;
985
986 case 'U': retval = (int) t->sse; break;
987 }
988
989 if (!localtime) {
991 }
993
994 return retval;
995}
996/* }}} */
997
998/* {{{ Format a local date/time */
1000{
1002}
1003/* }}} */
1004
1005/* {{{ Format a GMT date/time */
1010/* }}} */
1011
1012/* {{{ Format a local time/date as integer */
1014{
1015 zend_string *format;
1016 zend_long ts;
1017 bool ts_is_null = 1;
1018 int ret;
1019
1021 Z_PARAM_STR(format)
1023 Z_PARAM_LONG_OR_NULL(ts, ts_is_null)
1025
1026 if (ZSTR_LEN(format) != 1) {
1027 php_error_docref(NULL, E_WARNING, "idate format is one char");
1029 }
1030
1031 if (ts_is_null) {
1032 ts = php_time();
1033 }
1034
1035 ret = php_idate(ZSTR_VAL(format)[0], ts, 0);
1036 if (ret == -1) {
1037 php_error_docref(NULL, E_WARNING, "Unrecognized date format token");
1039 }
1041}
1042/* }}} */
1043
1044/* {{{ php_date_set_tzdb - NOT THREADSAFE */
1046{
1047 const timelib_tzdb *builtin = timelib_builtin_db();
1048
1049 if (php_version_compare(tzdb->version, builtin->version) > 0) {
1052 }
1053}
1054/* }}} */
1055
1056/* {{{ php_parse_date: Backwards compatibility function */
1058{
1059 timelib_time *parsed_time;
1061 int error2;
1063
1064 parsed_time = timelib_strtotime(string, strlen(string), &error, DATE_TIMEZONEDB, php_date_parse_tzfile_wrapper);
1065 if (error->error_count) {
1066 timelib_time_dtor(parsed_time);
1068 return -1;
1069 }
1071 timelib_update_ts(parsed_time, NULL);
1072 retval = timelib_date_to_int(parsed_time, &error2);
1073 timelib_time_dtor(parsed_time);
1074 if (error2) {
1075 return -1;
1076 }
1077 return retval;
1078}
1079/* }}} */
1080
1081/* {{{ Convert string representation of date and time to a timestamp */
1083{
1084 zend_string *times;
1085 int parse_error, epoch_does_not_fit_in_zend_long;
1087 zend_long preset_ts, ts;
1088 bool preset_ts_is_null = 1;
1089 timelib_time *t, *now;
1090 timelib_tzinfo *tzi;
1091
1093 Z_PARAM_STR(times)
1095 Z_PARAM_LONG_OR_NULL(preset_ts, preset_ts_is_null)
1097
1098 /* timelib_strtotime() expects the string to not be empty */
1099 if (ZSTR_LEN(times) == 0) {
1101 }
1102
1103 tzi = get_timezone_info();
1104 if (!tzi) {
1105 return;
1106 }
1107
1109 now->tz_info = tzi;
1110 now->zone_type = TIMELIB_ZONETYPE_ID;
1112 !preset_ts_is_null ? (timelib_sll) preset_ts : (timelib_sll) php_time());
1113
1114 t = timelib_strtotime(ZSTR_VAL(times), ZSTR_LEN(times), &error,
1115 DATE_TIMEZONEDB, php_date_parse_tzfile_wrapper);
1116 parse_error = error->error_count;
1118 if (parse_error) {
1122 }
1123
1125 timelib_update_ts(t, tzi);
1126 ts = timelib_date_to_int(t, &epoch_does_not_fit_in_zend_long);
1127
1130
1131 if (epoch_does_not_fit_in_zend_long) {
1132 php_error_docref(NULL, E_WARNING, "Epoch doesn't fit in a PHP integer");
1134 }
1135
1136 RETURN_LONG(ts);
1137}
1138/* }}} */
1139
1140/* {{{ php_mktime - (gm)mktime helper */
1142{
1143 zend_long hou, min, sec, mon, day, yea;
1144 bool min_is_null = 1, sec_is_null = 1, mon_is_null = 1, day_is_null = 1, yea_is_null = 1;
1146 timelib_tzinfo *tzi = NULL;
1147 zend_long ts, adjust_seconds = 0;
1148 int epoch_does_not_fit_in_zend_long;
1149
1151 Z_PARAM_LONG(hou)
1153 Z_PARAM_LONG_OR_NULL(min, min_is_null)
1154 Z_PARAM_LONG_OR_NULL(sec, sec_is_null)
1155 Z_PARAM_LONG_OR_NULL(mon, mon_is_null)
1156 Z_PARAM_LONG_OR_NULL(day, day_is_null)
1157 Z_PARAM_LONG_OR_NULL(yea, yea_is_null)
1159
1160 /* Initialize structure with current time */
1162 if (gmt) {
1164 } else {
1165 tzi = get_timezone_info();
1166 if (!tzi) {
1167 return;
1168 }
1169 now->tz_info = tzi;
1170 now->zone_type = TIMELIB_ZONETYPE_ID;
1172 }
1173
1174 now->h = hou;
1175
1176 if (!min_is_null) {
1177 now->i = min;
1178 }
1179
1180 if (!sec_is_null) {
1181 now->s = sec;
1182 }
1183
1184 if (!mon_is_null) {
1185 now->m = mon;
1186 }
1187
1188 if (!day_is_null) {
1189 now->d = day;
1190 }
1191
1192 if (!yea_is_null) {
1193 if (yea >= 0 && yea < 70) {
1194 yea += 2000;
1195 } else if (yea >= 70 && yea <= 100) {
1196 yea += 1900;
1197 }
1198 now->y = yea;
1199 }
1200
1201 /* Update the timestamp */
1202 if (gmt) {
1204 } else {
1205 timelib_update_ts(now, tzi);
1206 }
1207
1208 /* Clean up and return */
1209 ts = timelib_date_to_int(now, &epoch_does_not_fit_in_zend_long);
1210
1211 if (epoch_does_not_fit_in_zend_long) {
1213 php_error_docref(NULL, E_WARNING, "Epoch doesn't fit in a PHP integer");
1215 }
1216
1217 ts += adjust_seconds;
1219
1220 RETURN_LONG(ts);
1221}
1222/* }}} */
1223
1224/* {{{ Get UNIX timestamp for a date */
1229/* }}} */
1230
1231/* {{{ Get UNIX timestamp for a GMT date */
1236/* }}} */
1237
1238/* {{{ Returns true(1) if it is a valid date in gregorian calendar */
1240{
1241 zend_long m, d, y;
1242
1244 Z_PARAM_LONG(m)
1245 Z_PARAM_LONG(d)
1246 Z_PARAM_LONG(y)
1248
1249 if (y < 1 || y > 32767 || !timelib_valid_date(y, m, d)) {
1251 }
1252 RETURN_TRUE; /* True : This month, day, year arguments are valid */
1253}
1254/* }}} */
1255
1256/* {{{ php_strftime - (gm)strftime helper */
1258{
1259 zend_string *format;
1260 zend_long timestamp;
1261 bool timestamp_is_null = 1;
1262 struct tm ta;
1263 int max_reallocs = 5;
1264 size_t buf_len = 256, real_len;
1265 timelib_time *ts;
1266 timelib_tzinfo *tzi;
1269
1271 Z_PARAM_STR(format)
1273 Z_PARAM_LONG_OR_NULL(timestamp, timestamp_is_null)
1275
1276 if (ZSTR_LEN(format) == 0) {
1278 }
1279
1280 if (timestamp_is_null) {
1281 timestamp = (zend_long) php_time();
1282 }
1283
1284 ts = timelib_time_ctor();
1285 if (gmt) {
1286 tzi = NULL;
1287 timelib_unixtime2gmt(ts, (timelib_sll) timestamp);
1288 } else {
1289 tzi = get_timezone_info();
1290 if (!tzi) {
1291 return;
1292 }
1293 ts->tz_info = tzi;
1295 timelib_unixtime2local(ts, (timelib_sll) timestamp);
1296 }
1297 ta.tm_sec = ts->s;
1298 ta.tm_min = ts->i;
1299 ta.tm_hour = ts->h;
1300 ta.tm_mday = ts->d;
1301 ta.tm_mon = ts->m - 1;
1302 ta.tm_year = ts->y - 1900;
1303 ta.tm_wday = timelib_day_of_week(ts->y, ts->m, ts->d);
1304 ta.tm_yday = timelib_day_of_year(ts->y, ts->m, ts->d);
1305 if (gmt) {
1306 ta.tm_isdst = 0;
1307#ifdef HAVE_STRUCT_TM_TM_GMTOFF
1308 ta.tm_gmtoff = 0;
1309#endif
1310#ifdef HAVE_STRUCT_TM_TM_ZONE
1311 ta.tm_zone = "GMT";
1312#endif
1313 } else {
1314 offset = timelib_get_time_zone_info(timestamp, tzi);
1315
1316 ta.tm_isdst = offset->is_dst;
1317#ifdef HAVE_STRUCT_TM_TM_GMTOFF
1318 ta.tm_gmtoff = offset->offset;
1319#endif
1320#ifdef HAVE_STRUCT_TM_TM_ZONE
1321 ta.tm_zone = offset->abbr;
1322#endif
1323 }
1324
1325 /* VS2012 crt has a bug where strftime crash with %z and %Z format when the
1326 initial buffer is too small. See
1327 http://connect.microsoft.com/VisualStudio/feedback/details/759720/vs2012-strftime-crash-with-z-formatting-code */
1328 buf = zend_string_alloc(buf_len, 0);
1329 while ((real_len = strftime(ZSTR_VAL(buf), buf_len, ZSTR_VAL(format), &ta)) == buf_len || real_len == 0) {
1330 buf_len *= 2;
1331 buf = zend_string_extend(buf, buf_len, 0);
1332 if (!--max_reallocs) {
1333 break;
1334 }
1335 }
1336#ifdef PHP_WIN32
1337 /* VS2012 strftime() returns number of characters, not bytes.
1338 See VC++11 bug id 766205. */
1339 if (real_len > 0) {
1340 real_len = strlen(buf->val);
1341 }
1342#endif
1343
1345 if (!gmt) {
1347 }
1348
1349 if (real_len && real_len != buf_len) {
1350 buf = zend_string_truncate(buf, real_len, 0);
1352 }
1353 zend_string_efree(buf);
1355}
1356/* }}} */
1357
1358/* {{{ Format a local time/date according to locale settings */
1363/* }}} */
1364
1365/* {{{ Format a GMT/UCT time/date according to locale settings */
1370/* }}} */
1371
1372/* {{{ Return current UNIX timestamp */
1379/* }}} */
1380
1381/* {{{ Returns the results of the C system call localtime as an associative array if the associative_array argument is set to 1 other wise it is a regular array */
1383{
1384 zend_long timestamp;
1385 bool timestamp_is_null = 1;
1386 bool associative = 0;
1387 timelib_tzinfo *tzi;
1388 timelib_time *ts;
1389
1392 Z_PARAM_LONG_OR_NULL(timestamp, timestamp_is_null)
1393 Z_PARAM_BOOL(associative)
1395
1396 if (timestamp_is_null) {
1397 timestamp = (zend_long) php_time();
1398 }
1399
1400 tzi = get_timezone_info();
1401 if (!tzi) {
1402 RETURN_THROWS();
1403 }
1404 ts = timelib_time_ctor();
1405 ts->tz_info = tzi;
1407 timelib_unixtime2local(ts, (timelib_sll) timestamp);
1408
1410
1411 if (associative) {
1412 add_assoc_long(return_value, "tm_sec", ts->s);
1413 add_assoc_long(return_value, "tm_min", ts->i);
1414 add_assoc_long(return_value, "tm_hour", ts->h);
1415 add_assoc_long(return_value, "tm_mday", ts->d);
1416 add_assoc_long(return_value, "tm_mon", ts->m - 1);
1417 add_assoc_long(return_value, "tm_year", ts->y - 1900);
1418 add_assoc_long(return_value, "tm_wday", timelib_day_of_week(ts->y, ts->m, ts->d));
1419 add_assoc_long(return_value, "tm_yday", timelib_day_of_year(ts->y, ts->m, ts->d));
1420 add_assoc_long(return_value, "tm_isdst", ts->dst);
1421 } else {
1431 }
1432
1434}
1435/* }}} */
1436
1437/* {{{ Get date/time information */
1439{
1440 zend_long timestamp;
1441 bool timestamp_is_null = 1;
1442 timelib_tzinfo *tzi;
1443 timelib_time *ts;
1444
1447 Z_PARAM_LONG_OR_NULL(timestamp, timestamp_is_null)
1449
1450 if (timestamp_is_null) {
1451 timestamp = (zend_long) php_time();
1452 }
1453
1454 tzi = get_timezone_info();
1455 if (!tzi) {
1456 RETURN_THROWS();
1457 }
1458 ts = timelib_time_ctor();
1459 ts->tz_info = tzi;
1461 timelib_unixtime2local(ts, (timelib_sll) timestamp);
1462
1464
1465 add_assoc_long(return_value, "seconds", ts->s);
1466 add_assoc_long(return_value, "minutes", ts->i);
1467 add_assoc_long(return_value, "hours", ts->h);
1468 add_assoc_long(return_value, "mday", ts->d);
1469 add_assoc_long(return_value, "wday", timelib_day_of_week(ts->y, ts->m, ts->d));
1470 add_assoc_long(return_value, "mon", ts->m);
1471 add_assoc_long(return_value, "year", ts->y);
1472 add_assoc_long(return_value, "yday", timelib_day_of_year(ts->y, ts->m, ts->d));
1473 add_assoc_string(return_value, "weekday", php_date_full_day_name(ts->y, ts->m, ts->d));
1474 add_assoc_string(return_value, "month", mon_full_names[ts->m - 1]);
1475 add_index_long(return_value, 0, timestamp);
1476
1478}
1479/* }}} */
1480
1481static void create_date_period_datetime(timelib_time *datetime, zend_class_entry *ce, zval *zv)
1482{
1483 if (datetime) {
1484 php_date_obj *date_obj;
1485
1486 object_init_ex(zv, ce);
1487 date_obj = Z_PHPDATE_P(zv);
1488 date_obj->time = timelib_time_clone(datetime);
1489 } else {
1490 ZVAL_NULL(zv);
1491 }
1492}
1493
1494static void create_date_period_interval(timelib_rel_time *interval, zval *zv)
1495{
1496 if (interval) {
1497 php_interval_obj *interval_obj;
1498
1499 object_init_ex(zv, date_ce_interval);
1500 interval_obj = Z_PHPINTERVAL_P(zv);
1501 interval_obj->diff = timelib_rel_time_clone(interval);
1502 interval_obj->initialized = 1;
1503 } else {
1504 ZVAL_NULL(zv);
1505 }
1506}
1507
1508static void write_date_period_property(zend_object *obj, const char *name, const size_t name_len, zval *zv)
1509{
1510 zend_string *property_name = zend_string_init(name, name_len, 0);
1511
1512 zend_std_write_property(obj, property_name, zv, NULL);
1513
1515 zend_string_release(property_name);
1516}
1517
1518static void initialize_date_period_properties(php_period_obj *period_obj)
1519{
1520 zval zv;
1521
1522 /* rebuild properties */
1523 zend_std_get_properties_ex(&period_obj->std);
1524
1525 create_date_period_datetime(period_obj->start, period_obj->start_ce, &zv);
1526 write_date_period_property(&period_obj->std, "start", sizeof("start") - 1, &zv);
1527
1528 create_date_period_datetime(period_obj->current, period_obj->start_ce, &zv);
1529 write_date_period_property(&period_obj->std, "current", sizeof("current") - 1, &zv);
1530
1531 create_date_period_datetime(period_obj->end, period_obj->start_ce, &zv);
1532 write_date_period_property(&period_obj->std, "end", sizeof("end") - 1, &zv);
1533
1534 create_date_period_interval(period_obj->interval, &zv);
1535 write_date_period_property(&period_obj->std, "interval", sizeof("interval") - 1, &zv);
1536
1537 ZVAL_LONG(&zv, (zend_long) period_obj->recurrences);
1538 write_date_period_property(&period_obj->std, "recurrences", sizeof("recurrences") - 1, &zv);
1539
1540 ZVAL_BOOL(&zv, period_obj->include_start_date);
1541 write_date_period_property(&period_obj->std, "include_start_date", sizeof("include_start_date") - 1, &zv);
1542
1543 ZVAL_BOOL(&zv, period_obj->include_end_date);
1544 write_date_period_property(&period_obj->std, "include_end_date", sizeof("include_end_date") - 1, &zv);
1545}
1546
1547/* define an overloaded iterator structure */
1554
1555/* {{{ date_period_it_invalidate_current */
1556static void date_period_it_invalidate_current(zend_object_iterator *iter)
1557{
1558 date_period_it *iterator = (date_period_it *)iter;
1559
1560 if (Z_TYPE(iterator->current) != IS_UNDEF) {
1561 zval_ptr_dtor(&iterator->current);
1562 ZVAL_UNDEF(&iterator->current);
1563 }
1564}
1565/* }}} */
1566
1567/* {{{ date_period_it_dtor */
1568static void date_period_it_dtor(zend_object_iterator *iter)
1569{
1570 date_period_it *iterator = (date_period_it *)iter;
1571
1572 date_period_it_invalidate_current(iter);
1573
1574 zval_ptr_dtor(&iterator->intern.data);
1575}
1576/* }}} */
1577
1578/* {{{ date_period_it_has_more */
1579static zend_result date_period_it_has_more(zend_object_iterator *iter)
1580{
1581 date_period_it *iterator = (date_period_it *)iter;
1582 php_period_obj *object = Z_PHPPERIOD_P(&iterator->intern.data);
1583
1584 if (object->end) {
1585 if (object->current->sse == object->end->sse) {
1586 if (object->include_end_date) {
1587 return object->current->us <= object->end->us ? SUCCESS : FAILURE;
1588 } else {
1589 return object->current->us < object->end->us ? SUCCESS : FAILURE;
1590 }
1591 }
1592
1593 return object->current->sse < object->end->sse ? SUCCESS : FAILURE;
1594 } else {
1595 return (iterator->current_index < object->recurrences) ? SUCCESS : FAILURE;
1596 }
1597}
1598/* }}} */
1599
1600static zend_class_entry *get_base_date_class(zend_class_entry *start_ce)
1601{
1602 zend_class_entry *tmp = start_ce;
1603
1604 while (tmp != date_ce_date && tmp != date_ce_immutable && tmp->parent) {
1605 tmp = tmp->parent;
1606 }
1607
1608 return tmp;
1609}
1610
1611/* {{{ date_period_it_current_data */
1612static zval *date_period_it_current_data(zend_object_iterator *iter)
1613{
1614 date_period_it *iterator = (date_period_it *)iter;
1615 php_period_obj *object = Z_PHPPERIOD_P(&iterator->intern.data);
1616 timelib_time *it_time = object->current;
1617 php_date_obj *newdateobj;
1618
1619 /* Create new object */
1620 php_date_instantiate(get_base_date_class(object->start_ce), &iterator->current);
1621 newdateobj = Z_PHPDATE_P(&iterator->current);
1622 newdateobj->time = timelib_time_ctor();
1623 *newdateobj->time = *it_time;
1624 if (it_time->tz_abbr) {
1625 newdateobj->time->tz_abbr = timelib_strdup(it_time->tz_abbr);
1626 }
1627 if (it_time->tz_info) {
1628 newdateobj->time->tz_info = it_time->tz_info;
1629 }
1630
1631 return &iterator->current;
1632}
1633/* }}} */
1634
1635/* {{{ date_period_it_current_key */
1636static void date_period_it_current_key(zend_object_iterator *iter, zval *key)
1637{
1638 date_period_it *iterator = (date_period_it *)iter;
1639 ZVAL_LONG(key, iterator->current_index);
1640}
1641/* }}} */
1642
1643static void date_period_advance(timelib_time *it_time, timelib_rel_time *interval)
1644{
1645 it_time->have_relative = 1;
1646 it_time->relative = *interval;
1647 it_time->sse_uptodate = 0;
1648 timelib_update_ts(it_time, NULL);
1649 timelib_update_from_sse(it_time);
1650}
1651
1652/* {{{ date_period_it_move_forward */
1653static void date_period_it_move_forward(zend_object_iterator *iter)
1654{
1655 date_period_it *iterator = (date_period_it *)iter;
1656 php_period_obj *object = Z_PHPPERIOD_P(&iterator->intern.data);
1657 timelib_time *it_time = object->current;
1658 zval current_zv;
1659
1660 date_period_advance(it_time, object->interval);
1661
1662 /* rebuild properties */
1663 zend_std_get_properties_ex(&object->std);
1664
1665 create_date_period_datetime(object->current, object->start_ce, &current_zv);
1666 zend_string *property_name = ZSTR_INIT_LITERAL("current", 0);
1667 zend_std_write_property(&object->std, property_name, &current_zv, NULL);
1668 zval_ptr_dtor(&current_zv);
1669 zend_string_release(property_name);
1670
1671 iterator->current_index++;
1672 date_period_it_invalidate_current(iter);
1673}
1674/* }}} */
1675
1676/* {{{ date_period_it_rewind */
1677static void date_period_it_rewind(zend_object_iterator *iter)
1678{
1679 date_period_it *iterator = (date_period_it *)iter;
1680
1681 iterator->current_index = 0;
1682 if (iterator->object->current) {
1683 timelib_time_dtor(iterator->object->current);
1684 }
1685 if (!iterator->object->start) {
1686 date_throw_uninitialized_error(date_ce_period);
1687 return;
1688 }
1689
1690 iterator->object->current = timelib_time_clone(iterator->object->start);
1691
1692 if (!iterator->object->include_start_date) {
1693 date_period_advance(iterator->object->current, iterator->object->interval);
1694 }
1695
1696 date_period_it_invalidate_current(iter);
1697}
1698/* }}} */
1699
1700/* iterator handler table */
1701static const zend_object_iterator_funcs date_period_it_funcs = {
1702 date_period_it_dtor,
1703 date_period_it_has_more,
1704 date_period_it_current_data,
1705 date_period_it_current_key,
1706 date_period_it_move_forward,
1707 date_period_it_rewind,
1708 date_period_it_invalidate_current,
1709 NULL, /* get_gc */
1710};
1711
1712static zend_object_iterator *date_object_period_get_iterator(zend_class_entry *ce, zval *object, int by_ref) /* {{{ */
1713{
1714 date_period_it *iterator;
1715
1716 if (by_ref) {
1717 zend_throw_error(NULL, "An iterator cannot be used with foreach by reference");
1718 return NULL;
1719 }
1720
1721 iterator = emalloc(sizeof(date_period_it));
1722
1724
1725 ZVAL_OBJ_COPY(&iterator->intern.data, Z_OBJ_P(object));
1726 iterator->intern.funcs = &date_period_it_funcs;
1727 iterator->object = Z_PHPPERIOD_P(object);
1728 ZVAL_UNDEF(&iterator->current);
1729
1730 return (zend_object_iterator*)iterator;
1731} /* }}} */
1732
1733static int implement_date_interface_handler(zend_class_entry *interface, zend_class_entry *implementor) /* {{{ */
1734{
1735 if (implementor->type == ZEND_USER_CLASS &&
1736 !instanceof_function(implementor, date_ce_date) &&
1737 !instanceof_function(implementor, date_ce_immutable)
1738 ) {
1739 zend_error_noreturn(E_ERROR, "DateTimeInterface can't be implemented by user classes");
1740 }
1741
1742 return SUCCESS;
1743} /* }}} */
1744
1745static int date_interval_has_property(zend_object *object, zend_string *name, int type, void **cache_slot) /* {{{ */
1746{
1747 php_interval_obj *obj;
1748 zval rv;
1749 zval *prop;
1750 int retval = 0;
1751
1752 obj = php_interval_obj_from_obj(object);
1753
1754 if (!obj->initialized) {
1755 retval = zend_std_has_property(object, name, type, cache_slot);
1756 return retval;
1757 }
1758
1759 prop = date_interval_read_property(object, name, BP_VAR_IS, cache_slot, &rv);
1760
1761 if (prop != &EG(uninitialized_zval)) {
1762 if (type == 2) {
1763 retval = 1;
1764 } else if (type == 1) {
1765 retval = zend_is_true(prop);
1766 } else if (type == 0) {
1767 retval = (Z_TYPE_P(prop) != IS_NULL);
1768 }
1769 } else {
1770 retval = zend_std_has_property(object, name, type, cache_slot);
1771 }
1772
1773 return retval;
1774
1775}
1776/* }}} */
1777
1778static void date_register_classes(void) /* {{{ */
1779{
1780 date_ce_interface = register_class_DateTimeInterface();
1781 date_ce_interface->interface_gets_implemented = implement_date_interface_handler;
1782
1783 date_ce_date = register_class_DateTime(date_ce_interface);
1784 date_ce_date->create_object = date_object_new_date;
1785 date_ce_date->default_object_handlers = &date_object_handlers_date;
1786 memcpy(&date_object_handlers_date, &std_object_handlers, sizeof(zend_object_handlers));
1787 date_object_handlers_date.offset = XtOffsetOf(php_date_obj, std);
1788 date_object_handlers_date.free_obj = date_object_free_storage_date;
1789 date_object_handlers_date.clone_obj = date_object_clone_date;
1790 date_object_handlers_date.compare = date_object_compare_date;
1791 date_object_handlers_date.get_properties_for = date_object_get_properties_for;
1792 date_object_handlers_date.get_gc = date_object_get_gc;
1793
1794 date_ce_immutable = register_class_DateTimeImmutable(date_ce_interface);
1795 date_ce_immutable->create_object = date_object_new_date;
1796 date_ce_immutable->default_object_handlers = &date_object_handlers_date;
1797 memcpy(&date_object_handlers_immutable, &std_object_handlers, sizeof(zend_object_handlers));
1798 date_object_handlers_immutable.clone_obj = date_object_clone_date;
1799 date_object_handlers_immutable.compare = date_object_compare_date;
1800 date_object_handlers_immutable.get_properties_for = date_object_get_properties_for;
1801 date_object_handlers_immutable.get_gc = date_object_get_gc;
1802
1803 date_ce_timezone = register_class_DateTimeZone();
1804 date_ce_timezone->create_object = date_object_new_timezone;
1805 date_ce_timezone->default_object_handlers = &date_object_handlers_timezone;
1806 memcpy(&date_object_handlers_timezone, &std_object_handlers, sizeof(zend_object_handlers));
1807 date_object_handlers_timezone.offset = XtOffsetOf(php_timezone_obj, std);
1808 date_object_handlers_timezone.free_obj = date_object_free_storage_timezone;
1809 date_object_handlers_timezone.clone_obj = date_object_clone_timezone;
1810 date_object_handlers_timezone.get_properties_for = date_object_get_properties_for_timezone;
1811 date_object_handlers_timezone.get_gc = date_object_get_gc_timezone;
1812 date_object_handlers_timezone.get_debug_info = date_object_get_debug_info_timezone;
1813 date_object_handlers_timezone.compare = date_object_compare_timezone;
1814
1815 date_ce_interval = register_class_DateInterval();
1816 date_ce_interval->create_object = date_object_new_interval;
1817 date_ce_interval->default_object_handlers = &date_object_handlers_interval;
1818 memcpy(&date_object_handlers_interval, &std_object_handlers, sizeof(zend_object_handlers));
1819 date_object_handlers_interval.offset = XtOffsetOf(php_interval_obj, std);
1820 date_object_handlers_interval.free_obj = date_object_free_storage_interval;
1821 date_object_handlers_interval.clone_obj = date_object_clone_interval;
1822 date_object_handlers_interval.has_property = date_interval_has_property;
1823 date_object_handlers_interval.read_property = date_interval_read_property;
1824 date_object_handlers_interval.write_property = date_interval_write_property;
1825 date_object_handlers_interval.get_properties = date_object_get_properties_interval;
1826 date_object_handlers_interval.get_property_ptr_ptr = date_interval_get_property_ptr_ptr;
1827 date_object_handlers_interval.get_gc = date_object_get_gc_interval;
1828 date_object_handlers_interval.compare = date_interval_compare_objects;
1829
1830 date_ce_period = register_class_DatePeriod(zend_ce_aggregate);
1831 date_ce_period->create_object = date_object_new_period;
1832 date_ce_period->default_object_handlers = &date_object_handlers_period;
1833 date_ce_period->get_iterator = date_object_period_get_iterator;
1834 memcpy(&date_object_handlers_period, &std_object_handlers, sizeof(zend_object_handlers));
1835 date_object_handlers_period.offset = XtOffsetOf(php_period_obj, std);
1836 date_object_handlers_period.free_obj = date_object_free_storage_period;
1837 date_object_handlers_period.clone_obj = date_object_clone_period;
1838 date_object_handlers_period.get_gc = date_object_get_gc_period;
1839 date_object_handlers_period.get_property_ptr_ptr = date_period_get_property_ptr_ptr;
1840 date_object_handlers_period.read_property = date_period_read_property;
1841 date_object_handlers_period.write_property = date_period_write_property;
1842
1843 date_ce_date_error = register_class_DateError(zend_ce_error);
1844 date_ce_date_object_error = register_class_DateObjectError(date_ce_date_error);
1845 date_ce_date_range_error = register_class_DateRangeError(date_ce_date_error);
1846
1847 date_ce_date_exception = register_class_DateException(zend_ce_exception);
1848 date_ce_date_invalid_timezone_exception = register_class_DateInvalidTimeZoneException(date_ce_date_exception);
1849 date_ce_date_invalid_operation_exception = register_class_DateInvalidOperationException(date_ce_date_exception);
1850 date_ce_date_malformed_string_exception = register_class_DateMalformedStringException(date_ce_date_exception);
1851 date_ce_date_malformed_interval_string_exception = register_class_DateMalformedIntervalStringException(date_ce_date_exception);
1852 date_ce_date_malformed_period_string_exception = register_class_DateMalformedPeriodStringException(date_ce_date_exception);
1853} /* }}} */
1854
1855static zend_object *date_object_new_date(zend_class_entry *class_type) /* {{{ */
1856{
1857 php_date_obj *intern = zend_object_alloc(sizeof(php_date_obj), class_type);
1858
1859 zend_object_std_init(&intern->std, class_type);
1860 object_properties_init(&intern->std, class_type);
1861
1862 return &intern->std;
1863} /* }}} */
1864
1865static zend_object *date_object_clone_date(zend_object *this_ptr) /* {{{ */
1866{
1867 php_date_obj *old_obj = php_date_obj_from_obj(this_ptr);
1868 php_date_obj *new_obj = php_date_obj_from_obj(date_object_new_date(old_obj->std.ce));
1869
1870 zend_objects_clone_members(&new_obj->std, &old_obj->std);
1871 if (!old_obj->time) {
1872 return &new_obj->std;
1873 }
1874
1875 /* this should probably moved to a new `timelib_time *timelime_time_clone(timelib_time *)` */
1876 new_obj->time = timelib_time_ctor();
1877 *new_obj->time = *old_obj->time;
1878 if (old_obj->time->tz_abbr) {
1879 new_obj->time->tz_abbr = timelib_strdup(old_obj->time->tz_abbr);
1880 }
1881 if (old_obj->time->tz_info) {
1882 new_obj->time->tz_info = old_obj->time->tz_info;
1883 }
1884
1885 return &new_obj->std;
1886} /* }}} */
1887
1888static void date_clone_immutable(zval *object, zval *new_object) /* {{{ */
1889{
1890 ZVAL_OBJ(new_object, date_object_clone_date(Z_OBJ_P(object)));
1891} /* }}} */
1892
1893static int date_object_compare_date(zval *d1, zval *d2) /* {{{ */
1894{
1895 php_date_obj *o1;
1896 php_date_obj *o2;
1897
1899
1900 o1 = Z_PHPDATE_P(d1);
1901 o2 = Z_PHPDATE_P(d2);
1902
1903 if (!o1->time || !o2->time) {
1904 zend_throw_error(date_ce_date_object_error, "Trying to compare an incomplete DateTime or DateTimeImmutable object");
1905 return ZEND_UNCOMPARABLE;
1906 }
1907 if (!o1->time->sse_uptodate) {
1909 }
1910 if (!o2->time->sse_uptodate) {
1912 }
1913
1914 return timelib_time_compare(o1->time, o2->time);
1915} /* }}} */
1916
1917static HashTable *date_object_get_gc(zend_object *object, zval **table, int *n) /* {{{ */
1918{
1919 *table = NULL;
1920 *n = 0;
1921 return zend_std_get_properties(object);
1922} /* }}} */
1923
1924static HashTable *date_object_get_gc_timezone(zend_object *object, zval **table, int *n) /* {{{ */
1925{
1926 *table = NULL;
1927 *n = 0;
1928 return zend_std_get_properties(object);
1929} /* }}} */
1930
1931static void date_object_to_hash(php_date_obj *dateobj, HashTable *props)
1932{
1933 zval zv;
1934
1935 /* first we add the date and time in ISO format */
1936 ZVAL_STR(&zv, date_format("x-m-d H:i:s.u", sizeof("x-m-d H:i:s.u")-1, dateobj->time, 1));
1937 zend_hash_str_update(props, "date", sizeof("date")-1, &zv);
1938
1939 /* then we add the timezone name (or similar) */
1940 if (dateobj->time->is_localtime) {
1941 ZVAL_LONG(&zv, dateobj->time->zone_type);
1942 zend_hash_str_update(props, "timezone_type", sizeof("timezone_type")-1, &zv);
1943
1944 switch (dateobj->time->zone_type) {
1946 ZVAL_STRING(&zv, dateobj->time->tz_info->name);
1947 break;
1949 zend_string *tmpstr = zend_string_alloc(sizeof("UTC+05:00")-1, 0);
1950 int utc_offset = dateobj->time->z;
1951
1952 ZSTR_LEN(tmpstr) = snprintf(ZSTR_VAL(tmpstr), sizeof("+05:00"), "%c%02d:%02d",
1953 utc_offset < 0 ? '-' : '+',
1954 abs(utc_offset / 3600),
1955 abs(((utc_offset % 3600) / 60)));
1956
1957 ZVAL_NEW_STR(&zv, tmpstr);
1958 }
1959 break;
1961 ZVAL_STRING(&zv, dateobj->time->tz_abbr);
1962 break;
1963 }
1964 zend_hash_str_update(props, "timezone", sizeof("timezone")-1, &zv);
1965 }
1966}
1967
1968static HashTable *date_object_get_properties_for(zend_object *object, zend_prop_purpose purpose) /* {{{ */
1969{
1970 HashTable *props;
1972
1973 switch (purpose) {
1979 break;
1980 default:
1981 return zend_std_get_properties_for(object, purpose);
1982 }
1983
1984 dateobj = php_date_obj_from_obj(object);
1985 props = zend_array_dup(zend_std_get_properties(object));
1986 if (!dateobj->time) {
1987 return props;
1988 }
1989
1990 date_object_to_hash(dateobj, props);
1991
1992 return props;
1993} /* }}} */
1994
1995static zend_object *date_object_new_timezone(zend_class_entry *class_type) /* {{{ */
1996{
1997 php_timezone_obj *intern = zend_object_alloc(sizeof(php_timezone_obj), class_type);
1998
1999 zend_object_std_init(&intern->std, class_type);
2000 object_properties_init(&intern->std, class_type);
2001
2002 return &intern->std;
2003} /* }}} */
2004
2005static zend_object *date_object_clone_timezone(zend_object *this_ptr) /* {{{ */
2006{
2007 php_timezone_obj *old_obj = php_timezone_obj_from_obj(this_ptr);
2008 php_timezone_obj *new_obj = php_timezone_obj_from_obj(date_object_new_timezone(old_obj->std.ce));
2009
2010 zend_objects_clone_members(&new_obj->std, &old_obj->std);
2011 if (!old_obj->initialized) {
2012 return &new_obj->std;
2013 }
2014
2015 new_obj->type = old_obj->type;
2016 new_obj->initialized = 1;
2017 switch (new_obj->type) {
2019 new_obj->tzi.tz = old_obj->tzi.tz;
2020 break;
2022 new_obj->tzi.utc_offset = old_obj->tzi.utc_offset;
2023 break;
2025 new_obj->tzi.z.utc_offset = old_obj->tzi.z.utc_offset;
2026 new_obj->tzi.z.dst = old_obj->tzi.z.dst;
2027 new_obj->tzi.z.abbr = timelib_strdup(old_obj->tzi.z.abbr);
2028 break;
2029 }
2030
2031 return &new_obj->std;
2032} /* }}} */
2033
2034static int date_object_compare_timezone(zval *tz1, zval *tz2) /* {{{ */
2035{
2036 php_timezone_obj *o1, *o2;
2037
2039
2040 o1 = Z_PHPTIMEZONE_P(tz1);
2041 o2 = Z_PHPTIMEZONE_P(tz2);
2042
2043 if (!o1->initialized || !o2->initialized) {
2044 zend_throw_error(date_ce_date_object_error, "Trying to compare uninitialized DateTimeZone objects");
2045 return ZEND_UNCOMPARABLE;
2046 }
2047
2048 if (o1->type != o2->type) {
2049 zend_throw_error(date_ce_date_exception, "Cannot compare two different kinds of DateTimeZone objects");
2050 return ZEND_UNCOMPARABLE;
2051 }
2052
2053 switch (o1->type) {
2055 return o1->tzi.utc_offset == o2->tzi.utc_offset ? 0 : 1;
2057 return strcmp(o1->tzi.z.abbr, o2->tzi.z.abbr) ? 1 : 0;
2059 return strcmp(o1->tzi.tz->name, o2->tzi.tz->name) ? 1 : 0;
2061 }
2062} /* }}} */
2063
2064static void php_timezone_to_string(php_timezone_obj *tzobj, zval *zv)
2065{
2066 switch (tzobj->type) {
2068 ZVAL_STRING(zv, tzobj->tzi.tz->name);
2069 break;
2071 timelib_sll utc_offset = tzobj->tzi.utc_offset;
2072 int seconds = utc_offset % 60;
2073 size_t size;
2074 const char *format;
2075 if (seconds == 0) {
2076 size = sizeof("+05:00");
2077 format = "%c%02d:%02d";
2078 } else {
2079 size = sizeof("+05:00:01");
2080 format = "%c%02d:%02d:%02d";
2081 }
2082 zend_string *tmpstr = zend_string_alloc(size - 1, 0);
2083
2084 /* Note: if seconds == 0, the seconds argument will be excessive and therefore ignored. */
2085 ZSTR_LEN(tmpstr) = snprintf(ZSTR_VAL(tmpstr), size, format,
2086 utc_offset < 0 ? '-' : '+',
2087 abs((int)(utc_offset / 3600)),
2088 abs((int)(utc_offset % 3600) / 60),
2089 abs(seconds));
2090
2091 ZVAL_NEW_STR(zv, tmpstr);
2092 }
2093 break;
2095 ZVAL_STRING(zv, tzobj->tzi.z.abbr);
2096 break;
2097 }
2098}
2099
2100static void date_timezone_object_to_hash(php_timezone_obj *tzobj, HashTable *props)
2101{
2102 zval zv;
2103
2104 ZVAL_LONG(&zv, tzobj->type);
2105 zend_hash_str_update(props, "timezone_type", strlen("timezone_type"), &zv);
2106
2107 php_timezone_to_string(tzobj, &zv);
2108 zend_hash_str_update(props, "timezone", strlen("timezone"), &zv);
2109}
2110
2111static HashTable *date_object_get_properties_for_timezone(zend_object *object, zend_prop_purpose purpose) /* {{{ */
2112{
2113 HashTable *props;
2114 php_timezone_obj *tzobj;
2115
2116 switch (purpose) {
2122 break;
2123 default:
2124 return zend_std_get_properties_for(object, purpose);
2125 }
2126
2127 tzobj = php_timezone_obj_from_obj(object);
2128 props = zend_array_dup(zend_std_get_properties(object));
2129 if (!tzobj->initialized) {
2130 return props;
2131 }
2132
2133 date_timezone_object_to_hash(tzobj, props);
2134
2135 return props;
2136} /* }}} */
2137
2138static HashTable *date_object_get_debug_info_timezone(zend_object *object, int *is_temp) /* {{{ */
2139{
2140 HashTable *ht, *props;
2141 zval zv;
2142 php_timezone_obj *tzobj;
2143
2144 tzobj = php_timezone_obj_from_obj(object);
2145 props = zend_std_get_properties(object);
2146
2147 *is_temp = 1;
2148 ht = zend_array_dup(props);
2149
2150 ZVAL_LONG(&zv, tzobj->type);
2151 zend_hash_str_update(ht, "timezone_type", sizeof("timezone_type")-1, &zv);
2152
2153 php_timezone_to_string(tzobj, &zv);
2154 zend_hash_str_update(ht, "timezone", sizeof("timezone")-1, &zv);
2155
2156 return ht;
2157} /* }}} */
2158
2159static zend_object *date_object_new_interval(zend_class_entry *class_type) /* {{{ */
2160{
2161 php_interval_obj *intern = zend_object_alloc(sizeof(php_interval_obj), class_type);
2162
2163 zend_object_std_init(&intern->std, class_type);
2164 object_properties_init(&intern->std, class_type);
2165
2166 return &intern->std;
2167} /* }}} */
2168
2169static zend_object *date_object_clone_interval(zend_object *this_ptr) /* {{{ */
2170{
2171 php_interval_obj *old_obj = php_interval_obj_from_obj(this_ptr);
2172 php_interval_obj *new_obj = php_interval_obj_from_obj(date_object_new_interval(old_obj->std.ce));
2173
2174 zend_objects_clone_members(&new_obj->std, &old_obj->std);
2175 new_obj->civil_or_wall = old_obj->civil_or_wall;
2176 new_obj->from_string = old_obj->from_string;
2177 if (old_obj->date_string) {
2178 new_obj->date_string = zend_string_copy(old_obj->date_string);
2179 }
2180 new_obj->initialized = old_obj->initialized;
2181 if (old_obj->diff) {
2182 new_obj->diff = timelib_rel_time_clone(old_obj->diff);
2183 }
2184
2185 return &new_obj->std;
2186} /* }}} */
2187
2188static HashTable *date_object_get_gc_interval(zend_object *object, zval **table, int *n) /* {{{ */
2189{
2190
2191 *table = NULL;
2192 *n = 0;
2193 return zend_std_get_properties(object);
2194} /* }}} */
2195
2196static void date_interval_object_to_hash(php_interval_obj *intervalobj, HashTable *props)
2197{
2198 zval zv;
2199
2200 /* Records whether this is a special relative interval that needs to be recreated from a string */
2201 if (intervalobj->from_string) {
2202 ZVAL_BOOL(&zv, (bool)intervalobj->from_string);
2203 zend_hash_str_update(props, "from_string", strlen("from_string"), &zv);
2204 ZVAL_STR_COPY(&zv, intervalobj->date_string);
2205 zend_hash_str_update(props, "date_string", strlen("date_string"), &zv);
2206 return;
2207 }
2208
2209#define PHP_DATE_INTERVAL_ADD_PROPERTY(n,f) \
2210 ZVAL_LONG(&zv, (zend_long)intervalobj->diff->f); \
2211 zend_hash_str_update(props, n, sizeof(n)-1, &zv);
2212
2219 ZVAL_DOUBLE(&zv, (double)intervalobj->diff->us / 1000000.0);
2220 zend_hash_str_update(props, "f", sizeof("f") - 1, &zv);
2221 PHP_DATE_INTERVAL_ADD_PROPERTY("invert", invert);
2222 if (intervalobj->diff->days != TIMELIB_UNSET) {
2223 PHP_DATE_INTERVAL_ADD_PROPERTY("days", days);
2224 } else {
2225 ZVAL_FALSE(&zv);
2226 zend_hash_str_update(props, "days", sizeof("days")-1, &zv);
2227 }
2228 ZVAL_BOOL(&zv, (bool)intervalobj->from_string);
2229 zend_hash_str_update(props, "from_string", strlen("from_string"), &zv);
2230
2231#undef PHP_DATE_INTERVAL_ADD_PROPERTY
2232}
2233
2234static HashTable *date_object_get_properties_interval(zend_object *object) /* {{{ */
2235{
2236 HashTable *props;
2237 php_interval_obj *intervalobj;
2238
2239 intervalobj = php_interval_obj_from_obj(object);
2240 props = zend_std_get_properties(object);
2241 if (!intervalobj->initialized) {
2242 return props;
2243 }
2244
2245 date_interval_object_to_hash(intervalobj, props);
2246
2247 return props;
2248} /* }}} */
2249
2250static zend_object *date_object_new_period(zend_class_entry *class_type) /* {{{ */
2251{
2252 php_period_obj *intern = zend_object_alloc(sizeof(php_period_obj), class_type);
2253
2254 zend_object_std_init(&intern->std, class_type);
2255 object_properties_init(&intern->std, class_type);
2256
2257 return &intern->std;
2258} /* }}} */
2259
2260static zend_object *date_object_clone_period(zend_object *this_ptr) /* {{{ */
2261{
2262 php_period_obj *old_obj = php_period_obj_from_obj(this_ptr);
2263 php_period_obj *new_obj = php_period_obj_from_obj(date_object_new_period(old_obj->std.ce));
2264
2265 zend_objects_clone_members(&new_obj->std, &old_obj->std);
2266 new_obj->initialized = old_obj->initialized;
2267 new_obj->recurrences = old_obj->recurrences;
2268 new_obj->include_start_date = old_obj->include_start_date;
2269 new_obj->include_end_date = old_obj->include_end_date;
2270 new_obj->start_ce = old_obj->start_ce;
2271
2272 if (old_obj->start) {
2273 new_obj->start = timelib_time_clone(old_obj->start);
2274 }
2275 if (old_obj->current) {
2276 new_obj->current = timelib_time_clone(old_obj->current);
2277 }
2278 if (old_obj->end) {
2279 new_obj->end = timelib_time_clone(old_obj->end);
2280 }
2281 if (old_obj->interval) {
2282 new_obj->interval = timelib_rel_time_clone(old_obj->interval);
2283 }
2284 return &new_obj->std;
2285} /* }}} */
2286
2287static void date_object_free_storage_date(zend_object *object) /* {{{ */
2288{
2289 php_date_obj *intern = php_date_obj_from_obj(object);
2290
2291 if (intern->time) {
2292 timelib_time_dtor(intern->time);
2293 }
2294
2295 zend_object_std_dtor(&intern->std);
2296} /* }}} */
2297
2298static void date_object_free_storage_timezone(zend_object *object) /* {{{ */
2299{
2300 php_timezone_obj *intern = php_timezone_obj_from_obj(object);
2301
2302 if (intern->type == TIMELIB_ZONETYPE_ABBR) {
2303 timelib_free(intern->tzi.z.abbr);
2304 }
2305 zend_object_std_dtor(&intern->std);
2306} /* }}} */
2307
2308static void date_object_free_storage_interval(zend_object *object) /* {{{ */
2309{
2310 php_interval_obj *intern = php_interval_obj_from_obj(object);
2311
2312 if (intern->date_string) {
2313 zend_string_release(intern->date_string);
2314 intern->date_string = NULL;
2315 }
2316 timelib_rel_time_dtor(intern->diff);
2317 zend_object_std_dtor(&intern->std);
2318} /* }}} */
2319
2320static void date_object_free_storage_period(zend_object *object) /* {{{ */
2321{
2322 php_period_obj *intern = php_period_obj_from_obj(object);
2323
2324 if (intern->start) {
2325 timelib_time_dtor(intern->start);
2326 }
2327
2328 if (intern->current) {
2329 timelib_time_dtor(intern->current);
2330 }
2331
2332 if (intern->end) {
2333 timelib_time_dtor(intern->end);
2334 }
2335
2337 zend_object_std_dtor(&intern->std);
2338} /* }}} */
2339
2340static void add_common_properties(HashTable *myht, zend_object *zobj)
2341{
2342 HashTable *common;
2344 zval *prop;
2345
2346 common = zend_std_get_properties(zobj);
2347
2349 if (zend_hash_add(myht, name, prop) != NULL) {
2350 Z_TRY_ADDREF_P(prop);
2351 }
2353}
2354
2355/* Advanced Interface */
2357{
2358 object_init_ex(object, pce);
2359 return object;
2360} /* }}} */
2361
2362/* Helper function used to store the latest found warnings and errors while
2363 * parsing, from either strtotime or parse_from_format. */
2364static void update_errors_warnings(timelib_error_container **last_errors) /* {{{ */
2365{
2366 if (DATEG(last_errors)) {
2369 }
2370
2371 if (last_errors == NULL || (*last_errors) == NULL) {
2372 return;
2373 }
2374
2375 if ((*last_errors)->warning_count || (*last_errors)->error_count) {
2377 return;
2378 }
2379
2381 *last_errors = NULL;
2382} /* }}} */
2383
2384static void php_date_set_time_fraction(timelib_time *time, int microsecond)
2385{
2386 time->us = microsecond;
2387}
2388
2389static void php_date_get_current_time_with_fraction(time_t *sec, suseconds_t *usec)
2390{
2391#ifdef HAVE_GETTIMEOFDAY
2392 struct timeval tp = {0}; /* For setting microsecond */
2393
2394 gettimeofday(&tp, NULL);
2395 *sec = tp.tv_sec;
2396 *usec = tp.tv_usec;
2397#else
2398 *sec = time(NULL);
2399 *usec = 0;
2400#endif
2401}
2402
2403PHPAPI bool php_date_initialize(php_date_obj *dateobj, const char *time_str, size_t time_str_len, const char *format, zval *timezone_object, int flags) /* {{{ */
2404{
2406 timelib_tzinfo *tzi = NULL;
2408 int type = TIMELIB_ZONETYPE_ID, new_dst = 0;
2409 char *new_abbr = NULL;
2410 timelib_sll new_offset = 0;
2411 time_t sec;
2412 suseconds_t usec;
2413 int options = 0;
2414
2415 if (dateobj->time) {
2417 }
2418 if (format) {
2419 if (time_str_len == 0) {
2420 time_str = "";
2421 }
2422 dateobj->time = timelib_parse_from_format(format, time_str, time_str_len, &err, DATE_TIMEZONEDB, php_date_parse_tzfile_wrapper);
2423 } else {
2424 if (time_str_len == 0) {
2425 time_str = "now";
2426 time_str_len = sizeof("now") - 1;
2427 }
2428 dateobj->time = timelib_strtotime(time_str, time_str_len, &err, DATE_TIMEZONEDB, php_date_parse_tzfile_wrapper);
2429 }
2430
2431 /* update last errors and warnings */
2432 update_errors_warnings(&err);
2433
2434 /* If called from a constructor throw an exception */
2435 if ((flags & PHP_DATE_INIT_CTOR) && err && err->error_count) {
2436 /* spit out the first library error message, at least */
2437 zend_throw_exception_ex(date_ce_date_malformed_string_exception, 0, "Failed to parse time string (%s) at position %d (%c): %s", time_str,
2438 err->error_messages[0].position, err->error_messages[0].character ? err->error_messages[0].character : ' ', err->error_messages[0].message);
2439 }
2440 if (err && err->error_count) {
2442 dateobj->time = 0;
2443 return 0;
2444 }
2445
2446 if (timezone_object) {
2447 php_timezone_obj *tzobj;
2448
2449 tzobj = Z_PHPTIMEZONE_P(timezone_object);
2450 switch (tzobj->type) {
2452 tzi = tzobj->tzi.tz;
2453 break;
2455 new_offset = tzobj->tzi.utc_offset;
2456 break;
2458 new_offset = tzobj->tzi.z.utc_offset;
2459 new_dst = tzobj->tzi.z.dst;
2460 new_abbr = timelib_strdup(tzobj->tzi.z.abbr);
2461 break;
2462 default:
2463 zend_throw_error(NULL, "The DateTimeZone object has not been correctly initialized by its constructor");
2464 return 0;
2465 }
2466 type = tzobj->type;
2467 } else if (dateobj->time->tz_info) {
2468 tzi = dateobj->time->tz_info;
2469 } else {
2470 tzi = get_timezone_info();
2471 if (!tzi) {
2472 return 0;
2473 }
2474 }
2475
2477 now->zone_type = type;
2478 switch (type) {
2480 now->tz_info = tzi;
2481 break;
2483 now->z = new_offset;
2484 break;
2486 now->z = new_offset;
2487 now->dst = new_dst;
2488 now->tz_abbr = new_abbr;
2489 break;
2490 }
2491 php_date_get_current_time_with_fraction(&sec, &usec);
2493 php_date_set_time_fraction(now, usec);
2494
2495 if (!format
2496 && time_str_len == sizeof("now") - 1
2497 && memcmp(time_str, "now", sizeof("now") - 1) == 0) {
2499 dateobj->time = now;
2500 return 1;
2501 }
2502
2506 }
2508
2509 timelib_update_ts(dateobj->time, tzi);
2511
2512 dateobj->time->have_relative = 0;
2513
2515
2516 return 1;
2517} /* }}} */
2518
2520{
2521 dateobj->time = timelib_time_ctor();
2522 dateobj->time->zone_type = TIMELIB_ZONETYPE_OFFSET;
2523
2526 php_date_set_time_fraction(dateobj->time, usec);
2527} /* }}} */
2528
2530{
2531 double sec_dval = trunc(ts);
2532 zend_long sec;
2533 int usec;
2534
2535 if (UNEXPECTED(isnan(sec_dval) || !PHP_DATE_DOUBLE_FITS_LONG(sec_dval))) {
2537 date_ce_date_range_error,
2538 1,
2539 "must be a finite number between " TIMELIB_LONG_FMT " and " TIMELIB_LONG_FMT ".999999, %g given",
2542 ts
2543 );
2544 return false;
2545 }
2546
2547 sec = (zend_long)sec_dval;
2548 usec = (int) round(fmod(ts, 1) * 1000000);
2549
2550 if (UNEXPECTED(abs(usec) == 1000000)) {
2551 sec += usec > 0 ? 1 : -1;
2552 usec = 0;
2553 }
2554
2555 if (UNEXPECTED(usec < 0)) {
2556 if (UNEXPECTED(sec == TIMELIB_LONG_MIN)) {
2558 date_ce_date_range_error,
2559 1,
2560 "must be a finite number between " TIMELIB_LONG_FMT " and " TIMELIB_LONG_FMT ".999999, %g given",
2563 ts
2564 );
2565 return false;
2566 }
2567
2568 sec = sec - 1;
2569 usec = 1000000 + usec;
2570 }
2571
2573
2574 return true;
2575} /* }}} */
2576
2577/* {{{ Returns new DateTime object */
2579{
2580 zval *timezone_object = NULL;
2581 char *time_str = NULL;
2582 size_t time_str_len = 0;
2583
2586 Z_PARAM_STRING(time_str, time_str_len)
2587 Z_PARAM_OBJECT_OF_CLASS_OR_NULL(timezone_object, date_ce_timezone)
2589
2590 php_date_instantiate(date_ce_date, return_value);
2591 if (!php_date_initialize(Z_PHPDATE_P(return_value), time_str, time_str_len, NULL, timezone_object, 0)) {
2594 }
2595}
2596/* }}} */
2597
2598/* {{{ Returns new DateTimeImmutable object */
2600{
2601 zval *timezone_object = NULL;
2602 char *time_str = NULL;
2603 size_t time_str_len = 0;
2604
2607 Z_PARAM_STRING(time_str, time_str_len)
2608 Z_PARAM_OBJECT_OF_CLASS_OR_NULL(timezone_object, date_ce_timezone)
2610
2611 php_date_instantiate(date_ce_immutable, return_value);
2612 if (!php_date_initialize(Z_PHPDATE_P(return_value), time_str, time_str_len, NULL, timezone_object, 0)) {
2615 }
2616}
2617/* }}} */
2618
2619/* {{{ Returns new DateTime object formatted according to the specified format */
2621{
2622 zval *timezone_object = NULL;
2623 char *time_str = NULL, *format_str = NULL;
2624 size_t time_str_len = 0, format_str_len = 0;
2625
2627 Z_PARAM_STRING(format_str, format_str_len)
2628 Z_PARAM_PATH(time_str, time_str_len)
2630 Z_PARAM_OBJECT_OF_CLASS_OR_NULL(timezone_object, date_ce_timezone)
2632
2633 php_date_instantiate(execute_data->This.value.ce ? execute_data->This.value.ce : date_ce_date, return_value);
2634 if (!php_date_initialize(Z_PHPDATE_P(return_value), time_str, time_str_len, format_str, timezone_object, PHP_DATE_INIT_FORMAT)) {
2637 }
2638}
2639/* }}} */
2640
2641/* {{{ Returns new DateTimeImmutable object formatted according to the specified format */
2643{
2644 zval *timezone_object = NULL;
2645 char *time_str = NULL, *format_str = NULL;
2646 size_t time_str_len = 0, format_str_len = 0;
2647
2649 Z_PARAM_STRING(format_str, format_str_len)
2650 Z_PARAM_PATH(time_str, time_str_len)
2652 Z_PARAM_OBJECT_OF_CLASS_OR_NULL(timezone_object, date_ce_timezone)
2654
2655 php_date_instantiate(execute_data->This.value.ce ? execute_data->This.value.ce : date_ce_immutable, return_value);
2656 if (!php_date_initialize(Z_PHPDATE_P(return_value), time_str, time_str_len, format_str, timezone_object, PHP_DATE_INIT_FORMAT)) {
2659 }
2660}
2661/* }}} */
2662
2663/* {{{ Creates new DateTime object */
2665{
2666 zval *timezone_object = NULL;
2667 char *time_str = NULL;
2668 size_t time_str_len = 0;
2669
2672 Z_PARAM_STRING(time_str, time_str_len)
2673 Z_PARAM_OBJECT_OF_CLASS_OR_NULL(timezone_object, date_ce_timezone)
2675
2676 php_date_initialize(Z_PHPDATE_P(ZEND_THIS), time_str, time_str_len, NULL, timezone_object, PHP_DATE_INIT_CTOR);
2677}
2678/* }}} */
2679
2680/* {{{ Creates new DateTimeImmutable object */
2682{
2683 zval *timezone_object = NULL;
2684 char *time_str = NULL;
2685 size_t time_str_len = 0;
2686
2689 Z_PARAM_STRING(time_str, time_str_len)
2690 Z_PARAM_OBJECT_OF_CLASS_OR_NULL(timezone_object, date_ce_timezone)
2692
2693 php_date_initialize(Z_PHPDATE_P(ZEND_THIS), time_str, time_str_len, NULL, timezone_object, PHP_DATE_INIT_CTOR);
2694}
2695/* }}} */
2696
2697/* {{{ Creates new DateTime object from an existing immutable DateTimeImmutable object. */
2698PHP_METHOD(DateTime, createFromImmutable)
2699{
2700 zval *datetimeimmutable_object = NULL;
2701 php_date_obj *new_obj = NULL;
2702 php_date_obj *old_obj = NULL;
2703
2705 Z_PARAM_OBJECT_OF_CLASS(datetimeimmutable_object, date_ce_immutable)
2707
2708 old_obj = Z_PHPDATE_P(datetimeimmutable_object);
2709 DATE_CHECK_INITIALIZED(old_obj->time, Z_OBJCE_P(datetimeimmutable_object));
2710
2711 php_date_instantiate(execute_data->This.value.ce ? execute_data->This.value.ce : date_ce_date, return_value);
2712 new_obj = Z_PHPDATE_P(return_value);
2713
2714 new_obj->time = timelib_time_clone(old_obj->time);
2715}
2716/* }}} */
2717
2718/* {{{ Creates new DateTime object from an existing DateTimeInterface object. */
2719PHP_METHOD(DateTime, createFromInterface)
2720{
2721 zval *datetimeinterface_object = NULL;
2722 php_date_obj *new_obj = NULL;
2723 php_date_obj *old_obj = NULL;
2724
2726 Z_PARAM_OBJECT_OF_CLASS(datetimeinterface_object, date_ce_interface)
2728
2729 old_obj = Z_PHPDATE_P(datetimeinterface_object);
2730 DATE_CHECK_INITIALIZED(old_obj->time, Z_OBJCE_P(datetimeinterface_object));
2731
2732 php_date_instantiate(execute_data->This.value.ce ? execute_data->This.value.ce : date_ce_date, return_value);
2733 new_obj = Z_PHPDATE_P(return_value);
2734
2735 new_obj->time = timelib_time_clone(old_obj->time);
2736}
2737/* }}} */
2738
2739/* {{{ Creates new DateTime object from given unix timetamp */
2740PHP_METHOD(DateTime, createFromTimestamp)
2741{
2742 zval *value;
2743 zval new_object;
2744 php_date_obj *new_dateobj;
2745
2749
2750 php_date_instantiate(execute_data->This.value.ce ? execute_data->This.value.ce : date_ce_date, &new_object);
2751 new_dateobj = Z_PHPDATE_P(&new_object);
2752
2753 switch (Z_TYPE_P(value)) {
2754 case IS_LONG:
2756 break;
2757
2758 case IS_DOUBLE:
2760 zval_ptr_dtor(&new_object);
2761 RETURN_THROWS();
2762 }
2763 break;
2764
2766 }
2767
2768 RETURN_OBJ(Z_OBJ(new_object));
2769}
2770/* }}} */
2771
2772/* {{{ Creates new DateTimeImmutable object from an existing mutable DateTime object. */
2774{
2775 zval *datetime_object = NULL;
2776 php_date_obj *new_obj = NULL;
2777 php_date_obj *old_obj = NULL;
2778
2780 Z_PARAM_OBJECT_OF_CLASS(datetime_object, date_ce_date)
2782
2783 old_obj = Z_PHPDATE_P(datetime_object);
2784 DATE_CHECK_INITIALIZED(old_obj->time, Z_OBJCE_P(datetime_object));
2785
2786 php_date_instantiate(execute_data->This.value.ce ? execute_data->This.value.ce : date_ce_immutable, return_value);
2787 new_obj = Z_PHPDATE_P(return_value);
2788
2789 new_obj->time = timelib_time_clone(old_obj->time);
2790}
2791/* }}} */
2792
2793/* {{{ Creates new DateTimeImmutable object from an existing DateTimeInterface object. */
2794PHP_METHOD(DateTimeImmutable, createFromInterface)
2795{
2796 zval *datetimeinterface_object = NULL;
2797 php_date_obj *new_obj = NULL;
2798 php_date_obj *old_obj = NULL;
2799
2801 Z_PARAM_OBJECT_OF_CLASS(datetimeinterface_object, date_ce_interface)
2803
2804 old_obj = Z_PHPDATE_P(datetimeinterface_object);
2805 DATE_CHECK_INITIALIZED(old_obj->time, Z_OBJCE_P(datetimeinterface_object));
2806
2807 php_date_instantiate(execute_data->This.value.ce ? execute_data->This.value.ce : date_ce_immutable, return_value);
2808 new_obj = Z_PHPDATE_P(return_value);
2809
2810 new_obj->time = timelib_time_clone(old_obj->time);
2811}
2812/* }}} */
2813
2814/* {{{ Creates new DateTimeImmutable object from given unix timestamp */
2815PHP_METHOD(DateTimeImmutable, createFromTimestamp)
2816{
2817 zval *value;
2818 zval new_object;
2819 php_date_obj *new_dateobj;
2820
2824
2825 php_date_instantiate(execute_data->This.value.ce ? execute_data->This.value.ce : date_ce_immutable, &new_object);
2826 new_dateobj = Z_PHPDATE_P(&new_object);
2827
2828 switch (Z_TYPE_P(value)) {
2829 case IS_LONG:
2831 break;
2832
2833 case IS_DOUBLE:
2835 zval_ptr_dtor(&new_object);
2836 RETURN_THROWS();
2837 }
2838 break;
2839
2841 }
2842
2843 RETURN_OBJ(Z_OBJ(new_object));
2844}
2845/* }}} */
2846
2847static bool php_date_initialize_from_hash(php_date_obj **dateobj, HashTable *myht)
2848{
2849 zval *z_date;
2850 zval *z_timezone_type;
2851 zval *z_timezone;
2852 zval tmp_obj;
2853 timelib_tzinfo *tzi;
2854
2855 z_date = zend_hash_str_find(myht, "date", sizeof("date")-1);
2856 if (!z_date || Z_TYPE_P(z_date) != IS_STRING) {
2857 return false;
2858 }
2859
2860 z_timezone_type = zend_hash_str_find(myht, "timezone_type", sizeof("timezone_type")-1);
2861 if (!z_timezone_type || Z_TYPE_P(z_timezone_type) != IS_LONG) {
2862 return false;
2863 }
2864
2865 z_timezone = zend_hash_str_find(myht, "timezone", sizeof("timezone")-1);
2866 if (!z_timezone || Z_TYPE_P(z_timezone) != IS_STRING) {
2867 return false;
2868 }
2869
2870 switch (Z_LVAL_P(z_timezone_type)) {
2872 case TIMELIB_ZONETYPE_ABBR: {
2874 Z_STRVAL_P(z_date), Z_STRLEN_P(z_date), " ", 1,
2875 Z_STRVAL_P(z_timezone), Z_STRLEN_P(z_timezone));
2876 bool ret = php_date_initialize(*dateobj, ZSTR_VAL(tmp), ZSTR_LEN(tmp), NULL, NULL, 0);
2877 zend_string_release(tmp);
2878 return ret;
2879 }
2880
2881 case TIMELIB_ZONETYPE_ID: {
2882 bool ret;
2883 php_timezone_obj *tzobj;
2884
2885 tzi = php_date_parse_tzfile(Z_STRVAL_P(z_timezone), DATE_TIMEZONEDB);
2886
2887 if (tzi == NULL) {
2888 return false;
2889 }
2890
2891 tzobj = Z_PHPTIMEZONE_P(php_date_instantiate(date_ce_timezone, &tmp_obj));
2892 tzobj->type = TIMELIB_ZONETYPE_ID;
2893 tzobj->tzi.tz = tzi;
2894 tzobj->initialized = 1;
2895
2896 ret = php_date_initialize(*dateobj, Z_STRVAL_P(z_date), Z_STRLEN_P(z_date), NULL, &tmp_obj, 0);
2897 zval_ptr_dtor(&tmp_obj);
2898 return ret;
2899 }
2900 }
2901 return false;
2902} /* }}} */
2903
2904/* {{{ */
2906{
2908 zval *array;
2909 HashTable *myht;
2910
2912 Z_PARAM_ARRAY(array)
2914
2915 myht = Z_ARRVAL_P(array);
2916
2917 php_date_instantiate(date_ce_date, return_value);
2919 if (!php_date_initialize_from_hash(&dateobj, myht)) {
2920 zend_throw_error(NULL, "Invalid serialization data for DateTime object");
2921 RETURN_THROWS();
2922 }
2923}
2924/* }}} */
2925
2926/* {{{ */
2928{
2930 zval *array;
2931 HashTable *myht;
2932
2934 Z_PARAM_ARRAY(array)
2936
2937 myht = Z_ARRVAL_P(array);
2938
2939 php_date_instantiate(date_ce_immutable, return_value);
2941 if (!php_date_initialize_from_hash(&dateobj, myht)) {
2942 zend_throw_error(NULL, "Invalid serialization data for DateTimeImmutable object");
2943 RETURN_THROWS();
2944 }
2945}
2946/* }}} */
2947
2948/* {{{ */
2950{
2951 zval *object = ZEND_THIS;
2953 HashTable *myht;
2954
2956
2957 dateobj = Z_PHPDATE_P(object);
2959
2961 myht = Z_ARRVAL_P(return_value);
2962 date_object_to_hash(dateobj, myht);
2963
2964 add_common_properties(myht, &dateobj->std);
2965}
2966/* }}} */
2967
2968/* {{{ */
2970{
2971 zval *object = ZEND_THIS;
2973 HashTable *myht;
2974
2976
2977 dateobj = Z_PHPDATE_P(object);
2979
2981 myht = Z_ARRVAL_P(return_value);
2982 date_object_to_hash(dateobj, myht);
2983
2984 add_common_properties(myht, &dateobj->std);
2985}
2986/* }}} */
2987
2988static bool date_time_is_internal_property(zend_string *name)
2989{
2990 if (
2992 zend_string_equals_literal(name, "timezone_type") ||
2993 zend_string_equals_literal(name, "timezone")
2994 ) {
2995 return 1;
2996 }
2997 return 0;
2998}
2999
3000static void restore_custom_datetime_properties(zval *object, HashTable *myht)
3001{
3002 zend_string *prop_name;
3003 zval *prop_val;
3004
3005 ZEND_HASH_FOREACH_STR_KEY_VAL(myht, prop_name, prop_val) {
3006 if (!prop_name || (Z_TYPE_P(prop_val) == IS_REFERENCE) || date_time_is_internal_property(prop_name)) {
3007 continue;
3008 }
3009 update_property(Z_OBJ_P(object), prop_name, prop_val);
3011}
3012
3013/* {{{ */
3014PHP_METHOD(DateTime, __unserialize)
3015{
3016 zval *object = ZEND_THIS;
3018 zval *array;
3019 HashTable *myht;
3020
3022 Z_PARAM_ARRAY(array)
3024
3025 dateobj = Z_PHPDATE_P(object);
3026 myht = Z_ARRVAL_P(array);
3027
3028 if (!php_date_initialize_from_hash(&dateobj, myht)) {
3029 zend_throw_error(NULL, "Invalid serialization data for DateTime object");
3030 RETURN_THROWS();
3031 }
3032
3033 restore_custom_datetime_properties(object, myht);
3034}
3035/* }}} */
3036
3037/* {{{ */
3039{
3040 zval *object = ZEND_THIS;
3042 zval *array;
3043 HashTable *myht;
3044
3046 Z_PARAM_ARRAY(array)
3048
3049 dateobj = Z_PHPDATE_P(object);
3050 myht = Z_ARRVAL_P(array);
3051
3052 if (!php_date_initialize_from_hash(&dateobj, myht)) {
3053 zend_throw_error(NULL, "Invalid serialization data for DateTimeImmutable object");
3054 RETURN_THROWS();
3055 }
3056
3057 restore_custom_datetime_properties(object, myht);
3058}
3059/* }}} */
3060
3061/* {{{ */
3063{
3064 zval *object = ZEND_THIS;
3066 HashTable *myht;
3067
3069
3070 dateobj = Z_PHPDATE_P(object);
3071
3072 myht = Z_OBJPROP_P(object);
3073
3074 if (!php_date_initialize_from_hash(&dateobj, myht)) {
3075 zend_throw_error(NULL, "Invalid serialization data for DateTime object");
3076 RETURN_THROWS();
3077 }
3078}
3079/* }}} */
3080
3081/* {{{ */
3083{
3084 zval *object = ZEND_THIS;
3086 HashTable *myht;
3087
3089
3090 dateobj = Z_PHPDATE_P(object);
3091
3092 myht = Z_OBJPROP_P(object);
3093
3094 if (!php_date_initialize_from_hash(&dateobj, myht)) {
3095 zend_throw_error(NULL, "Invalid serialization data for DateTimeImmutable object");
3096 RETURN_THROWS();
3097 }
3098}
3099/* }}} */
3100
3101/* Helper function used to add an associative array of warnings and errors to a zval */
3102static void zval_from_error_container(zval *z, timelib_error_container *error) /* {{{ */
3103{
3104 int i;
3105 zval element;
3106
3107 add_assoc_long(z, "warning_count", error->warning_count);
3108 array_init(&element);
3109 for (i = 0; i < error->warning_count; i++) {
3110 add_index_string(&element, error->warning_messages[i].position, error->warning_messages[i].message);
3111 }
3112 add_assoc_zval(z, "warnings", &element);
3113
3114 add_assoc_long(z, "error_count", error->error_count);
3115 array_init(&element);
3116 for (i = 0; i < error->error_count; i++) {
3117 add_index_string(&element, error->error_messages[i].position, error->error_messages[i].message);
3118 }
3119 add_assoc_zval(z, "errors", &element);
3120} /* }}} */
3121
3122/* {{{ Returns the warnings and errors found while parsing a date/time string. */
3124{
3126
3127 if (DATEG(last_errors)) {
3129 zval_from_error_container(return_value, DATEG(last_errors));
3130 } else {
3132 }
3133}
3134/* }}} */
3135
3136static void php_date_do_return_parsed_time(INTERNAL_FUNCTION_PARAMETERS, timelib_time *parsed_time, timelib_error_container *error) /* {{{ */
3137{
3138 zval element;
3139
3141#define PHP_DATE_PARSE_DATE_SET_TIME_ELEMENT(name, elem) \
3142 if (parsed_time->elem == TIMELIB_UNSET) { \
3143 add_assoc_bool(return_value, #name, 0); \
3144 } else { \
3145 add_assoc_long(return_value, #name, parsed_time->elem); \
3146 }
3153
3154 if (parsed_time->us == TIMELIB_UNSET) {
3155 add_assoc_bool(return_value, "fraction", 0);
3156 } else {
3157 add_assoc_double(return_value, "fraction", (double)parsed_time->us / 1000000.0);
3158 }
3159
3160 zval_from_error_container(return_value, error);
3161
3163
3164 add_assoc_bool(return_value, "is_localtime", parsed_time->is_localtime);
3165
3166 if (parsed_time->is_localtime) {
3167 PHP_DATE_PARSE_DATE_SET_TIME_ELEMENT(zone_type, zone_type);
3168 switch (parsed_time->zone_type) {
3171 add_assoc_bool(return_value, "is_dst", parsed_time->dst);
3172 break;
3174 if (parsed_time->tz_abbr) {
3175 add_assoc_string(return_value, "tz_abbr", parsed_time->tz_abbr);
3176 }
3177 if (parsed_time->tz_info) {
3178 add_assoc_string(return_value, "tz_id", parsed_time->tz_info->name);
3179 }
3180 break;
3183 add_assoc_bool(return_value, "is_dst", parsed_time->dst);
3184 add_assoc_string(return_value, "tz_abbr", parsed_time->tz_abbr);
3185 break;
3186 }
3187 }
3188 if (parsed_time->have_relative) {
3189 array_init(&element);
3190 add_assoc_long(&element, "year", parsed_time->relative.y);
3191 add_assoc_long(&element, "month", parsed_time->relative.m);
3192 add_assoc_long(&element, "day", parsed_time->relative.d);
3193 add_assoc_long(&element, "hour", parsed_time->relative.h);
3194 add_assoc_long(&element, "minute", parsed_time->relative.i);
3195 add_assoc_long(&element, "second", parsed_time->relative.s);
3196 if (parsed_time->relative.have_weekday_relative) {
3197 add_assoc_long(&element, "weekday", parsed_time->relative.weekday);
3198 }
3199 if (parsed_time->relative.have_special_relative && (parsed_time->relative.special.type == TIMELIB_SPECIAL_WEEKDAY)) {
3200 add_assoc_long(&element, "weekdays", parsed_time->relative.special.amount);
3201 }
3202 if (parsed_time->relative.first_last_day_of) {
3203 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);
3204 }
3205 add_assoc_zval(return_value, "relative", &element);
3206 }
3207 timelib_time_dtor(parsed_time);
3208} /* }}} */
3209
3210/* {{{ Returns associative array with detailed info about given date */
3212{
3215 timelib_time *parsed_time;
3216
3220
3221 parsed_time = timelib_strtotime(ZSTR_VAL(date), ZSTR_LEN(date), &error, DATE_TIMEZONEDB, php_date_parse_tzfile_wrapper);
3222 php_date_do_return_parsed_time(INTERNAL_FUNCTION_PARAM_PASSTHRU, parsed_time, error);
3223}
3224/* }}} */
3225
3226/* {{{ Returns associative array with detailed info about given date */
3228{
3229 zend_string *date, *format;
3231 timelib_time *parsed_time;
3232
3234 Z_PARAM_STR(format)
3237
3238 parsed_time = timelib_parse_from_format(ZSTR_VAL(format), ZSTR_VAL(date), ZSTR_LEN(date), &error, DATE_TIMEZONEDB, php_date_parse_tzfile_wrapper);
3239 php_date_do_return_parsed_time(INTERNAL_FUNCTION_PARAM_PASSTHRU, parsed_time, error);
3240}
3241/* }}} */
3242
3243/* {{{ Returns date formatted according to given format */
3244PHP_FUNCTION(date_format)
3245{
3246 zval *object;
3248 char *format;
3249 size_t format_len;
3250
3251 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Os", &object, date_ce_interface, &format, &format_len) == FAILURE) {
3252 RETURN_THROWS();
3253 }
3254 dateobj = Z_PHPDATE_P(object);
3256 RETURN_STR(date_format(format, format_len, dateobj->time, dateobj->time->is_localtime));
3257}
3258/* }}} */
3259
3260static bool php_date_modify(zval *object, char *modify, size_t modify_len) /* {{{ */
3261{
3263 timelib_time *tmp_time;
3265
3266 dateobj = Z_PHPDATE_P(object);
3267
3268 if (!(dateobj->time)) {
3269 date_throw_uninitialized_error(Z_OBJCE_P(object));
3270 return 0;
3271 }
3272
3273 tmp_time = timelib_strtotime(modify, modify_len, &err, DATE_TIMEZONEDB, php_date_parse_tzfile_wrapper);
3274
3275 /* update last errors and warnings */
3276 update_errors_warnings(&err);
3277
3278 if (err && err->error_count) {
3279 /* spit out the first library error message, at least */
3280 php_error_docref(NULL, E_WARNING, "Failed to parse time string (%s) at position %d (%c): %s", modify,
3281 err->error_messages[0].position,
3282 err->error_messages[0].character ? err->error_messages[0].character : ' ',
3283 err->error_messages[0].message);
3284 timelib_time_dtor(tmp_time);
3285 return 0;
3286 }
3287
3288 memcpy(&dateobj->time->relative, &tmp_time->relative, sizeof(timelib_rel_time));
3289 dateobj->time->have_relative = tmp_time->have_relative;
3290 dateobj->time->sse_uptodate = 0;
3291
3292 if (tmp_time->y != TIMELIB_UNSET) {
3293 dateobj->time->y = tmp_time->y;
3294 }
3295 if (tmp_time->m != TIMELIB_UNSET) {
3296 dateobj->time->m = tmp_time->m;
3297 }
3298 if (tmp_time->d != TIMELIB_UNSET) {
3299 dateobj->time->d = tmp_time->d;
3300 }
3301
3302 if (tmp_time->h != TIMELIB_UNSET) {
3303 dateobj->time->h = tmp_time->h;
3304 if (tmp_time->i != TIMELIB_UNSET) {
3305 dateobj->time->i = tmp_time->i;
3306 if (tmp_time->s != TIMELIB_UNSET) {
3307 dateobj->time->s = tmp_time->s;
3308 } else {
3309 dateobj->time->s = 0;
3310 }
3311 } else {
3312 dateobj->time->i = 0;
3313 dateobj->time->s = 0;
3314 }
3315 }
3316
3317 if (tmp_time->us != TIMELIB_UNSET) {
3318 dateobj->time->us = tmp_time->us;
3319 }
3320
3321 /* Reset timezone to UTC if we detect a "@<ts>" modification */
3322 if (
3323 tmp_time->y == 1970 && tmp_time->m == 1 && tmp_time->d == 1 &&
3324 tmp_time->h == 0 && tmp_time->i == 0 && tmp_time->s == 0 && tmp_time->us == 0 &&
3325 tmp_time->have_zone && tmp_time->zone_type == TIMELIB_ZONETYPE_OFFSET &&
3326 tmp_time->z == 0 && tmp_time->dst == 0
3327 ) {
3329 }
3330
3331 timelib_time_dtor(tmp_time);
3332
3335 dateobj->time->have_relative = 0;
3336 memset(&dateobj->time->relative, 0, sizeof(dateobj->time->relative));
3337
3338 return 1;
3339} /* }}} */
3340
3341/* {{{ Alters the timestamp. */
3343{
3344 zval *object;
3345 char *modify;
3346 size_t modify_len;
3347
3348 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Os", &object, date_ce_date, &modify, &modify_len) == FAILURE) {
3349 RETURN_THROWS();
3350 }
3351
3352 if (!php_date_modify(object, modify, modify_len)) {
3354 }
3355
3356 RETURN_OBJ_COPY(Z_OBJ_P(object));
3357}
3358/* }}} */
3359
3360/* {{{ */
3362{
3363 zval *object;
3364 char *modify;
3365 size_t modify_len;
3367
3368 object = ZEND_THIS;
3370 Z_PARAM_STRING(modify, modify_len)
3372
3373 zend_replace_error_handling(EH_THROW, date_ce_date_malformed_string_exception, &zeh);
3374 if (!php_date_modify(object, modify, modify_len)) {
3376 RETURN_THROWS();
3377 }
3378
3380
3381 RETURN_OBJ_COPY(Z_OBJ_P(object));
3382}
3383/* }}} */
3384
3385/* {{{ */
3387{
3388 zval *object, new_object;
3389 char *modify;
3390 size_t modify_len;
3392
3393 object = ZEND_THIS;
3395 Z_PARAM_STRING(modify, modify_len)
3397
3398 date_clone_immutable(object, &new_object);
3399
3400 zend_replace_error_handling(EH_THROW, date_ce_date_malformed_string_exception, &zeh);
3401 if (!php_date_modify(&new_object, modify, modify_len)) {
3402 zval_ptr_dtor(&new_object);
3404 RETURN_THROWS();
3405 }
3406
3408
3409 RETURN_OBJ(Z_OBJ(new_object));
3410}
3411/* }}} */
3412
3413static void php_date_add(zval *object, zval *interval, zval *return_value) /* {{{ */
3414{
3416 php_interval_obj *intobj;
3417 timelib_time *new_time;
3418
3419 dateobj = Z_PHPDATE_P(object);
3421 intobj = Z_PHPINTERVAL_P(interval);
3422 DATE_CHECK_INITIALIZED(intobj->initialized, Z_OBJCE_P(interval));
3423
3424 if (intobj->civil_or_wall == PHP_DATE_WALL) {
3425 new_time = timelib_add_wall(dateobj->time, intobj->diff);
3426 } else {
3427 new_time = timelib_add(dateobj->time, intobj->diff);
3428 }
3430 dateobj->time = new_time;
3431} /* }}} */
3432
3433/* {{{ Adds an interval to the current date in object. */
3435{
3436 zval *object, *interval;
3437
3438 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "OO", &object, date_ce_date, &interval, date_ce_interval) == FAILURE) {
3439 RETURN_THROWS();
3440 }
3441
3442 php_date_add(object, interval, return_value);
3443
3444 RETURN_OBJ_COPY(Z_OBJ_P(object));
3445}
3446/* }}} */
3447
3448/* {{{ */
3450{
3451 zval *object, *interval, new_object;
3452
3453 object = ZEND_THIS;
3455 Z_PARAM_OBJECT_OF_CLASS(interval, date_ce_interval)
3457
3458 date_clone_immutable(object, &new_object);
3459 php_date_add(&new_object, interval, return_value);
3460
3461 RETURN_OBJ(Z_OBJ(new_object));
3462}
3463/* }}} */
3464
3465static void php_date_sub(zval *object, zval *interval, zval *return_value) /* {{{ */
3466{
3468 php_interval_obj *intobj;
3469 timelib_time *new_time;
3470
3471 dateobj = Z_PHPDATE_P(object);
3473 intobj = Z_PHPINTERVAL_P(interval);
3474 DATE_CHECK_INITIALIZED(intobj->initialized, Z_OBJCE_P(interval));
3475
3476 if (intobj->diff->have_weekday_relative || intobj->diff->have_special_relative) {
3477 php_error_docref(NULL, E_WARNING, "Only non-special relative time specifications are supported for subtraction");
3478 return;
3479 }
3480
3481 if (intobj->civil_or_wall == PHP_DATE_WALL) {
3482 new_time = timelib_sub_wall(dateobj->time, intobj->diff);
3483 } else {
3484 new_time = timelib_sub(dateobj->time, intobj->diff);
3485 }
3487 dateobj->time = new_time;
3488} /* }}} */
3489
3490/* {{{ Subtracts an interval to the current date in object. */
3492{
3493 zval *object, *interval;
3494
3495 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "OO", &object, date_ce_date, &interval, date_ce_interval) == FAILURE) {
3496 RETURN_THROWS();
3497 }
3498
3499 php_date_sub(object, interval, return_value);
3500 RETURN_OBJ_COPY(Z_OBJ_P(object));
3501}
3502/* }}} */
3503
3504/* {{{ Subtracts an interval to the current date in object. */
3506{
3507 zval *object, *interval;
3509
3510 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "OO", &object, date_ce_date, &interval, date_ce_interval) == FAILURE) {
3511 RETURN_THROWS();
3512 }
3513
3514 zend_replace_error_handling(EH_THROW, date_ce_date_invalid_operation_exception, &zeh);
3515 php_date_sub(object, interval, return_value);
3517
3518 RETURN_OBJ_COPY(Z_OBJ_P(object));
3519}
3520/* }}} */
3521
3522/* {{{ */
3524{
3525 zval *object, *interval, new_object;
3527
3528 object = ZEND_THIS;
3530 Z_PARAM_OBJECT_OF_CLASS(interval, date_ce_interval)
3532
3533 date_clone_immutable(object, &new_object);
3534
3535 zend_replace_error_handling(EH_THROW, date_ce_date_invalid_operation_exception, &zeh);
3536 php_date_sub(&new_object, interval, return_value);
3538
3539 RETURN_OBJ(Z_OBJ(new_object));
3540}
3541/* }}} */
3542
3543static void set_timezone_from_timelib_time(php_timezone_obj *tzobj, timelib_time *t)
3544{
3545 /* Free abbreviation if already set */
3546 if (tzobj->initialized && tzobj->type == TIMELIB_ZONETYPE_ABBR) {
3547 timelib_free(tzobj->tzi.z.abbr);
3548 }
3549
3550 /* Set new values */
3551 tzobj->initialized = 1;
3552 tzobj->type = t->zone_type;
3553
3554 switch (t->zone_type) {
3556 tzobj->tzi.tz = t->tz_info;
3557 break;
3559 tzobj->tzi.utc_offset = t->z;
3560 break;
3562 tzobj->tzi.z.utc_offset = t->z;
3563 tzobj->tzi.z.dst = t->dst;
3564 tzobj->tzi.z.abbr = timelib_strdup(t->tz_abbr);
3565 break;
3566 }
3567}
3568
3569
3570/* {{{ Return new DateTimeZone object relative to give DateTime */
3572{
3573 zval *object;
3575
3576 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &object, date_ce_interface) == FAILURE) {
3577 RETURN_THROWS();
3578 }
3579 dateobj = Z_PHPDATE_P(object);
3581 if (dateobj->time->is_localtime) {
3582 php_timezone_obj *tzobj;
3583 php_date_instantiate(date_ce_timezone, return_value);
3585 set_timezone_from_timelib_time(tzobj, dateobj->time);
3586 } else {
3588 }
3589}
3590/* }}} */
3591
3592static void php_date_timezone_set(zval *object, zval *timezone_object, zval *return_value) /* {{{ */
3593{
3595 php_timezone_obj *tzobj;
3596
3597 dateobj = Z_PHPDATE_P(object);
3599 tzobj = Z_PHPTIMEZONE_P(timezone_object);
3600
3601 switch (tzobj->type) {
3604 break;
3607 break;
3609 timelib_set_timezone(dateobj->time, tzobj->tzi.tz);
3610 break;
3611 }
3612 timelib_unixtime2local(dateobj->time, dateobj->time->sse);
3613} /* }}} */
3614
3615/* {{{ Sets the timezone for the DateTime object. */
3617{
3618 zval *object;
3619 zval *timezone_object;
3620
3621 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "OO", &object, date_ce_date, &timezone_object, date_ce_timezone) == FAILURE) {
3622 RETURN_THROWS();
3623 }
3624
3625 php_date_timezone_set(object, timezone_object, return_value);
3626
3627 RETURN_OBJ_COPY(Z_OBJ_P(object));
3628}
3629/* }}} */
3630
3631/* {{{ */
3633{
3634 zval *object, new_object;
3635 zval *timezone_object;
3636
3637 object = ZEND_THIS;
3639 Z_PARAM_OBJECT_OF_CLASS(timezone_object, date_ce_timezone)
3641
3642 date_clone_immutable(object, &new_object);
3643 php_date_timezone_set(&new_object, timezone_object, return_value);
3644
3645 RETURN_OBJ(Z_OBJ(new_object));
3646}
3647/* }}} */
3648
3649/* {{{ Returns the DST offset. */
3651{
3652 zval *object;
3655
3656 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &object, date_ce_interface) == FAILURE) {
3657 RETURN_THROWS();
3658 }
3659 dateobj = Z_PHPDATE_P(object);
3661 if (dateobj->time->is_localtime) {
3662 switch (dateobj->time->zone_type) {
3664 offset = timelib_get_time_zone_info(dateobj->time->sse, dateobj->time->tz_info);
3665 RETVAL_LONG(offset->offset);
3667 break;
3669 RETVAL_LONG(dateobj->time->z);
3670 break;
3672 RETVAL_LONG((dateobj->time->z + (3600 * dateobj->time->dst)));
3673 break;
3674 }
3675 return;
3676 } else {
3677 RETURN_LONG(0);
3678 }
3679}
3680/* }}} */
3681
3682static void php_date_time_set(zval *object, zend_long h, zend_long i, zend_long s, zend_long ms, zval *return_value) /* {{{ */
3683{
3685
3686 dateobj = Z_PHPDATE_P(object);
3688 dateobj->time->h = h;
3689 dateobj->time->i = i;
3690 dateobj->time->s = s;
3691 dateobj->time->us = ms;
3694} /* }}} */
3695
3696/* {{{ Sets the time. */
3698{
3699 zval *object;
3700 zend_long h, i, s = 0, ms = 0;
3701
3702 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Oll|ll", &object, date_ce_date, &h, &i, &s, &ms) == FAILURE) {
3703 RETURN_THROWS();
3704 }
3705
3706 php_date_time_set(object, h, i, s, ms, return_value);
3707
3708 RETURN_OBJ_COPY(Z_OBJ_P(object));
3709}
3710/* }}} */
3711
3712/* {{{ */
3714{
3715 zval *object, new_object;
3716 zend_long h, i, s = 0, ms = 0;
3717
3718 object = ZEND_THIS;
3720 Z_PARAM_LONG(h)
3721 Z_PARAM_LONG(i)
3724 Z_PARAM_LONG(ms)
3726
3727 date_clone_immutable(object, &new_object);
3728 php_date_time_set(&new_object, h, i, s, ms, return_value);
3729
3730 RETURN_OBJ(Z_OBJ(new_object));
3731}
3732/* }}} */
3733
3734static void php_date_date_set(zval *object, zend_long y, zend_long m, zend_long d, zval *return_value) /* {{{ */
3735{
3737
3738 dateobj = Z_PHPDATE_P(object);
3740 dateobj->time->y = y;
3741 dateobj->time->m = m;
3742 dateobj->time->d = d;
3744} /* }}} */
3745
3746/* {{{ Sets the date. */
3748{
3749 zval *object;
3750 zend_long y, m, d;
3751
3752 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Olll", &object, date_ce_date, &y, &m, &d) == FAILURE) {
3753 RETURN_THROWS();
3754 }
3755
3756 php_date_date_set(object, y, m, d, return_value);
3757
3758 RETURN_OBJ_COPY(Z_OBJ_P(object));
3759}
3760/* }}} */
3761
3762/* {{{ */
3764{
3765 zval *object, new_object;
3766 zend_long y, m, d;
3767
3768 object = ZEND_THIS;
3770 Z_PARAM_LONG(y)
3771 Z_PARAM_LONG(m)
3772 Z_PARAM_LONG(d)
3774
3775 date_clone_immutable(object, &new_object);
3776 php_date_date_set(&new_object, y, m, d, return_value);
3777
3778 RETURN_OBJ(Z_OBJ(new_object));
3779}
3780/* }}} */
3781
3782static void php_date_isodate_set(zval *object, zend_long y, zend_long w, zend_long d, zval *return_value) /* {{{ */
3783{
3785
3786 dateobj = Z_PHPDATE_P(object);
3788 dateobj->time->y = y;
3789 dateobj->time->m = 1;
3790 dateobj->time->d = 1;
3791 memset(&dateobj->time->relative, 0, sizeof(dateobj->time->relative));
3792 dateobj->time->relative.d = timelib_daynr_from_weeknr(y, w, d);
3793 dateobj->time->have_relative = 1;
3794
3796} /* }}} */
3797
3798/* {{{ Sets the ISO date. */
3800{
3801 zval *object;
3802 zend_long y, w, d = 1;
3803
3804 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Oll|l", &object, date_ce_date, &y, &w, &d) == FAILURE) {
3805 RETURN_THROWS();
3806 }
3807
3808 php_date_isodate_set(object, y, w, d, return_value);
3809
3810 RETURN_OBJ_COPY(Z_OBJ_P(object));
3811}
3812/* }}} */
3813
3814/* {{{ */
3816{
3817 zval *object, new_object;
3818 zend_long y, w, d = 1;
3819
3820 object = ZEND_THIS;
3822 Z_PARAM_LONG(y)
3823 Z_PARAM_LONG(w)
3825 Z_PARAM_LONG(d)
3827
3828 date_clone_immutable(object, &new_object);
3829 php_date_isodate_set(&new_object, y, w, d, return_value);
3830
3831 RETURN_OBJ(Z_OBJ(new_object));
3832}
3833/* }}} */
3834
3835static void php_date_timestamp_set(zval *object, zend_long timestamp, zval *return_value) /* {{{ */
3836{
3838
3839 dateobj = Z_PHPDATE_P(object);
3841 timelib_unixtime2local(dateobj->time, (timelib_sll)timestamp);
3843 php_date_set_time_fraction(dateobj->time, 0);
3844} /* }}} */
3845
3846/* {{{ Sets the date and time based on an Unix timestamp. */
3848{
3849 zval *object;
3850 zend_long timestamp;
3851
3852 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Ol", &object, date_ce_date, &timestamp) == FAILURE) {
3853 RETURN_THROWS();
3854 }
3855
3856 php_date_timestamp_set(object, timestamp, return_value);
3857
3858 RETURN_OBJ_COPY(Z_OBJ_P(object));
3859}
3860/* }}} */
3861
3862/* {{{ */
3864{
3865 zval *object, new_object;
3866 zend_long timestamp;
3867
3868 object = ZEND_THIS;
3870 Z_PARAM_LONG(timestamp)
3872
3873 date_clone_immutable(object, &new_object);
3874 php_date_timestamp_set(&new_object, timestamp, return_value);
3875
3876 RETURN_OBJ(Z_OBJ(new_object));
3877}
3878/* }}} */
3879
3880/* {{{ */
3882{
3883 zval *object, new_object;
3884 php_date_obj *dateobj, *new_dateobj;
3885 zend_long us;
3886
3888 Z_PARAM_LONG(us)
3890
3891 if (UNEXPECTED(us < 0 || us > 999999)) {
3893 date_ce_date_range_error,
3894 1,
3895 "must be between 0 and 999999, " ZEND_LONG_FMT " given",
3896 us
3897 );
3898 RETURN_THROWS();
3899 }
3900
3901 object = ZEND_THIS;
3902 dateobj = Z_PHPDATE_P(object);
3904
3905 date_clone_immutable(object, &new_object);
3906 new_dateobj = Z_PHPDATE_P(&new_object);
3907
3908 php_date_set_time_fraction(new_dateobj->time, (int)us);
3909
3910 RETURN_OBJ(Z_OBJ(new_object));
3911}
3912/* }}} */
3913
3914/* {{{ */
3915PHP_METHOD(DateTime, setMicrosecond)
3916{
3917 zval *object;
3919 zend_long us;
3920
3922 Z_PARAM_LONG(us)
3924
3925 if (UNEXPECTED(us < 0 || us > 999999)) {
3927 date_ce_date_range_error,
3928 1,
3929 "must be between 0 and 999999, " ZEND_LONG_FMT " given",
3930 us
3931 );
3932 RETURN_THROWS();
3933 }
3934
3935 object = ZEND_THIS;
3936 dateobj = Z_PHPDATE_P(object);
3938 php_date_set_time_fraction(dateobj->time, (int)us);
3939
3940 RETURN_OBJ_COPY(Z_OBJ_P(object));
3941}
3942/* }}} */
3943
3944/* {{{ Gets the Unix timestamp. */
3946{
3947 zval *object;
3949 zend_long timestamp;
3950 int epoch_does_not_fit_in_zend_long;
3951
3952 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &object, date_ce_interface) == FAILURE) {
3953 RETURN_THROWS();
3954 }
3955 dateobj = Z_PHPDATE_P(object);
3957
3958 if (!dateobj->time->sse_uptodate) {
3960 }
3961
3962 timestamp = timelib_date_to_int(dateobj->time, &epoch_does_not_fit_in_zend_long);
3963
3964 if (epoch_does_not_fit_in_zend_long) {
3965 zend_throw_error(date_ce_date_range_error, "Epoch doesn't fit in a PHP integer");
3966 RETURN_THROWS();
3967 }
3968
3969 RETURN_LONG(timestamp);
3970}
3971/* }}} */
3972
3973PHP_METHOD(DateTime, getMicrosecond) /* {{{ */
3974{
3975 zval *object;
3977
3979
3980 object = ZEND_THIS;
3981 dateobj = Z_PHPDATE_P(object);
3983
3985}
3986/* }}} */
3987
3988/* {{{ Returns the difference between two DateTime objects. */
3990{
3991 zval *object1, *object2;
3992 php_date_obj *dateobj1, *dateobj2;
3993 php_interval_obj *interval;
3994 bool absolute = 0;
3995
3996 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "OO|b", &object1, date_ce_interface, &object2, date_ce_interface, &absolute) == FAILURE) {
3997 RETURN_THROWS();
3998 }
3999 dateobj1 = Z_PHPDATE_P(object1);
4000 dateobj2 = Z_PHPDATE_P(object2);
4001 DATE_CHECK_INITIALIZED(dateobj1->time, Z_OBJCE_P(object1));
4002 DATE_CHECK_INITIALIZED(dateobj2->time, Z_OBJCE_P(object2));
4003
4004 php_date_instantiate(date_ce_interval, return_value);
4005 interval = Z_PHPINTERVAL_P(return_value);
4006 interval->diff = timelib_diff(dateobj1->time, dateobj2->time);
4007 if (absolute) {
4008 interval->diff->invert = 0;
4009 }
4010 interval->initialized = 1;
4011 interval->civil_or_wall = PHP_DATE_CIVIL;
4012}
4013/* }}} */
4014
4015static bool timezone_initialize(php_timezone_obj *tzobj, const char *tz, size_t tz_len, char **warning_message) /* {{{ */
4016{
4017 timelib_time *dummy_t = ecalloc(1, sizeof(timelib_time));
4018 int dst, not_found;
4019 const char *orig_tz = tz;
4020
4021 if (strlen(tz) != tz_len) {
4022 if (warning_message) {
4023 spprintf(warning_message, 0, "Timezone must not contain null bytes");
4024 }
4025 efree(dummy_t);
4026 return false;
4027 }
4028
4029 dummy_t->z = timelib_parse_zone(&tz, &dst, dummy_t, &not_found, DATE_TIMEZONEDB, php_date_parse_tzfile_wrapper);
4030 if ((dummy_t->z >= (100 * 60 * 60)) || (dummy_t->z <= (-100 * 60 * 60))) {
4031 if (warning_message) {
4032 spprintf(warning_message, 0, "Timezone offset is out of range (%s)", orig_tz);
4033 }
4034 timelib_free(dummy_t->tz_abbr);
4035 efree(dummy_t);
4036 return false;
4037 }
4038 dummy_t->dst = dst;
4039 if (!not_found && (*tz != '\0')) {
4040 if (warning_message) {
4041 spprintf(warning_message, 0, "Unknown or bad timezone (%s)", orig_tz);
4042 }
4043 timelib_free(dummy_t->tz_abbr);
4044 efree(dummy_t);
4045 return false;
4046 }
4047 if (not_found) {
4048 if (warning_message) {
4049 spprintf(warning_message, 0, "Unknown or bad timezone (%s)", orig_tz);
4050 }
4051 efree(dummy_t);
4052 return false;
4053 } else {
4054 set_timezone_from_timelib_time(tzobj, dummy_t);
4055 timelib_free(dummy_t->tz_abbr);
4056 efree(dummy_t);
4057 return true;
4058 }
4059} /* }}} */
4060
4061/* {{{ Returns new DateTimeZone object */
4063{
4064 zend_string *tz;
4065 php_timezone_obj *tzobj;
4066 char *warning_message;
4067
4069 Z_PARAM_PATH_STR(tz) /* To prevent null bytes */
4071
4072 tzobj = Z_PHPTIMEZONE_P(php_date_instantiate(date_ce_timezone, return_value));
4073 if (!timezone_initialize(tzobj, ZSTR_VAL(tz), ZSTR_LEN(tz), &warning_message)) {
4074 php_error_docref(NULL, E_WARNING, "%s", warning_message);
4075 efree(warning_message);
4078 }
4079}
4080/* }}} */
4081
4082/* {{{ Creates new DateTimeZone object. */
4084{
4085 zend_string *tz;
4086 php_timezone_obj *tzobj;
4087 char *exception_message;
4088
4090 Z_PARAM_PATH_STR(tz) /* To prevent null bytes */
4092
4093 tzobj = Z_PHPTIMEZONE_P(ZEND_THIS);
4094 if (!timezone_initialize(tzobj, ZSTR_VAL(tz), ZSTR_LEN(tz), &exception_message)) {
4095 zend_throw_exception_ex(date_ce_date_invalid_timezone_exception, 0, "DateTimeZone::__construct(): %s", exception_message);
4096 efree(exception_message);
4097 RETURN_THROWS();
4098 }
4099}
4100/* }}} */
4101
4102static bool php_date_timezone_initialize_from_hash(zval **return_value, php_timezone_obj **tzobj, HashTable *myht) /* {{{ */
4103{
4104 zval *z_timezone_type;
4105
4106 if ((z_timezone_type = zend_hash_str_find(myht, "timezone_type", sizeof("timezone_type") - 1)) == NULL) {
4107 return false;
4108 }
4109
4110 zval *z_timezone;
4111
4112 if ((z_timezone = zend_hash_str_find(myht, "timezone", sizeof("timezone") - 1)) == NULL) {
4113 return false;
4114 }
4115
4116 if (Z_TYPE_P(z_timezone_type) != IS_LONG) {
4117 return false;
4118 }
4119 if (Z_LVAL_P(z_timezone_type) < TIMELIB_ZONETYPE_OFFSET || Z_LVAL_P(z_timezone_type) > TIMELIB_ZONETYPE_ID) {
4120 return false;
4121 }
4122 if (Z_TYPE_P(z_timezone) != IS_STRING) {
4123 return false;
4124 }
4125 return timezone_initialize(*tzobj, Z_STRVAL_P(z_timezone), Z_STRLEN_P(z_timezone), NULL);
4126} /* }}} */
4127
4128/* {{{ */
4130{
4131 php_timezone_obj *tzobj;
4132 zval *array;
4133 HashTable *myht;
4134
4136 Z_PARAM_ARRAY(array)
4138
4139 myht = Z_ARRVAL_P(array);
4140
4141 php_date_instantiate(date_ce_timezone, return_value);
4143 if (!php_date_timezone_initialize_from_hash(&return_value, &tzobj, myht)) {
4144 zend_throw_error(NULL, "Invalid serialization data for DateTimeZone object");
4145 RETURN_THROWS();
4146 }
4147}
4148/* }}} */
4149
4150/* {{{ */
4152{
4153 zval *object = ZEND_THIS;
4154 php_timezone_obj *tzobj;
4155 HashTable *myht;
4156
4158
4159 tzobj = Z_PHPTIMEZONE_P(object);
4160
4161 myht = Z_OBJPROP_P(object);
4162
4163 if (!php_date_timezone_initialize_from_hash(&return_value, &tzobj, myht)) {
4164 zend_throw_error(NULL, "Invalid serialization data for DateTimeZone object");
4165 RETURN_THROWS();
4166 }
4167}
4168/* }}} */
4169
4170/* {{{ */
4172{
4173 zval *object = ZEND_THIS;
4174 php_timezone_obj *tzobj;
4175 HashTable *myht;
4176
4178
4179 tzobj = Z_PHPTIMEZONE_P(object);
4181
4183 myht = Z_ARRVAL_P(return_value);
4184 date_timezone_object_to_hash(tzobj, myht);
4185
4186 add_common_properties(myht, &tzobj->std);
4187}
4188/* }}} */
4189
4190static bool date_timezone_is_internal_property(zend_string *name)
4191{
4192 if (
4193 zend_string_equals_literal(name, "timezone_type") ||
4194 zend_string_equals_literal(name, "timezone")
4195 ) {
4196 return 1;
4197 }
4198 return 0;
4199}
4200
4201static void restore_custom_datetimezone_properties(zval *object, HashTable *myht)
4202{
4203 zend_string *prop_name;
4204 zval *prop_val;
4205
4206 ZEND_HASH_FOREACH_STR_KEY_VAL(myht, prop_name, prop_val) {
4207 if (!prop_name || (Z_TYPE_P(prop_val) == IS_REFERENCE) || date_timezone_is_internal_property(prop_name)) {
4208 continue;
4209 }
4210 update_property(Z_OBJ_P(object), prop_name, prop_val);
4212}
4213
4214/* {{{ */
4216{
4217 zval *object = ZEND_THIS;
4218 php_timezone_obj *tzobj;
4219 zval *array;
4220 HashTable *myht;
4221
4223 Z_PARAM_ARRAY(array)
4225
4226 tzobj = Z_PHPTIMEZONE_P(object);
4227 myht = Z_ARRVAL_P(array);
4228
4229 if (!php_date_timezone_initialize_from_hash(&object, &tzobj, myht)) {
4230 zend_throw_error(NULL, "Invalid serialization data for DateTimeZone object");
4231 RETURN_THROWS();
4232 }
4233
4234 restore_custom_datetimezone_properties(object, myht);
4235}
4236/* }}} */
4237
4238/* {{{ Returns the name of the timezone. */
4240{
4241 zval *object;
4242 php_timezone_obj *tzobj;
4243
4244 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &object, date_ce_timezone) == FAILURE) {
4245 RETURN_THROWS();
4246 }
4247 tzobj = Z_PHPTIMEZONE_P(object);
4249 php_timezone_to_string(tzobj, return_value);
4250}
4251/* }}} */
4252
4253/* {{{ Returns the timezone name from abbreviation */
4255{
4256 zend_string *abbr;
4257 const char *tzid;
4258 zend_long gmtoffset = -1;
4259 zend_long isdst = -1;
4260
4262 Z_PARAM_STR(abbr)
4264 Z_PARAM_LONG(gmtoffset)
4265 Z_PARAM_LONG(isdst)
4267
4268 tzid = timelib_timezone_id_from_abbr(ZSTR_VAL(abbr), gmtoffset, isdst);
4269
4270 if (tzid) {
4271 RETURN_STRING(tzid);
4272 } else {
4274 }
4275}
4276/* }}} */
4277
4278/* {{{ Returns the timezone offset. */
4280{
4281 zval *object, *dateobject;
4282 php_timezone_obj *tzobj;
4285
4286 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "OO", &object, date_ce_timezone, &dateobject, date_ce_interface) == FAILURE) {
4287 RETURN_THROWS();
4288 }
4289 tzobj = Z_PHPTIMEZONE_P(object);
4291 dateobj = Z_PHPDATE_P(dateobject);
4292 DATE_CHECK_INITIALIZED(dateobj->time, Z_OBJCE_P(dateobject));
4293
4294 switch (tzobj->type) {
4296 offset = timelib_get_time_zone_info(dateobj->time->sse, tzobj->tzi.tz);
4297 RETVAL_LONG(offset->offset);
4299 break;
4301 RETURN_LONG(tzobj->tzi.utc_offset);
4302 break;
4304 RETURN_LONG(tzobj->tzi.z.utc_offset + (tzobj->tzi.z.dst * 3600));
4305 break;
4306 }
4307}
4308/* }}} */
4309
4310/* {{{ Returns numerically indexed array containing associative array for all transitions in the specified range for the timezone. */
4312{
4313 zval *object, element;
4314 php_timezone_obj *tzobj;
4315 uint64_t begin = 0;
4316 bool found;
4317 zend_long timestamp_begin = ZEND_LONG_MIN, timestamp_end = INT32_MAX;
4318
4319 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O|ll", &object, date_ce_timezone, &timestamp_begin, &timestamp_end) == FAILURE) {
4320 RETURN_THROWS();
4321 }
4322 tzobj = Z_PHPTIMEZONE_P(object);
4324 if (tzobj->type != TIMELIB_ZONETYPE_ID) {
4326 }
4327
4328#define add_nominal() \
4329 array_init(&element); \
4330 add_assoc_long(&element, "ts", timestamp_begin); \
4331 add_assoc_str(&element, "time", php_format_date(DATE_FORMAT_ISO8601_LARGE_YEAR, 13, timestamp_begin, 0)); \
4332 add_assoc_long(&element, "offset", tzobj->tzi.tz->type[0].offset); \
4333 add_assoc_bool(&element, "isdst", tzobj->tzi.tz->type[0].isdst); \
4334 add_assoc_string(&element, "abbr", &tzobj->tzi.tz->timezone_abbr[tzobj->tzi.tz->type[0].abbr_idx]); \
4335 add_next_index_zval(return_value, &element);
4336
4337#define add(i,ts) \
4338 array_init(&element); \
4339 add_assoc_long(&element, "ts", ts); \
4340 add_assoc_str(&element, "time", php_format_date(DATE_FORMAT_ISO8601_LARGE_YEAR, 13, ts, 0)); \
4341 add_assoc_long(&element, "offset", tzobj->tzi.tz->type[tzobj->tzi.tz->trans_idx[i]].offset); \
4342 add_assoc_bool(&element, "isdst", tzobj->tzi.tz->type[tzobj->tzi.tz->trans_idx[i]].isdst); \
4343 add_assoc_string(&element, "abbr", &tzobj->tzi.tz->timezone_abbr[tzobj->tzi.tz->type[tzobj->tzi.tz->trans_idx[i]].abbr_idx]); \
4344 add_next_index_zval(return_value, &element);
4345
4346#define add_by_index(i,ts) \
4347 array_init(&element); \
4348 add_assoc_long(&element, "ts", ts); \
4349 add_assoc_str(&element, "time", php_format_date(DATE_FORMAT_ISO8601_LARGE_YEAR, 13, ts, 0)); \
4350 add_assoc_long(&element, "offset", tzobj->tzi.tz->type[i].offset); \
4351 add_assoc_bool(&element, "isdst", tzobj->tzi.tz->type[i].isdst); \
4352 add_assoc_string(&element, "abbr", &tzobj->tzi.tz->timezone_abbr[tzobj->tzi.tz->type[i].abbr_idx]); \
4353 add_next_index_zval(return_value, &element);
4354
4355#define add_from_tto(to,ts) \
4356 array_init(&element); \
4357 add_assoc_long(&element, "ts", ts); \
4358 add_assoc_str(&element, "time", php_format_date(DATE_FORMAT_ISO8601_LARGE_YEAR, 13, ts, 0)); \
4359 add_assoc_long(&element, "offset", (to)->offset); \
4360 add_assoc_bool(&element, "isdst", (to)->is_dst); \
4361 add_assoc_string(&element, "abbr", (to)->abbr); \
4362 add_next_index_zval(return_value, &element);
4363
4364#define add_last() add(tzobj->tzi.tz->bit64.timecnt - 1, timestamp_begin)
4365
4367
4368 if (timestamp_begin == ZEND_LONG_MIN) {
4369 add_nominal();
4370 begin = 0;
4371 found = 1;
4372 } else {
4373 begin = 0;
4374 found = 0;
4375 if (tzobj->tzi.tz->bit64.timecnt > 0) {
4376 do {
4377 if (tzobj->tzi.tz->trans[begin] > timestamp_begin) {
4378 if (begin > 0) {
4379 add(begin - 1, timestamp_begin);
4380 } else {
4381 add_nominal();
4382 }
4383 found = 1;
4384 break;
4385 }
4386 begin++;
4387 } while (begin < tzobj->tzi.tz->bit64.timecnt);
4388 }
4389 }
4390
4391 if (!found) {
4392 if (tzobj->tzi.tz->bit64.timecnt > 0) {
4393 if (tzobj->tzi.tz->posix_info && tzobj->tzi.tz->posix_info->dst_end) {
4394 timelib_time_offset *tto = timelib_get_time_zone_info(timestamp_begin, tzobj->tzi.tz);
4395 add_from_tto(tto, timestamp_begin);
4397 } else {
4398 add_last();
4399 }
4400 } else {
4401 add_nominal();
4402 }
4403 } else {
4404 for (uint64_t i = begin; i < tzobj->tzi.tz->bit64.timecnt; ++i) {
4405 if (tzobj->tzi.tz->trans[i] < timestamp_end) {
4406 add(i, tzobj->tzi.tz->trans[i]);
4407 } else {
4408 return;
4409 }
4410 }
4411 }
4412 if (tzobj->tzi.tz->posix_info && tzobj->tzi.tz->posix_info->dst_end) {
4413 timelib_sll start_y, end_y, dummy_m, dummy_d;
4414 timelib_sll last_transition_ts = tzobj->tzi.tz->trans[tzobj->tzi.tz->bit64.timecnt - 1];
4415
4416 /* Find out year for last transition */
4417 timelib_unixtime2date(last_transition_ts, &start_y, &dummy_m, &dummy_d);
4418
4419 /* Find out year for final boundary timestamp */
4420 timelib_unixtime2date(timestamp_end, &end_y, &dummy_m, &dummy_d);
4421
4422 for (timelib_sll i = start_y; i <= end_y; i++) {
4423 timelib_posix_transitions transitions = { 0 };
4424
4425 timelib_get_transitions_for_year(tzobj->tzi.tz, i, &transitions);
4426
4427 for (size_t j = 0; j < transitions.count; j++) {
4428 if (transitions.times[j] <= last_transition_ts) {
4429 continue;
4430 }
4431 if (transitions.times[j] < timestamp_begin) {
4432 continue;
4433 }
4434 if (transitions.times[j] > timestamp_end) {
4435 return;
4436 }
4437 add_by_index(transitions.types[j], transitions.times[j]);
4438 }
4439 }
4440 }
4441}
4442/* }}} */
4443
4444/* {{{ Returns location information for a timezone, including country code, latitude/longitude and comments */
4446{
4447 zval *object;
4448 php_timezone_obj *tzobj;
4449
4450 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &object, date_ce_timezone) == FAILURE) {
4451 RETURN_THROWS();
4452 }
4453 tzobj = Z_PHPTIMEZONE_P(object);
4455 if (tzobj->type != TIMELIB_ZONETYPE_ID) {
4457 }
4458
4460 add_assoc_string(return_value, "country_code", tzobj->tzi.tz->location.country_code);
4461 add_assoc_double(return_value, "latitude", tzobj->tzi.tz->location.latitude);
4462 add_assoc_double(return_value, "longitude", tzobj->tzi.tz->location.longitude);
4463 add_assoc_string(return_value, "comments", tzobj->tzi.tz->location.comments);
4464}
4465/* }}} */
4466
4467static bool date_interval_initialize(timelib_rel_time **rt, /*const*/ char *format, size_t format_length) /* {{{ */
4468{
4469 timelib_time *b = NULL, *e = NULL;
4471 int r = 0;
4472 bool retval = false;
4474
4475 timelib_strtointerval(format, format_length, &b, &e, &p, &r, &errors);
4476
4477 if (errors->error_count > 0) {
4478 zend_throw_exception_ex(date_ce_date_malformed_interval_string_exception, 0, "Unknown or bad format (%s)", format);
4479 retval = false;
4480 if (p) {
4482 }
4483 } else {
4484 if (p) {
4485 *rt = p;
4486 retval = true;
4487 } else {
4488 if (b && e) {
4491 *rt = timelib_diff(b, e);
4492 retval = true;
4493 } else {
4494 zend_throw_exception_ex(date_ce_date_malformed_interval_string_exception, 0, "Failed to parse interval (%s)", format);
4495 retval = false;
4496 }
4497 }
4498 }
4500 timelib_free(b);
4501 timelib_free(e);
4502 return retval;
4503} /* }}} */
4504
4505static int date_interval_compare_objects(zval *o1, zval *o2)
4506{
4508 /* There is no well defined way to compare intervals like P1M and P30D, which may compare
4509 * smaller, equal or greater depending on the point in time at which the interval starts. As
4510 * such, we treat DateInterval objects are non-comparable and emit a warning. */
4511 zend_error(E_WARNING, "Cannot compare DateInterval objects");
4512 return ZEND_UNCOMPARABLE;
4513}
4514
4515/* {{{ date_interval_read_property */
4516static zval *date_interval_read_property(zend_object *object, zend_string *name, int type, void **cache_slot, zval *rv)
4517{
4518 php_interval_obj *obj;
4519 zval *retval;
4520 timelib_sll value = -1;
4521 double fvalue = -1;
4522
4523 obj = php_interval_obj_from_obj(object);
4524
4525 if (!obj->initialized) {
4526 retval = zend_std_read_property(object, name, type, cache_slot, rv);
4527 return retval;
4528 }
4529
4530#define GET_VALUE_FROM_STRUCT(n,m) \
4531 if (zend_string_equals_literal(name, m)) { \
4532 value = obj->diff->n; \
4533 break; \
4534 }
4535 do {
4536 GET_VALUE_FROM_STRUCT(y, "y");
4537 GET_VALUE_FROM_STRUCT(m, "m");
4538 GET_VALUE_FROM_STRUCT(d, "d");
4539 GET_VALUE_FROM_STRUCT(h, "h");
4540 GET_VALUE_FROM_STRUCT(i, "i");
4542 if (zend_string_equals_literal(name, "f")) {
4543 fvalue = obj->diff->us / 1000000.0;
4544 break;
4545 }
4546 GET_VALUE_FROM_STRUCT(invert, "invert");
4547 GET_VALUE_FROM_STRUCT(days, "days");
4548 /* didn't find any */
4549 retval = zend_std_read_property(object, name, type, cache_slot, rv);
4550
4551 return retval;
4552 } while(0);
4553
4554 retval = rv;
4555
4556 if (fvalue != -1) {
4557 ZVAL_DOUBLE(retval, fvalue);
4558 } else if (value != TIMELIB_UNSET) {
4560 } else {
4562 }
4563
4564 return retval;
4565}
4566/* }}} */
4567
4568/* {{{ date_interval_write_property */
4569static zval *date_interval_write_property(zend_object *object, zend_string *name, zval *value, void **cache_slot)
4570{
4571 php_interval_obj *obj;
4572
4573 obj = php_interval_obj_from_obj(object);
4574
4575 if (!obj->initialized) {
4576 return zend_std_write_property(object, name, value, cache_slot);
4577 }
4578
4579#define SET_VALUE_FROM_STRUCT(n,m) \
4580 if (zend_string_equals_literal(name, m)) { \
4581 obj->diff->n = zval_get_long(value); \
4582 break; \
4583 }
4584
4585 do {
4586 SET_VALUE_FROM_STRUCT(y, "y");
4587 SET_VALUE_FROM_STRUCT(m, "m");
4588 SET_VALUE_FROM_STRUCT(d, "d");
4589 SET_VALUE_FROM_STRUCT(h, "h");
4590 SET_VALUE_FROM_STRUCT(i, "i");
4592 if (zend_string_equals_literal(name, "f")) {
4593 obj->diff->us = zend_dval_to_lval(zval_get_double(value) * 1000000.0);
4594 break;
4595 }
4596 SET_VALUE_FROM_STRUCT(invert, "invert");
4597 /* didn't find any */
4598 value = zend_std_write_property(object, name, value, cache_slot);
4599 } while(0);
4600
4601 return value;
4602}
4603/* }}} */
4604
4605/* {{{ date_interval_get_property_ptr_ptr */
4606static zval *date_interval_get_property_ptr_ptr(zend_object *object, zend_string *name, int type, void **cache_slot)
4607{
4608 zval *ret;
4609
4610 if (
4619 zend_string_equals_literal(name, "invert") ) {
4620 /* Fallback to read_property. */
4621 if (cache_slot) {
4622 cache_slot[0] = cache_slot[1] = cache_slot[2] = NULL;
4623 }
4624 ret = NULL;
4625 } else {
4626 ret = zend_std_get_property_ptr_ptr(object, name, type, cache_slot);
4627 }
4628
4629 return ret;
4630}
4631/* }}} */
4632
4633/* {{{ Creates new DateInterval object. */
4635{
4636 zend_string *interval_string = NULL;
4637 timelib_rel_time *reltime;
4638
4640 Z_PARAM_STR(interval_string)
4642
4643 if (!date_interval_initialize(&reltime, ZSTR_VAL(interval_string), ZSTR_LEN(interval_string))) {
4644 RETURN_THROWS();
4645 }
4646
4648 diobj->diff = reltime;
4649 diobj->initialized = 1;
4651}
4652/* }}} */
4653
4654static void php_date_interval_initialize_from_hash(zval **return_value, php_interval_obj **intobj, HashTable *myht) /* {{{ */
4655{
4656 /* If we have a date_string, use that instead */
4657 zval *date_str = zend_hash_str_find(myht, "date_string", strlen("date_string"));
4658 if (date_str && Z_TYPE_P(date_str) == IS_STRING) {
4661
4662 time = timelib_strtotime(Z_STRVAL_P(date_str), Z_STRLEN_P(date_str), &err, DATE_TIMEZONEDB, php_date_parse_tzfile_wrapper);
4663
4664 if (err->error_count > 0) {
4666 "Unknown or bad format (%s) at position %d (%c) while unserializing: %s",
4667 Z_STRVAL_P(date_str),
4668 err->error_messages[0].position,
4669 err->error_messages[0].character ? err->error_messages[0].character : ' ', err->error_messages[0].message);
4672 return;
4673 }
4674
4675 /* If ->diff is already set, then we need to free it first */
4676 if ((*intobj)->diff) {
4677 timelib_rel_time_dtor((*intobj)->diff);
4678 }
4679
4680 (*intobj)->diff = timelib_rel_time_clone(&time->relative);
4681 (*intobj)->initialized = 1;
4682 (*intobj)->civil_or_wall = PHP_DATE_CIVIL;
4683 (*intobj)->from_string = true;
4684 (*intobj)->date_string = zend_string_copy(Z_STR_P(date_str));
4685
4688
4689 return;
4690 }
4691
4692 /* If ->diff is already set, then we need to free it first */
4693 if ((*intobj)->diff) {
4694 timelib_rel_time_dtor((*intobj)->diff);
4695 }
4696
4697 /* Set new value */
4698 (*intobj)->diff = timelib_rel_time_ctor();
4699
4700#define PHP_DATE_INTERVAL_READ_PROPERTY(element, member, itype, def) \
4701 do { \
4702 zval *z_arg = zend_hash_str_find(myht, element, sizeof(element) - 1); \
4703 if (z_arg && Z_TYPE_P(z_arg) <= IS_STRING) { \
4704 (*intobj)->diff->member = (itype)zval_get_long(z_arg); \
4705 } else { \
4706 (*intobj)->diff->member = (itype)def; \
4707 } \
4708 } while (0);
4709
4710#define PHP_DATE_INTERVAL_READ_PROPERTY_I64(element, member) \
4711 do { \
4712 zval *z_arg = zend_hash_str_find(myht, element, sizeof(element) - 1); \
4713 if (z_arg && Z_TYPE_P(z_arg) <= IS_STRING) { \
4714 zend_string *tmp_str; \
4715 zend_string *str = zval_get_tmp_string(z_arg, &tmp_str); \
4716 DATE_A64I((*intobj)->diff->member, ZSTR_VAL(str)); \
4717 zend_tmp_string_release(tmp_str); \
4718 } else { \
4719 (*intobj)->diff->member = -1LL; \
4720 } \
4721 } while (0);
4722
4723#define PHP_DATE_INTERVAL_READ_PROPERTY_DAYS(member) \
4724 do { \
4725 zval *z_arg = zend_hash_str_find(myht, "days", sizeof("days") - 1); \
4726 if (z_arg && Z_TYPE_P(z_arg) == IS_FALSE) { \
4727 (*intobj)->diff->member = TIMELIB_UNSET; \
4728 } else if (z_arg && Z_TYPE_P(z_arg) <= IS_STRING) { \
4729 zend_string *str = zval_get_string(z_arg); \
4730 DATE_A64I((*intobj)->diff->member, ZSTR_VAL(str)); \
4731 zend_string_release(str); \
4732 } else { \
4733 (*intobj)->diff->member = -1LL; \
4734 } \
4735 } while (0);
4736
4737#define PHP_DATE_INTERVAL_READ_PROPERTY_DOUBLE(element, member, def) \
4738 do { \
4739 zval *z_arg = zend_hash_str_find(myht, element, sizeof(element) - 1); \
4740 if (z_arg) { \
4741 (*intobj)->diff->member = (double)zval_get_double(z_arg); \
4742 } else { \
4743 (*intobj)->diff->member = (double)def; \
4744 } \
4745 } while (0);
4746
4753 {
4754 zval *z_arg = zend_hash_str_find(myht, "f", sizeof("f") - 1);
4755 if (z_arg) {
4756 (*intobj)->diff->us = zend_dval_to_lval(zval_get_double(z_arg) * 1000000.0);
4757 }
4758 }
4759 PHP_DATE_INTERVAL_READ_PROPERTY("weekday", weekday, int, -1)
4760 PHP_DATE_INTERVAL_READ_PROPERTY("weekday_behavior", weekday_behavior, int, -1)
4761 PHP_DATE_INTERVAL_READ_PROPERTY("first_last_day_of", first_last_day_of, int, -1)
4762 PHP_DATE_INTERVAL_READ_PROPERTY("invert", invert, int, 0);
4764 PHP_DATE_INTERVAL_READ_PROPERTY("special_type", special.type, unsigned int, 0);
4765 PHP_DATE_INTERVAL_READ_PROPERTY_I64("special_amount", special.amount);
4766 PHP_DATE_INTERVAL_READ_PROPERTY("have_weekday_relative", have_weekday_relative, unsigned int, 0);
4767 PHP_DATE_INTERVAL_READ_PROPERTY("have_special_relative", have_special_relative, unsigned int, 0);
4768 {
4769 zval *z_arg = zend_hash_str_find(myht, "civil_or_wall", sizeof("civil_or_wall") - 1);
4770 (*intobj)->civil_or_wall = PHP_DATE_CIVIL;
4771 if (z_arg) {
4772 zend_long val = zval_get_long(z_arg);
4773 (*intobj)->civil_or_wall = val;
4774 }
4775 }
4776
4777 (*intobj)->initialized = 1;
4778} /* }}} */
4779
4780/* {{{ */
4782{
4783 php_interval_obj *intobj;
4784 zval *array;
4785 HashTable *myht;
4786
4788 Z_PARAM_ARRAY(array)
4790
4791 myht = Z_ARRVAL_P(array);
4792
4793 php_date_instantiate(date_ce_interval, return_value);
4794 intobj = Z_PHPINTERVAL_P(return_value);
4795 php_date_interval_initialize_from_hash(&return_value, &intobj, myht);
4796}
4797/* }}} */
4798
4799/* {{{ */
4801{
4802 zval *object = ZEND_THIS;
4803 php_interval_obj *intervalobj;
4804 HashTable *myht;
4805
4807
4808 intervalobj = Z_PHPINTERVAL_P(object);
4809 DATE_CHECK_INITIALIZED(intervalobj->initialized, Z_OBJCE_P(object));
4810
4812 myht = Z_ARRVAL_P(return_value);
4813 date_interval_object_to_hash(intervalobj, myht);
4814
4815 add_common_properties(myht, &intervalobj->std);
4816}
4817/* }}} */
4818
4819static bool date_interval_is_internal_property(zend_string *name)
4820{
4821 if (
4822 zend_string_equals_literal(name, "date_string") ||
4823 zend_string_equals_literal(name, "from_string") ||
4831 zend_string_equals_literal(name, "invert") ||
4833 ) {
4834 return 1;
4835 }
4836 return 0;
4837}
4838
4839static void restore_custom_dateinterval_properties(zval *object, HashTable *myht)
4840{
4841 zend_string *prop_name;
4842 zval *prop_val;
4843
4844 ZEND_HASH_FOREACH_STR_KEY_VAL(myht, prop_name, prop_val) {
4845 if (!prop_name || (Z_TYPE_P(prop_val) == IS_REFERENCE) || date_interval_is_internal_property(prop_name)) {
4846 continue;
4847 }
4848 update_property(Z_OBJ_P(object), prop_name, prop_val);
4850}
4851
4852
4853/* {{{ */
4855{
4856 zval *object = ZEND_THIS;
4857 php_interval_obj *intervalobj;
4858 zval *array;
4859 HashTable *myht;
4860
4862 Z_PARAM_ARRAY(array)
4864
4865 intervalobj = Z_PHPINTERVAL_P(object);
4866 myht = Z_ARRVAL_P(array);
4867
4868 php_date_interval_initialize_from_hash(&object, &intervalobj, myht);
4869 restore_custom_dateinterval_properties(object, myht);
4870}
4871/* }}} */
4872
4873/* {{{ */
4875{
4876 zval *object = ZEND_THIS;
4877 php_interval_obj *intobj;
4878 HashTable *myht;
4879
4881
4882 intobj = Z_PHPINTERVAL_P(object);
4883
4884 myht = Z_OBJPROP_P(object);
4885
4886 php_date_interval_initialize_from_hash(&return_value, &intobj, myht);
4887}
4888/* }}} */
4889
4890static void date_interval_instantiate_from_time(zval *return_value, timelib_time *time, zend_string *time_str)
4891{
4892 php_interval_obj *diobj;
4893
4894 php_date_instantiate(date_ce_interval, return_value);
4896 diobj->diff = timelib_rel_time_clone(&time->relative);
4897 diobj->initialized = 1;
4899 diobj->from_string = true;
4900 diobj->date_string = zend_string_copy(time_str);
4901}
4902
4903/* {{{ Uses the normal date parsers and sets up a DateInterval from the relative parts of the parsed string */
4905{
4906 zend_string *time_str = NULL;
4909
4911 Z_PARAM_STR(time_str)
4913
4914 time = timelib_strtotime(ZSTR_VAL(time_str), ZSTR_LEN(time_str), &err, DATE_TIMEZONEDB, php_date_parse_tzfile_wrapper);
4915
4916 if (err->error_count > 0) {
4917 php_error_docref(NULL, E_WARNING, "Unknown or bad format (%s) at position %d (%c): %s", ZSTR_VAL(time_str),
4918 err->error_messages[0].position, err->error_messages[0].character ? err->error_messages[0].character : ' ', err->error_messages[0].message);
4920 goto cleanup;
4921 }
4922
4923 if (time->have_date || time->have_time || time->have_zone) {
4924 php_error_docref(NULL, E_WARNING, "String '%s' contains non-relative elements", ZSTR_VAL(time_str));
4926 goto cleanup;
4927 }
4928
4929 date_interval_instantiate_from_time(return_value, time, time_str);
4930
4931cleanup:
4934}
4935/* }}} */
4936
4937/* {{{ Uses the normal date parsers and sets up a DateInterval from the relative parts of the parsed string */
4938PHP_METHOD(DateInterval, createFromDateString)
4939{
4940 zend_string *time_str = NULL;
4943
4945 Z_PARAM_STR(time_str)
4947
4948 time = timelib_strtotime(ZSTR_VAL(time_str), ZSTR_LEN(time_str), &err, DATE_TIMEZONEDB, php_date_parse_tzfile_wrapper);
4949
4950 if (err->error_count > 0) {
4951 zend_throw_error(date_ce_date_malformed_interval_string_exception, "Unknown or bad format (%s) at position %d (%c): %s", ZSTR_VAL(time_str),
4952 err->error_messages[0].position, err->error_messages[0].character ? err->error_messages[0].character : ' ', err->error_messages[0].message);
4953 goto cleanup;
4954 }
4955
4956 if (time->have_date || time->have_time || time->have_zone) {
4957 zend_throw_error(date_ce_date_malformed_interval_string_exception, "String '%s' contains non-relative elements", ZSTR_VAL(time_str));
4958 goto cleanup;
4959 }
4960
4961 date_interval_instantiate_from_time(return_value, time, time_str);
4962
4963cleanup:
4966}
4967/* }}} */
4968
4969/* {{{ date_interval_format - */
4970static zend_string *date_interval_format(char *format, size_t format_len, timelib_rel_time *t)
4971{
4972 smart_str string = {0};
4973 size_t i;
4974 int length, have_format_spec = 0;
4975 char buffer[33];
4976
4977 if (!format_len) {
4978 return ZSTR_EMPTY_ALLOC();
4979 }
4980
4981 for (i = 0; i < format_len; i++) {
4982 if (have_format_spec) {
4983 switch (format[i]) {
4984 case 'Y': length = slprintf(buffer, sizeof(buffer), "%02d", (int) t->y); break;
4985 case 'y': length = slprintf(buffer, sizeof(buffer), "%d", (int) t->y); break;
4986
4987 case 'M': length = slprintf(buffer, sizeof(buffer), "%02d", (int) t->m); break;
4988 case 'm': length = slprintf(buffer, sizeof(buffer), "%d", (int) t->m); break;
4989
4990 case 'D': length = slprintf(buffer, sizeof(buffer), "%02d", (int) t->d); break;
4991 case 'd': length = slprintf(buffer, sizeof(buffer), "%d", (int) t->d); break;
4992
4993 case 'H': length = slprintf(buffer, sizeof(buffer), "%02d", (int) t->h); break;
4994 case 'h': length = slprintf(buffer, sizeof(buffer), "%d", (int) t->h); break;
4995
4996 case 'I': length = slprintf(buffer, sizeof(buffer), "%02d", (int) t->i); break;
4997 case 'i': length = slprintf(buffer, sizeof(buffer), "%d", (int) t->i); break;
4998
4999 case 'S': length = slprintf(buffer, sizeof(buffer), "%02" ZEND_LONG_FMT_SPEC, (zend_long) t->s); break;
5000 case 's': length = slprintf(buffer, sizeof(buffer), ZEND_LONG_FMT, (zend_long) t->s); break;
5001
5002 case 'F': length = slprintf(buffer, sizeof(buffer), "%06" ZEND_LONG_FMT_SPEC, (zend_long) t->us); break;
5003 case 'f': length = slprintf(buffer, sizeof(buffer), ZEND_LONG_FMT, (zend_long) t->us); break;
5004
5005 case 'a': {
5006 if ((int) t->days != TIMELIB_UNSET) {
5007 length = slprintf(buffer, sizeof(buffer), "%d", (int) t->days);
5008 } else {
5009 length = slprintf(buffer, sizeof(buffer), "(unknown)");
5010 }
5011 } break;
5012 case 'r': length = slprintf(buffer, sizeof(buffer), "%s", t->invert ? "-" : ""); break;
5013 case 'R': length = slprintf(buffer, sizeof(buffer), "%c", t->invert ? '-' : '+'); break;
5014
5015 case '%': length = slprintf(buffer, sizeof(buffer), "%%"); break;
5016 default: buffer[0] = '%'; buffer[1] = format[i]; buffer[2] = '\0'; length = 2; break;
5017 }
5018 smart_str_appendl(&string, buffer, length);
5019 have_format_spec = 0;
5020 } else {
5021 if (format[i] == '%') {
5022 have_format_spec = 1;
5023 } else {
5024 smart_str_appendc(&string, format[i]);
5025 }
5026 }
5027 }
5028
5029 smart_str_0(&string);
5030
5031 if (string.s == NULL) {
5032 return ZSTR_EMPTY_ALLOC();
5033 }
5034
5035 return string.s;
5036}
5037/* }}} */
5038
5039/* {{{ Formats the interval. */
5040PHP_FUNCTION(date_interval_format)
5041{
5042 zval *object;
5043 php_interval_obj *diobj;
5044 char *format;
5045 size_t format_len;
5046
5047 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Os", &object, date_ce_interval, &format, &format_len) == FAILURE) {
5048 RETURN_THROWS();
5049 }
5050 diobj = Z_PHPINTERVAL_P(object);
5052
5053 RETURN_STR(date_interval_format(format, format_len, diobj->diff));
5054}
5055/* }}} */
5056
5057static bool date_period_initialize(timelib_time **st, timelib_time **et, timelib_rel_time **d, zend_long *recurrences, /*const*/ char *format, size_t format_length) /* {{{ */
5058{
5059 timelib_time *b = NULL, *e = NULL;
5061 int r = 0;
5063 bool retval = false;
5064
5065 timelib_strtointerval(format, format_length, &b, &e, &p, &r, &errors);
5066
5067 if (errors->error_count > 0) {
5068 retval = false;
5069 zend_throw_exception_ex(date_ce_date_malformed_period_string_exception, 0, "Unknown or bad format (%s)", format);
5070 if (b) {
5072 }
5073 if (e) {
5075 }
5076 if (p) {
5078 }
5079 } else {
5080 *st = b;
5081 *et = e;
5082 *d = p;
5083 *recurrences = r;
5084 retval = true;
5085 }
5087 return retval;
5088} /* }}} */
5089
5090static bool date_period_init_iso8601_string(php_period_obj *dpobj, zend_class_entry* base_ce, char *isostr, size_t isostr_len, zend_long options, zend_long *recurrences)
5091{
5092 if (!date_period_initialize(&(dpobj->start), &(dpobj->end), &(dpobj->interval), recurrences, isostr, isostr_len)) {
5093 return false;
5094 }
5095
5096 if (dpobj->start == NULL) {
5098 zend_throw_exception_ex(date_ce_date_malformed_period_string_exception, 0, "%s(): ISO interval must contain a start date, \"%s\" given", ZSTR_VAL(func), isostr);
5099 zend_string_release(func);
5100 return false;
5101 }
5102 if (dpobj->interval == NULL) {
5104 zend_throw_exception_ex(date_ce_date_malformed_period_string_exception, 0, "%s(): ISO interval must contain an interval, \"%s\" given", ZSTR_VAL(func), isostr);
5105 zend_string_release(func);
5106 return false;
5107 }
5108 if (dpobj->end == NULL && recurrences == 0) {
5110 zend_throw_exception_ex(date_ce_date_malformed_period_string_exception, 0, "%s(): ISO interval must contain an end date or a recurrence count, \"%s\" given", ZSTR_VAL(func), isostr);
5111 zend_string_release(func);
5112 return false;
5113 }
5114
5115 if (dpobj->start) {
5116 timelib_update_ts(dpobj->start, NULL);
5117 }
5118 if (dpobj->end) {
5119 timelib_update_ts(dpobj->end, NULL);
5120 }
5121 dpobj->start_ce = base_ce;
5122
5123 return true;
5124}
5125
5126static bool date_period_init_finish(php_period_obj *dpobj, zend_long options, zend_long recurrences)
5127{
5128 const zend_long max_recurrences = (INT_MAX - 8);
5129
5130 if (dpobj->end == NULL && (recurrences < 1 || recurrences > max_recurrences)) {
5132 zend_throw_exception_ex(date_ce_date_malformed_period_string_exception, 0, "%s(): Recurrence count must be greater or equal to 1 and lower than " ZEND_LONG_FMT, ZSTR_VAL(func), max_recurrences + 1);
5133 zend_string_release(func);
5134 return false;
5135 }
5136
5137 /* options */
5140
5141 /* recurrences */
5142 recurrences += dpobj->include_start_date + dpobj->include_end_date;
5143
5144 if (UNEXPECTED(recurrences > max_recurrences)) {
5146 zend_throw_exception_ex(date_ce_date_malformed_string_exception, 0, "%s(): Recurrence count must be greater or equal to 1 and lower than " ZEND_LONG_FMT " (including options)", ZSTR_VAL(func), max_recurrences + 1);
5147 zend_string_release(func);
5148 return false;
5149 }
5150
5151 dpobj->recurrences = (int)recurrences;
5152
5153 dpobj->initialized = 1;
5154
5155 initialize_date_period_properties(dpobj);
5156
5157 return true;
5158}
5159
5160PHP_METHOD(DatePeriod, createFromISO8601String)
5161{
5162 php_period_obj *dpobj;
5163 zend_long recurrences = 0, options = 0;
5164 char *isostr = NULL;
5165 size_t isostr_len = 0;
5166
5168 Z_PARAM_STRING(isostr, isostr_len)
5172
5173 object_init_ex(return_value, execute_data->This.value.ce ? execute_data->This.value.ce : date_ce_period);
5174 dpobj = Z_PHPPERIOD_P(return_value);
5175
5176 dpobj->current = NULL;
5177
5178 if (!date_period_init_iso8601_string(dpobj, date_ce_immutable, isostr, isostr_len, options, &recurrences)) {
5179 RETURN_THROWS();
5180 }
5181
5182 if (!date_period_init_finish(dpobj, options, recurrences)) {
5183 RETURN_THROWS();
5184 }
5185}
5186
5187/* {{{ Creates new DatePeriod object. */
5189{
5190 php_period_obj *dpobj;
5192 zval *start, *end = NULL, *interval;
5193 zend_long recurrences = 0, options = 0;
5194 char *isostr = NULL;
5195 size_t isostr_len = 0;
5196 timelib_time *clone;
5197
5198 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) {
5199 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) {
5200 if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), "s|l", &isostr, &isostr_len, &options) == FAILURE) {
5201 zend_type_error("DatePeriod::__construct() accepts (DateTimeInterface, DateInterval, int [, int]), or (DateTimeInterface, DateInterval, DateTime [, int]), or (string [, int]) as arguments");
5202 RETURN_THROWS();
5203 }
5204 }
5205 }
5206
5207 dpobj = Z_PHPPERIOD_P(ZEND_THIS);
5208 dpobj->current = NULL;
5209
5210 if (isostr) {
5211 zend_error(E_DEPRECATED, "Calling DatePeriod::__construct(string $isostr, int $options = 0) is deprecated, "
5212 "use DatePeriod::createFromISO8601String() instead");
5213 if (UNEXPECTED(EG(exception))) {
5214 RETURN_THROWS();
5215 }
5216
5217 if (!date_period_init_iso8601_string(dpobj, date_ce_date, isostr, isostr_len, options, &recurrences)) {
5218 RETURN_THROWS();
5219 }
5220 } else {
5221 /* check initialisation */
5222 DATE_CHECK_INITIALIZED(Z_PHPDATE_P(start)->time, date_ce_interface);
5223 if (end) {
5224 DATE_CHECK_INITIALIZED(Z_PHPDATE_P(end)->time, date_ce_interface);
5225 }
5226
5227 /* init */
5228 php_interval_obj *intobj = Z_PHPINTERVAL_P(interval);
5229
5230 /* start date */
5232 clone = timelib_time_ctor();
5233 memcpy(clone, dateobj->time, sizeof(timelib_time));
5234 if (dateobj->time->tz_abbr) {
5235 clone->tz_abbr = timelib_strdup(dateobj->time->tz_abbr);
5236 }
5237 if (dateobj->time->tz_info) {
5238 clone->tz_info = dateobj->time->tz_info;
5239 }
5240 dpobj->start = clone;
5241 dpobj->start_ce = Z_OBJCE_P(start);
5242
5243 /* interval */
5244 dpobj->interval = timelib_rel_time_clone(intobj->diff);
5245
5246 /* end date */
5247 if (end) {
5249 clone = timelib_time_clone(dateobj->time);
5250 dpobj->end = clone;
5251 }
5252 }
5253
5254 if (!date_period_init_finish(dpobj, options, recurrences)) {
5255 RETURN_THROWS();
5256 }
5257}
5258/* }}} */
5259
5260/* {{{ Get start date. */
5262{
5263 php_period_obj *dpobj;
5265
5267
5268 dpobj = Z_PHPPERIOD_P(ZEND_THIS);
5270
5273 dateobj->time = timelib_time_ctor();
5274 *dateobj->time = *dpobj->start;
5275 if (dpobj->start->tz_abbr) {
5276 dateobj->time->tz_abbr = timelib_strdup(dpobj->start->tz_abbr);
5277 }
5278 if (dpobj->start->tz_info) {
5279 dateobj->time->tz_info = dpobj->start->tz_info;
5280 }
5281}
5282/* }}} */
5283
5284/* {{{ Get end date. */
5286{
5287 php_period_obj *dpobj;
5289
5291
5292 dpobj = Z_PHPPERIOD_P(ZEND_THIS);
5293
5294 if (!dpobj->end) {
5295 return;
5296 }
5297
5300 dateobj->time = timelib_time_ctor();
5301 *dateobj->time = *dpobj->end;
5302 if (dpobj->end->tz_abbr) {
5303 dateobj->time->tz_abbr = timelib_strdup(dpobj->end->tz_abbr);
5304 }
5305 if (dpobj->end->tz_info) {
5306 dateobj->time->tz_info = dpobj->end->tz_info;
5307 }
5308}
5309/* }}} */
5310
5311/* {{{ Get date interval. */
5312PHP_METHOD(DatePeriod, getDateInterval)
5313{
5314 php_period_obj *dpobj;
5315 php_interval_obj *diobj;
5316
5318
5319 dpobj = Z_PHPPERIOD_P(ZEND_THIS);
5321
5322 php_date_instantiate(date_ce_interval, return_value);
5324 diobj->diff = timelib_rel_time_clone(dpobj->interval);
5325 diobj->initialized = 1;
5326}
5327/* }}} */
5328
5329/* {{{ Get recurrences. */
5330PHP_METHOD(DatePeriod, getRecurrences)
5331{
5332 php_period_obj *dpobj;
5333
5335
5336 dpobj = Z_PHPPERIOD_P(ZEND_THIS);
5337
5338 if (0 == dpobj->recurrences - dpobj->include_start_date - dpobj->include_end_date) {
5339 return;
5340 }
5341
5343}
5344/* }}} */
5345
5352
5353static int check_id_allowed(char *id, zend_long what) /* {{{ */
5354{
5355 if ((what & PHP_DATE_TIMEZONE_GROUP_AFRICA) && strncasecmp(id, "Africa/", 7) == 0) return 1;
5356 if ((what & PHP_DATE_TIMEZONE_GROUP_AMERICA) && strncasecmp(id, "America/", 8) == 0) return 1;
5357 if ((what & PHP_DATE_TIMEZONE_GROUP_ANTARCTICA) && strncasecmp(id, "Antarctica/", 11) == 0) return 1;
5358 if ((what & PHP_DATE_TIMEZONE_GROUP_ARCTIC) && strncasecmp(id, "Arctic/", 7) == 0) return 1;
5359 if ((what & PHP_DATE_TIMEZONE_GROUP_ASIA) && strncasecmp(id, "Asia/", 5) == 0) return 1;
5360 if ((what & PHP_DATE_TIMEZONE_GROUP_ATLANTIC) && strncasecmp(id, "Atlantic/", 9) == 0) return 1;
5361 if ((what & PHP_DATE_TIMEZONE_GROUP_AUSTRALIA) && strncasecmp(id, "Australia/", 10) == 0) return 1;
5362 if ((what & PHP_DATE_TIMEZONE_GROUP_EUROPE) && strncasecmp(id, "Europe/", 7) == 0) return 1;
5363 if ((what & PHP_DATE_TIMEZONE_GROUP_INDIAN) && strncasecmp(id, "Indian/", 7) == 0) return 1;
5364 if ((what & PHP_DATE_TIMEZONE_GROUP_PACIFIC) && strncasecmp(id, "Pacific/", 8) == 0) return 1;
5365 if ((what & PHP_DATE_TIMEZONE_GROUP_UTC) && strncasecmp(id, "UTC", 3) == 0) return 1;
5366 return 0;
5367} /* }}} */
5368
5369/* {{{ Returns numerically index array with all timezone identifiers. */
5371{
5372 const timelib_tzdb *tzdb;
5373 const timelib_tzdb_index_entry *table;
5374 int i, item_count;
5376 char *option = NULL;
5377 size_t option_len = 0;
5378
5381 Z_PARAM_LONG(what)
5382 Z_PARAM_STRING_OR_NULL(option, option_len)
5384
5385 /* Extra validation */
5386 if (what == PHP_DATE_TIMEZONE_PER_COUNTRY && option_len != 2) {
5387 zend_argument_value_error(2, "must be a two-letter ISO 3166-1 compatible country code "
5388 "when argument #1 ($timezoneGroup) is DateTimeZone::PER_COUNTRY");
5389 RETURN_THROWS();
5390 }
5391
5392 tzdb = DATE_TIMEZONEDB;
5393 table = timelib_timezone_identifiers_list((timelib_tzdb*) tzdb, &item_count);
5394
5396
5397 for (i = 0; i < item_count; ++i) {
5398 if (what == PHP_DATE_TIMEZONE_PER_COUNTRY) {
5399 if (tzdb->data[table[i].pos + 5] == option[0] && tzdb->data[table[i].pos + 6] == option[1]) {
5400 add_next_index_string(return_value, table[i].id);
5401 }
5402 } else if (what == PHP_DATE_TIMEZONE_GROUP_ALL_W_BC || (check_id_allowed(table[i].id, what) && (tzdb->data[table[i].pos + 4] == '\1'))) {
5403 add_next_index_string(return_value, table[i].id);
5404 }
5405 };
5406}
5407/* }}} */
5408
5409/* {{{ Returns the Olson database version number. */
5411{
5412 const timelib_tzdb *tzdb;
5413
5415
5416 tzdb = DATE_TIMEZONEDB;
5417 RETURN_STRING(tzdb->version);
5418}
5419/* }}} */
5420
5421/* {{{ Returns associative array containing dst, offset and the timezone name */
5423{
5424 const timelib_tz_lookup_table *table, *entry;
5425 zval element, *abbr_array_p, abbr_array;
5426
5428
5431 entry = table;
5432
5433 do {
5434 array_init(&element);
5435 add_assoc_bool_ex(&element, "dst", sizeof("dst") -1, entry->type);
5436 add_assoc_long_ex(&element, "offset", sizeof("offset") - 1, entry->gmtoffset);
5437 if (entry->full_tz_name) {
5438 add_assoc_string_ex(&element, "timezone_id", sizeof("timezone_id") - 1, entry->full_tz_name);
5439 } else {
5440 add_assoc_null_ex(&element, "timezone_id", sizeof("timezone_id") - 1);
5441 }
5442
5443 abbr_array_p = zend_hash_str_find(Z_ARRVAL_P(return_value), entry->name, strlen(entry->name));
5444 if (!abbr_array_p) {
5445 array_init(&abbr_array);
5446 add_assoc_zval(return_value, entry->name, &abbr_array);
5447 } else {
5448 ZVAL_COPY_VALUE(&abbr_array, abbr_array_p);
5449 }
5450 add_next_index_zval(&abbr_array, &element);
5451 entry++;
5452 } while (entry->name);
5453}
5454/* }}} */
5455
5456/* {{{ Sets the default timezone used by all date/time functions in a script */
5458{
5459 char *zone;
5460 size_t zone_len;
5461
5463 Z_PARAM_STRING(zone, zone_len)
5465
5467 php_error_docref(NULL, E_NOTICE, "Timezone ID '%s' is invalid", zone);
5469 }
5470 if (DATEG(timezone)) {
5472 DATEG(timezone) = NULL;
5473 }
5474 DATEG(timezone) = estrndup(zone, zone_len);
5476}
5477/* }}} */
5478
5479/* {{{ Gets the default timezone used by all date/time functions in a script */
5481{
5482 timelib_tzinfo *default_tz;
5484
5485 default_tz = get_timezone_info();
5486 if (!default_tz) {
5487 RETURN_THROWS();
5488 }
5489 RETVAL_STRING(default_tz->name);
5490}
5491/* }}} */
5492
5493/* {{{ php_do_date_sunrise_sunset
5494 * Common for date_sunrise() and date_sunset() functions
5495 */
5496static void php_do_date_sunrise_sunset(INTERNAL_FUNCTION_PARAMETERS, bool calc_sunset)
5497{
5498 double latitude, longitude, zenith, gmt_offset, altitude;
5499 bool latitude_is_null = 1, longitude_is_null = 1, zenith_is_null = 1, gmt_offset_is_null = 1;
5500 double h_rise, h_set, N;
5501 timelib_sll rise, set, transit;
5502 zend_long time, retformat = SUNFUNCS_RET_STRING;
5503 int rs;
5504 timelib_time *t;
5505 timelib_tzinfo *tzi;
5506 zend_string *retstr;
5507
5511 Z_PARAM_LONG(retformat)
5512 Z_PARAM_DOUBLE_OR_NULL(latitude, latitude_is_null)
5513 Z_PARAM_DOUBLE_OR_NULL(longitude, longitude_is_null)
5514 Z_PARAM_DOUBLE_OR_NULL(zenith, zenith_is_null)
5515 Z_PARAM_DOUBLE_OR_NULL(gmt_offset, gmt_offset_is_null)
5517
5518 if (latitude_is_null) {
5519 latitude = INI_FLT("date.default_latitude");
5520 }
5521
5522 if (longitude_is_null) {
5523 longitude = INI_FLT("date.default_longitude");
5524 }
5525
5526 if (zenith_is_null) {
5527 if (calc_sunset) {
5528 zenith = INI_FLT("date.sunset_zenith");
5529 } else {
5530 zenith = INI_FLT("date.sunrise_zenith");
5531 }
5532 }
5533
5534 if (retformat != SUNFUNCS_RET_TIMESTAMP &&
5535 retformat != SUNFUNCS_RET_STRING &&
5536 retformat != SUNFUNCS_RET_DOUBLE)
5537 {
5538 zend_argument_value_error(2, "must be one of SUNFUNCS_RET_TIMESTAMP, SUNFUNCS_RET_STRING, or SUNFUNCS_RET_DOUBLE");
5539 RETURN_THROWS();
5540 }
5541 altitude = 90 - zenith;
5542
5543 if (!zend_finite(latitude) || !zend_finite(longitude)) {
5545 }
5546
5547 /* Initialize time struct */
5548 tzi = get_timezone_info();
5549 if (!tzi) {
5550 RETURN_THROWS();
5551 }
5552 t = timelib_time_ctor();
5553 t->tz_info = tzi;
5555
5556 if (gmt_offset_is_null) {
5557 gmt_offset = timelib_get_current_offset(t) / 3600;
5558 }
5559
5561 rs = timelib_astro_rise_set_altitude(t, longitude, latitude, altitude, 1, &h_rise, &h_set, &rise, &set, &transit);
5563
5564 if (rs != 0) {
5566 }
5567
5568 if (retformat == SUNFUNCS_RET_TIMESTAMP) {
5569 RETURN_LONG(calc_sunset ? set : rise);
5570 }
5571 N = (calc_sunset ? h_set : h_rise) + gmt_offset;
5572
5573 if (N > 24 || N < 0) {
5574 N -= floor(N / 24) * 24;
5575 }
5576 if (!(N <= 24 && N >= 0)) {
5578 }
5579
5580 switch (retformat) {
5582 retstr = strpprintf(0, "%02d:%02d", (int) N, (int) (60 * (N - (int) N)));
5583 RETURN_NEW_STR(retstr);
5584 break;
5587 break;
5588 }
5589}
5590/* }}} */
5591
5592/* {{{ Returns time of sunrise for a given day and location */
5594{
5595 php_do_date_sunrise_sunset(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
5596}
5597/* }}} */
5598
5599/* {{{ Returns time of sunset for a given day and location */
5601{
5602 php_do_date_sunrise_sunset(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
5603}
5604/* }}} */
5605
5606/* {{{ Returns an array with information about sun set/rise and twilight begin/end */
5608{
5610 double latitude, longitude;
5611 timelib_time *t, *t2;
5612 timelib_tzinfo *tzi;
5613 int rs;
5614 timelib_sll rise, set, transit;
5615 int dummy;
5616 double ddummy;
5617
5620 Z_PARAM_DOUBLE(latitude)
5621 Z_PARAM_DOUBLE(longitude)
5623
5624 if (!zend_finite(latitude)) {
5625 zend_argument_value_error(2, "must be finite");
5626 RETURN_THROWS();
5627 }
5628 if (!zend_finite(longitude)) {
5629 zend_argument_value_error(3, "must be finite");
5630 RETURN_THROWS();
5631 }
5632
5633 /* Initialize time struct */
5634 tzi = get_timezone_info();
5635 if (!tzi) {
5636 RETURN_THROWS();
5637 }
5638 t = timelib_time_ctor();
5639 t->tz_info = tzi;
5642
5643 /* Setup */
5646
5647 /* Get sun up/down and transit */
5648 rs = timelib_astro_rise_set_altitude(t, longitude, latitude, -35.0/60, 1, &ddummy, &ddummy, &rise, &set, &transit);
5649 switch (rs) {
5650 case -1: /* always below */
5651 add_assoc_bool(return_value, "sunrise", 0);
5652 add_assoc_bool(return_value, "sunset", 0);
5653 break;
5654 case 1: /* always above */
5655 add_assoc_bool(return_value, "sunrise", 1);
5656 add_assoc_bool(return_value, "sunset", 1);
5657 break;
5658 default:
5659 t2->sse = rise;
5660 add_assoc_long(return_value, "sunrise", timelib_date_to_int(t2, &dummy));
5661 t2->sse = set;
5662 add_assoc_long(return_value, "sunset", timelib_date_to_int(t2, &dummy));
5663 }
5664 t2->sse = transit;
5665 add_assoc_long(return_value, "transit", timelib_date_to_int(t2, &dummy));
5666
5667 /* Get civil twilight */
5668 rs = timelib_astro_rise_set_altitude(t, longitude, latitude, -6.0, 0, &ddummy, &ddummy, &rise, &set, &transit);
5669 switch (rs) {
5670 case -1: /* always below */
5671 add_assoc_bool(return_value, "civil_twilight_begin", 0);
5672 add_assoc_bool(return_value, "civil_twilight_end", 0);
5673 break;
5674 case 1: /* always above */
5675 add_assoc_bool(return_value, "civil_twilight_begin", 1);
5676 add_assoc_bool(return_value, "civil_twilight_end", 1);
5677 break;
5678 default:
5679 t2->sse = rise;
5680 add_assoc_long(return_value, "civil_twilight_begin", timelib_date_to_int(t2, &dummy));
5681 t2->sse = set;
5682 add_assoc_long(return_value, "civil_twilight_end", timelib_date_to_int(t2, &dummy));
5683 }
5684
5685 /* Get nautical twilight */
5686 rs = timelib_astro_rise_set_altitude(t, longitude, latitude, -12.0, 0, &ddummy, &ddummy, &rise, &set, &transit);
5687 switch (rs) {
5688 case -1: /* always below */
5689 add_assoc_bool(return_value, "nautical_twilight_begin", 0);
5690 add_assoc_bool(return_value, "nautical_twilight_end", 0);
5691 break;
5692 case 1: /* always above */
5693 add_assoc_bool(return_value, "nautical_twilight_begin", 1);
5694 add_assoc_bool(return_value, "nautical_twilight_end", 1);
5695 break;
5696 default:
5697 t2->sse = rise;
5698 add_assoc_long(return_value, "nautical_twilight_begin", timelib_date_to_int(t2, &dummy));
5699 t2->sse = set;
5700 add_assoc_long(return_value, "nautical_twilight_end", timelib_date_to_int(t2, &dummy));
5701 }
5702
5703 /* Get astronomical twilight */
5704 rs = timelib_astro_rise_set_altitude(t, longitude, latitude, -18.0, 0, &ddummy, &ddummy, &rise, &set, &transit);
5705 switch (rs) {
5706 case -1: /* always below */
5707 add_assoc_bool(return_value, "astronomical_twilight_begin", 0);
5708 add_assoc_bool(return_value, "astronomical_twilight_end", 0);
5709 break;
5710 case 1: /* always above */
5711 add_assoc_bool(return_value, "astronomical_twilight_begin", 1);
5712 add_assoc_bool(return_value, "astronomical_twilight_end", 1);
5713 break;
5714 default:
5715 t2->sse = rise;
5716 add_assoc_long(return_value, "astronomical_twilight_begin", timelib_date_to_int(t2, &dummy));
5717 t2->sse = set;
5718 add_assoc_long(return_value, "astronomical_twilight_end", timelib_date_to_int(t2, &dummy));
5719 }
5722}
5723/* }}} */
5724
5725static HashTable *date_object_get_gc_period(zend_object *object, zval **table, int *n) /* {{{ */
5726{
5727 *table = NULL;
5728 *n = 0;
5729 return zend_std_get_properties(object);
5730} /* }}} */
5731
5732static void date_period_object_to_hash(php_period_obj *period_obj, HashTable *props)
5733{
5734 zval zv;
5735
5736 create_date_period_datetime(period_obj->start, period_obj->start_ce, &zv);
5737 zend_hash_str_update(props, "start", sizeof("start")-1, &zv);
5738
5739 create_date_period_datetime(period_obj->current, period_obj->start_ce, &zv);
5740 zend_hash_str_update(props, "current", sizeof("current")-1, &zv);
5741
5742 create_date_period_datetime(period_obj->end, period_obj->start_ce, &zv);
5743 zend_hash_str_update(props, "end", sizeof("end")-1, &zv);
5744
5745 create_date_period_interval(period_obj->interval, &zv);
5746 zend_hash_str_update(props, "interval", sizeof("interval")-1, &zv);
5747
5748 /* converted to larger type (int->long); must check when unserializing */
5749 ZVAL_LONG(&zv, (zend_long) period_obj->recurrences);
5750 zend_hash_str_update(props, "recurrences", sizeof("recurrences")-1, &zv);
5751
5752 ZVAL_BOOL(&zv, period_obj->include_start_date);
5753 zend_hash_str_update(props, "include_start_date", sizeof("include_start_date")-1, &zv);
5754
5755 ZVAL_BOOL(&zv, period_obj->include_end_date);
5756 zend_hash_str_update(props, "include_end_date", sizeof("include_end_date")-1, &zv);
5757}
5758
5759static bool php_date_period_initialize_from_hash(php_period_obj *period_obj, HashTable *myht) /* {{{ */
5760{
5761 zval *ht_entry;
5762
5763 /* this function does no rollback on error */
5764
5765 ht_entry = zend_hash_str_find(myht, "start", sizeof("start")-1);
5766 if (ht_entry) {
5767 if (Z_TYPE_P(ht_entry) == IS_OBJECT && instanceof_function(Z_OBJCE_P(ht_entry), date_ce_interface)) {
5768 php_date_obj *date_obj;
5769 date_obj = Z_PHPDATE_P(ht_entry);
5770
5771 if (!date_obj->time) {
5772 return 0;
5773 }
5774
5775 if (period_obj->start != NULL) {
5776 timelib_time_dtor(period_obj->start);
5777 }
5778 period_obj->start = timelib_time_clone(date_obj->time);
5779 period_obj->start_ce = Z_OBJCE_P(ht_entry);
5780 } else if (Z_TYPE_P(ht_entry) != IS_NULL) {
5781 return 0;
5782 }
5783 } else {
5784 return 0;
5785 }
5786
5787 ht_entry = zend_hash_str_find(myht, "end", sizeof("end")-1);
5788 if (ht_entry) {
5789 if (Z_TYPE_P(ht_entry) == IS_OBJECT && instanceof_function(Z_OBJCE_P(ht_entry), date_ce_interface)) {
5790 php_date_obj *date_obj;
5791 date_obj = Z_PHPDATE_P(ht_entry);
5792
5793 if (!date_obj->time) {
5794 return 0;
5795 }
5796
5797 if (period_obj->end != NULL) {
5798 timelib_time_dtor(period_obj->end);
5799 }
5800 period_obj->end = timelib_time_clone(date_obj->time);
5801 } else if (Z_TYPE_P(ht_entry) != IS_NULL) {
5802 return 0;
5803 }
5804 } else {
5805 return 0;
5806 }
5807
5808 ht_entry = zend_hash_str_find(myht, "current", sizeof("current")-1);
5809 if (ht_entry) {
5810 if (Z_TYPE_P(ht_entry) == IS_OBJECT && instanceof_function(Z_OBJCE_P(ht_entry), date_ce_interface)) {
5811 php_date_obj *date_obj;
5812 date_obj = Z_PHPDATE_P(ht_entry);
5813
5814 if (!date_obj->time) {
5815 return 0;
5816 }
5817
5818 if (period_obj->current != NULL) {
5819 timelib_time_dtor(period_obj->current);
5820 }
5821 period_obj->current = timelib_time_clone(date_obj->time);
5822 } else if (Z_TYPE_P(ht_entry) != IS_NULL) {
5823 return 0;
5824 }
5825 } else {
5826 return 0;
5827 }
5828
5829 ht_entry = zend_hash_str_find(myht, "interval", sizeof("interval")-1);
5830 if (ht_entry) {
5831 if (Z_TYPE_P(ht_entry) == IS_OBJECT && Z_OBJCE_P(ht_entry) == date_ce_interval) {
5832 php_interval_obj *interval_obj;
5833 interval_obj = Z_PHPINTERVAL_P(ht_entry);
5834
5835 if (!interval_obj->initialized) {
5836 return 0;
5837 }
5838
5839 if (period_obj->interval != NULL) {
5840 timelib_rel_time_dtor(period_obj->interval);
5841 }
5842 period_obj->interval = timelib_rel_time_clone(interval_obj->diff);
5843 } else { /* interval is required */
5844 return 0;
5845 }
5846 } else {
5847 return 0;
5848 }
5849
5850 ht_entry = zend_hash_str_find(myht, "recurrences", sizeof("recurrences")-1);
5851 if (ht_entry &&
5852 Z_TYPE_P(ht_entry) == IS_LONG && Z_LVAL_P(ht_entry) >= 0 && Z_LVAL_P(ht_entry) <= INT_MAX) {
5853 period_obj->recurrences = Z_LVAL_P(ht_entry);
5854 } else {
5855 return 0;
5856 }
5857
5858 ht_entry = zend_hash_str_find(myht, "include_start_date", sizeof("include_start_date")-1);
5859 if (ht_entry &&
5860 (Z_TYPE_P(ht_entry) == IS_FALSE || Z_TYPE_P(ht_entry) == IS_TRUE)) {
5861 period_obj->include_start_date = (Z_TYPE_P(ht_entry) == IS_TRUE);
5862 } else {
5863 return 0;
5864 }
5865
5866 ht_entry = zend_hash_str_find(myht, "include_end_date", sizeof("include_end_date")-1);
5867 if (ht_entry &&
5868 (Z_TYPE_P(ht_entry) == IS_FALSE || Z_TYPE_P(ht_entry) == IS_TRUE)) {
5869 period_obj->include_end_date = (Z_TYPE_P(ht_entry) == IS_TRUE);
5870 } else {
5871 return 0;
5872 }
5873
5874 period_obj->initialized = 1;
5875
5876 initialize_date_period_properties(period_obj);
5877
5878 return 1;
5879} /* }}} */
5880
5881/* {{{ */
5883{
5884 php_period_obj *period_obj;
5885 zval *array;
5886 HashTable *myht;
5887
5889 Z_PARAM_ARRAY(array)
5891
5892 myht = Z_ARRVAL_P(array);
5893
5894 object_init_ex(return_value, date_ce_period);
5895 period_obj = Z_PHPPERIOD_P(return_value);
5896 if (!php_date_period_initialize_from_hash(period_obj, myht)) {
5897 zend_throw_error(NULL, "Invalid serialization data for DatePeriod object");
5898 RETURN_THROWS();
5899 }
5900}
5901/* }}} */
5902
5903/* {{{ */
5905{
5906 zval *object = ZEND_THIS;
5907 php_period_obj *period_obj;
5908 HashTable *myht;
5909
5911
5912 period_obj = Z_PHPPERIOD_P(object);
5913 DATE_CHECK_INITIALIZED(period_obj->start, Z_OBJCE_P(object));
5914
5916 myht = Z_ARRVAL_P(return_value);
5917 date_period_object_to_hash(period_obj, myht);
5918
5919 add_common_properties(myht, &period_obj->std);
5920}
5921/* }}} */
5922
5923/* {{{ date_period_is_internal_property
5924 * Common for date_period_read_property(), date_period_write_property(), and
5925 * restore_custom_dateperiod_properties functions
5926 */
5927static bool date_period_is_internal_property(zend_string *name)
5928{
5929 if (
5930 zend_string_equals_literal(name, "start") ||
5931 zend_string_equals_literal(name, "current") ||
5933 zend_string_equals_literal(name, "interval") ||
5934 zend_string_equals_literal(name, "recurrences") ||
5935 zend_string_equals_literal(name, "include_start_date") ||
5936 zend_string_equals_literal(name, "include_end_date")
5937 ) {
5938 return 1;
5939 }
5940 return 0;
5941}
5942/* }}} */
5943
5944static void restore_custom_dateperiod_properties(zval *object, HashTable *myht)
5945{
5946 zend_string *prop_name;
5947 zval *prop_val;
5948
5949 ZEND_HASH_FOREACH_STR_KEY_VAL(myht, prop_name, prop_val) {
5950 if (!prop_name || (Z_TYPE_P(prop_val) == IS_REFERENCE) || date_period_is_internal_property(prop_name)) {
5951 continue;
5952 }
5953 update_property(Z_OBJ_P(object), prop_name, prop_val);
5955}
5956
5957/* {{{ */
5958PHP_METHOD(DatePeriod, __unserialize)
5959{
5960 zval *object = ZEND_THIS;
5961 php_period_obj *period_obj;
5962 zval *array;
5963 HashTable *myht;
5964
5966 Z_PARAM_ARRAY(array)
5968
5969 period_obj = Z_PHPPERIOD_P(object);
5970 myht = Z_ARRVAL_P(array);
5971
5972 if (!php_date_period_initialize_from_hash(period_obj, myht)) {
5973 zend_throw_error(NULL, "Invalid serialization data for DatePeriod object");
5974 RETURN_THROWS();
5975 }
5976 restore_custom_dateperiod_properties(object, myht);
5977}
5978/* }}} */
5979
5980/* {{{ */
5982{
5983 zval *object = ZEND_THIS;
5984 php_period_obj *period_obj;
5985 HashTable *myht;
5986
5988
5989 period_obj = Z_PHPPERIOD_P(object);
5990
5991 myht = Z_OBJPROP_P(object);
5992
5993 if (!php_date_period_initialize_from_hash(period_obj, myht)) {
5994 zend_throw_error(NULL, "Invalid serialization data for DatePeriod object");
5995 RETURN_THROWS();
5996 }
5997}
5998/* }}} */
5999
6000/* {{{ date_period_read_property */
6001static zval *date_period_read_property(zend_object *object, zend_string *name, int type, void **cache_slot, zval *rv)
6002{
6003 if (type != BP_VAR_IS && type != BP_VAR_R) {
6004 if (date_period_is_internal_property(name)) {
6006 return &EG(uninitialized_zval);
6007 }
6008 }
6009
6010 return zend_std_read_property(object, name, type, cache_slot, rv);
6011}
6012/* }}} */
6013
6014static zval *date_period_write_property(zend_object *object, zend_string *name, zval *value, void **cache_slot)
6015{
6016 if (date_period_is_internal_property(name)) {
6018 return value;
6019 }
6020
6021 return zend_std_write_property(object, name, value, cache_slot);
6022}
6023
6024static zval *date_period_get_property_ptr_ptr(zend_object *object, zend_string *name, int type, void **cache_slot)
6025{
6026 if (date_period_is_internal_property(name)) {
6028 return &EG(error_zval);
6029 }
6030
6031 return zend_std_get_property_ptr_ptr(object, name, type, cache_slot);
6032}
bool exception
Definition assert.c:30
int timelib_astro_rise_set_altitude(timelib_time *t_loc, double lon, double lat, double altit, int upper_limb, double *h_rise, double *h_set, timelib_sll *ts_rise, timelib_sll *ts_set, timelib_sll *ts_transit)
Definition astro.c:212
abs(int|float $num)
floor(int|float $num)
gettimeofday(bool $as_float=false)
fmod(float $num1, float $num2)
char s[4]
Definition cdf.c:77
timelib_sll timelib_iso_day_of_week(timelib_sll y, timelib_sll m, timelib_sll d)
Definition dow.c:72
void timelib_isoweek_from_date(timelib_sll y, timelib_sll m, timelib_sll d, timelib_sll *iw, timelib_sll *iy)
Definition dow.c:93
timelib_sll timelib_day_of_year(timelib_sll y, timelib_sll m, timelib_sll d)
Definition dow.c:83
timelib_sll timelib_day_of_week(timelib_sll y, timelib_sll m, timelib_sll d)
Definition dow.c:67
int timelib_valid_date(timelib_sll y, timelib_sll m, timelib_sll d)
Definition dow.c:203
timelib_sll timelib_days_in_month(timelib_sll y, timelib_sll m)
Definition dow.c:88
timelib_sll timelib_daynr_from_weeknr(timelib_sll iy, timelib_sll iw, timelib_sll id)
Definition dow.c:147
int begin
Definition eaw_table.h:20
#define N
error($message)
Definition ext_skel.php:22
zend_ffi_type * type
Definition ffi.c:3812
zval * zv
Definition ffi.c:3975
zend_long n
Definition ffi.c:4979
new_type size
Definition ffi.c:4365
memcpy(ptr1, ptr2, size)
char * err
Definition ffi.c:3029
memset(ptr, 0, type->size)
zval * val
Definition ffi.c:4262
HashTable * ht
Definition ffi.c:4838
buf start
Definition ffi.c:4687
zend_ffi_ctype_name_buf buf
Definition ffi.c:4685
zend_long offset
#define NULL
Definition gdcache.h:45
#define round(tables, k1, k2)
Definition hash_gost.c:26
#define SUCCESS
Definition hash_sha3.c:261
again j
foreach($dp as $el) foreach( $dp as $el) if( $pass2< 2) echo ""
timelib_time * timelib_sub(timelib_time *old_time, timelib_rel_time *interval)
Definition interval.c:242
timelib_time * timelib_add(timelib_time *old_time, timelib_rel_time *interval)
Definition interval.c:211
timelib_rel_time * timelib_diff(timelib_time *one, timelib_time *two)
Definition interval.c:146
timelib_time * timelib_sub_wall(timelib_time *old_time, timelib_rel_time *interval)
Definition interval.c:338
timelib_time * timelib_add_wall(timelib_time *old_time, timelib_rel_time *interval)
Definition interval.c:284
PHPAPI ZEND_COLD void php_error_docref(const char *docref, int type, const char *format,...)
Definition main.c:1173
timelib_long timelib_parse_zone(const char **ptr, int *dst, timelib_time *t, int *tz_not_found, const timelib_tzdb *tzdb, timelib_tz_get_wrapper tz_wrapper)
Definition parse_date.c:940
const timelib_tz_lookup_table * timelib_timezone_abbreviations_list(void)
timelib_time * timelib_parse_from_format(const char *format, const char *string, size_t len, timelib_error_container **errors, const timelib_tzdb *tzdb, timelib_tz_get_wrapper tz_get_wrapper)
timelib_time * timelib_strtotime(const char *s, size_t len, timelib_error_container **errors, const timelib_tzdb *tzdb, timelib_tz_get_wrapper tz_get_wrapper)
const char * timelib_timezone_id_from_abbr(const char *abbr, timelib_long gmtoffset, int isdst)
void timelib_fill_holes(timelib_time *parsed, timelib_time *now, int options)
void timelib_strtointerval(const char *s, size_t len, timelib_time **begin, timelib_time **end, timelib_rel_time **period, int *recurrences, timelib_error_container **errors)
void timelib_get_transitions_for_year(timelib_tzinfo *tz, timelib_sll year, timelib_posix_transitions *transitions)
const timelib_tzdb_index_entry * timelib_timezone_identifiers_list(const timelib_tzdb *tzdb, int *count)
Definition parse_tz.c:611
void timelib_tzinfo_dtor(timelib_tzinfo *tz)
Definition parse_tz.c:728
timelib_tzinfo * timelib_parse_tzfile(const char *timezone, const timelib_tzdb *tzdb, int *error_code)
Definition parse_tz.c:662
timelib_time_offset * timelib_get_time_zone_info(timelib_sll ts, timelib_tzinfo *tz)
Definition parse_tz.c:881
timelib_sll timelib_get_current_offset(timelib_time *t)
Definition parse_tz.c:937
int timelib_timezone_id_is_valid(const char *timezone, const timelib_tzdb *tzdb)
Definition parse_tz.c:617
const timelib_tzdb * timelib_builtin_db(void)
Definition parse_tz.c:606
php_info_print_table_start()
Definition info.c:1064
php_info_print_table_row(2, "PDO Driver for Firebird", "enabled")
php_info_print_table_end()
Definition info.c:1074
#define PHP_GINIT
Definition php.h:397
#define PHP_FUNCTION
Definition php.h:364
#define PHP_MSHUTDOWN_FUNCTION
Definition php.h:401
#define PHP_MINFO
Definition php.h:396
#define PHP_MINIT_FUNCTION
Definition php.h:400
#define PHP_RINIT
Definition php.h:394
#define PHP_MSHUTDOWN
Definition php.h:393
#define PHP_MINFO_FUNCTION
Definition php.h:404
#define PHP_GINIT_FUNCTION
Definition php.h:405
#define INT_MAX
Definition php.h:237
#define PHP_RSHUTDOWN
Definition php.h:395
#define PHP_RINIT_FUNCTION
Definition php.h:402
#define PHP_RSHUTDOWN_FUNCTION
Definition php.h:403
#define PHP_MINIT
Definition php.h:392
#define PHP_METHOD
Definition php.h:365
#define PHPAPI
Definition php.h:71
#define PHP_MODULE_GLOBALS
Definition php.h:408
PHPAPI zend_long php_parse_date(const char *string, zend_long *now)
Definition php_date.c:1057
#define add(i, ts)
PHPAPI zend_class_entry * php_date_get_immutable_ce(void)
Definition php_date.c:279
#define PHP_DATE_PERIOD_INCLUDE_END_DATE
Definition php_date.c:232
#define add_last()
#define GET_VALUE_FROM_STRUCT(n, m)
#define PHP_DATE_TIMEZONE_GROUP_UTC
Definition php_date.c:226
#define PHP_DATE_TIMEZONE_GROUP_ATLANTIC
Definition php_date.c:221
PHPAPI zend_class_entry * php_date_get_date_ce(void)
Definition php_date.c:274
int php_date_global_timezone_db_enabled
Definition php_date.c:245
#define DATE_SUNRISE_ZENITH
Definition php_date.c:254
#define PHP_DATE_TIMEZONE_GROUP_INDIAN
Definition php_date.c:224
#define PHP_DATE_TIMEZONE_PER_COUNTRY
Definition php_date.c:229
PHPAPI zend_class_entry * php_date_get_period_ce(void)
Definition php_date.c:299
PHPAPI zend_class_entry * php_date_get_interface_ce(void)
Definition php_date.c:284
#define PHP_DATE_TIMEZONE_GROUP_AMERICA
Definition php_date.c:217
PHPAPI int php_idate(char format, time_t ts, bool localtime)
Definition php_date.c:901
#define PHP_DATE_TIMEZONE_GROUP_ALL_W_BC
Definition php_date.c:228
#define PHP_DATE_TIMEZONE_GROUP_PACIFIC
Definition php_date.c:225
PHPAPI zend_string * php_format_date_obj(const char *format, size_t format_len, php_date_obj *date_obj)
Definition php_date.c:846
#define PHP_DATE_PARSE_DATE_SET_TIME_ELEMENT(name, elem)
#define PHP_DATE_TIMEZONE_GROUP_AUSTRALIA
Definition php_date.c:222
#define DATE_TIMEZONEDB
Definition php_date.c:450
PHPAPI void php_strftime(INTERNAL_FUNCTION_PARAMETERS, bool gmt)
Definition php_date.c:1257
#define SUNFUNCS_RET_STRING
Definition php_date.c:213
PHPAPI timelib_tzinfo * get_timezone_info(void)
Definition php_date.c:573
#define SUNFUNCS_RET_TIMESTAMP
Definition php_date.c:212
#define PHP_DATE_TIMEZONE_GROUP_EUROPE
Definition php_date.c:223
timelib_tzdb * php_date_global_timezone_db
Definition php_date.c:244
#define DATE_CHECK_INITIALIZED(member, ce)
Definition php_date.c:327
#define PHP_DATE_TIMEZONE_GROUP_AFRICA
Definition php_date.c:216
#define PHP_DATE_INTERVAL_ADD_PROPERTY(n, f)
zend_module_entry date_module_entry
Definition php_date.c:370
#define DATE_SUNSET_ZENITH
Definition php_date.c:251
#define PHP_DATE_INTERVAL_READ_PROPERTY_DAYS(member)
#define PHP_DATE_PERIOD_EXCLUDE_START_DATE
Definition php_date.c:231
PHPAPI bool php_date_initialize_from_ts_double(php_date_obj *dateobj, double ts)
Definition php_date.c:2529
PHPAPI zend_string * php_format_date(const char *format, size_t format_len, time_t ts, bool localtime)
Definition php_date.c:875
#define SET_VALUE_FROM_STRUCT(n, m)
PHPAPI zend_class_entry * php_date_get_timezone_ce(void)
Definition php_date.c:289
PHPAPI void php_date_set_tzdb(timelib_tzdb *tzdb)
Definition php_date.c:1045
#define add_by_index(i, ts)
#define PHP_DATE_TIMEZONE_GROUP_ARCTIC
Definition php_date.c:219
PHPAPI time_t php_time(void)
Definition php_date.c:56
#define PHP_DATE_INTERVAL_READ_PROPERTY_I64(element, member)
#define PHP_DATE_TIMEZONE_GROUP_ANTARCTICA
Definition php_date.c:218
PHPAPI bool php_date_initialize(php_date_obj *dateobj, const char *time_str, size_t time_str_len, const char *format, zval *timezone_object, int flags)
Definition php_date.c:2403
PHPAPI void php_mktime(INTERNAL_FUNCTION_PARAMETERS, bool gmt)
Definition php_date.c:1141
#define PHP_DATE_TIMEZONE_GROUP_ASIA
Definition php_date.c:220
#define PHP_DATE_TIMEZONE_GROUP_ALL
Definition php_date.c:227
PHPAPI zval * php_date_instantiate(zend_class_entry *pce, zval *object)
Definition php_date.c:2356
#define SUNFUNCS_RET_DOUBLE
Definition php_date.c:214
php_date_obj * dateobj
Definition php_date.c:3976
#define add_nominal()
#define DATE_DEFAULT_LONGITUDE
Definition php_date.c:248
ZEND_PARSE_PARAMETERS_NONE()
PHPAPI zend_class_entry * php_date_get_interval_ce(void)
Definition php_date.c:294
#define DATE_DEFAULT_LATITUDE
Definition php_date.c:247
PHPAPI void php_date_initialize_from_ts_long(php_date_obj *dateobj, zend_long sec, int usec)
Definition php_date.c:2519
#define add_from_tto(to, ts)
#define PHP_DATE_INTERVAL_READ_PROPERTY(element, member, itype, def)
#define Z_PHPINTERVAL_P(zv)
Definition php_date.h:102
#define Z_PHPPERIOD_P(zv)
Definition php_date.h:121
struct _php_timezone_obj php_timezone_obj
Definition php_date.h:54
#define Z_PHPTIMEZONE_P(zv)
Definition php_date.h:84
#define PHP_DATE_INIT_FORMAT
Definition php_date.h:159
struct _php_interval_obj php_interval_obj
Definition php_date.h:55
#define PHP_DATE_INIT_CTOR
Definition php_date.h:158
#define PHP_DATE_CIVIL
Definition php_date.h:86
struct _php_date_obj php_date_obj
Definition php_date.h:53
#define Z_PHPDATE_P(zv)
Definition php_date.h:67
#define PHP_DATE_VERSION
Definition php_date.h:41
HashTable * tzcache
Definition php_date.h:126
#define PHP_DATE_DOUBLE_FITS_LONG(d)
Definition php_date.h:34
#define DATEG(v)
Definition php_date.h:130
timelib_error_container * last_errors
Definition php_date.h:127
struct _php_period_obj php_period_obj
Definition php_date.h:56
#define PHP_DATE_WALL
Definition php_date.h:87
char * default_timezone
Definition php_date.h:124
timezone_version_get()
date_sun_info(int $timestamp, float $latitude, float $longitude)
date_default_timezone_get()
timezone_open(string $timezone)
gmdate(string $format, ?int $timestamp=null)
date_default_timezone_set(string $timezoneId)
timezone_abbreviations_list()
date(string $format, ?int $timestamp=null)
date_parse_from_format(string $format, string $datetime)
date_sunset(int $timestamp, int $returnFormat=SUNFUNCS_RET_STRING, ?float $latitude=null, ?float $longitude=null, ?float $zenith=null, ?float $utcOffset=null)
idate(string $format, ?int $timestamp=null)
date_time_set(DateTime $object, int $hour, int $minute, int $second=0, int $microsecond=0)
date_timezone_get(DateTimeInterface $object)
timezone_name_get(DateTimeZone $object)
date_date_set(DateTime $object, int $year, int $month, int $day)
timezone_location_get(DateTimeZone $object)
getdate(?int $timestamp=null)
date_add(DateTime $object, DateInterval $interval)
date_create_immutable(string $datetime="now", ?DateTimeZone $timezone=null)
date_timezone_set(DateTime $object, DateTimeZone $timezone)
mktime(int $hour, ?int $minute=null, ?int $second=null, ?int $month=null, ?int $day=null, ?int $year=null)
date_sunrise(int $timestamp, int $returnFormat=SUNFUNCS_RET_STRING, ?float $latitude=null, ?float $longitude=null, ?float $zenith=null, ?float $utcOffset=null)
checkdate(int $month, int $day, int $year)
date_parse(string $datetime)
timezone_name_from_abbr(string $abbr, int $utcOffset=-1, int $isDST=-1)
date_create_from_format(string $format, string $datetime, ?DateTimeZone $timezone=null)
date_timestamp_get(DateTimeInterface $object)
date_create(string $datetime="now", ?DateTimeZone $timezone=null)
date_isodate_set(DateTime $object, int $year, int $week, int $dayOfWeek=1)
date_sub(DateTime $object, DateInterval $interval)
gmstrftime(string $format, ?int $timestamp=null)
timezone_offset_get(DateTimeZone $object, DateTimeInterface $datetime)
date_get_last_errors()
date_diff(DateTimeInterface $baseObject, DateTimeInterface $targetObject, bool $absolute=false)
strtotime(string $datetime, ?int $baseTimestamp=null)
date_interval_create_from_date_string(string $datetime)
date_timestamp_set(DateTime $object, int $timestamp)
gmmktime(int $hour, ?int $minute=null, ?int $second=null, ?int $month=null, ?int $day=null, ?int $year=null)
strftime(string $format, ?int $timestamp=null)
date_modify(DateTime $object, string $modifier)
time()
localtime(?int $timestamp=null, bool $associative=false)
date_offset_get(DateTimeInterface $object)
timezone_transitions_get(DateTimeZone $object, int $timestampBegin=PHP_INT_MIN, int $timestampEnd=PHP_INT_MAX)
date_create_immutable_from_format(string $format, string $datetime, ?DateTimeZone $timezone=null)
timezone_identifiers_list(int $timezoneGroup=DateTimeZone::ALL, ?string $countryCode=null)
unsigned const char * end
Definition php_ffi.h:51
#define t2
PHPAPI zval * cfg_get_entry(const char *name, size_t name_length)
Definition php_ini.c:892
#define PHP_INI_ALL
Definition php_ini.h:45
#define PHP_INI_BEGIN
Definition php_ini.h:52
#define STD_PHP_INI_ENTRY
Definition php_ini.h:64
#define PHP_INI_ENTRY
Definition php_ini.h:62
#define PHP_INI_MH
Definition php_ini.h:49
#define PHP_INI_END
Definition php_ini.h:53
PHP_JSON_API size_t int options
Definition php_json.h:102
#define min(a, b)
unsigned char key[REFLECTION_KEY_LEN]
PHPAPI int php_version_compare(const char *, const char *)
Definition versioning.c:121
zval rv
Definition session.c:1024
p
Definition session.c:1105
time_t now
Definition session.c:1281
#define slprintf
Definition snprintf.h:89
#define strpprintf
Definition spprintf.h:30
#define spprintf
Definition spprintf.h:29
zend_object std
Definition php_date.h:60
timelib_time * time
Definition php_date.h:59
zend_object std
Definition php_date.h:95
timelib_rel_time * diff
Definition php_date.h:90
zend_string * date_string
Definition php_date.h:93
timelib_rel_time * interval
Definition php_date.h:109
zend_object std
Definition php_date.h:114
bool include_end_date
Definition php_date.h:113
bool include_start_date
Definition php_date.h:112
timelib_time * start
Definition php_date.h:105
timelib_time * end
Definition php_date.h:108
timelib_time * current
Definition php_date.h:107
zend_class_entry * start_ce
Definition php_date.h:106
timelib_tzinfo * tz
Definition php_date.h:73
timelib_sll utc_offset
Definition php_date.h:74
union _php_timezone_obj::@213245010343033015320150043202117071337023242314 tzi
timelib_abbr_info z
Definition php_date.h:75
zend_object std
Definition php_date.h:77
timelib_sll utc_offset
Definition timelib.h:274
timelib_posix_trans_info * dst_end
Definition timelib.h:177
timelib_sll types[6]
Definition timelib.h:186
timelib_sll times[6]
Definition timelib.h:185
timelib_sll h
Definition timelib.h:225
timelib_sll days
Definition timelib.h:233
struct _timelib_rel_time::@101250100307152364107271232245320174113050270325 special
timelib_sll d
Definition timelib.h:224
timelib_sll us
Definition timelib.h:226
timelib_sll i
Definition timelib.h:225
timelib_sll amount
Definition timelib.h:237
unsigned int type
Definition timelib.h:236
unsigned int have_special_relative
Definition timelib.h:240
timelib_sll y
Definition timelib.h:224
unsigned int have_weekday_relative
Definition timelib.h:240
timelib_sll s
Definition timelib.h:225
timelib_sll m
Definition timelib.h:224
unsigned int is_localtime
Definition timelib.h:267
timelib_sll s
Definition timelib.h:253
timelib_sll h
Definition timelib.h:253
timelib_sll d
Definition timelib.h:252
timelib_sll sse
Definition timelib.h:261
char * tz_abbr
Definition timelib.h:256
timelib_sll m
Definition timelib.h:252
unsigned int zone_type
Definition timelib.h:268
signed int dst
Definition timelib.h:258
timelib_tzinfo * tz_info
Definition timelib.h:257
unsigned int have_zone
Definition timelib.h:263
timelib_sll y
Definition timelib.h:252
unsigned int sse_uptodate
Definition timelib.h:265
timelib_sll us
Definition timelib.h:254
timelib_sll i
Definition timelib.h:253
unsigned int have_relative
Definition timelib.h:263
timelib_rel_time relative
Definition timelib.h:259
const char * full_tz_name
Definition timelib.h:349
const char * version
Definition timelib.h:358
const unsigned char * data
Definition timelib.h:361
struct _timelib_tzinfo::@164363312306351063307143032200107146325273170202 bit64
uint32_t timecnt
Definition timelib.h:196
tlocinfo location
Definition timelib.h:217
timelib_posix_str * posix_info
Definition timelib.h:220
int64_t * trans
Definition timelib.h:209
double longitude
Definition timelib.h:147
char country_code[3]
Definition timelib.h:145
char * comments
Definition timelib.h:148
double latitude
Definition timelib.h:146
zend_string * name
Definition zend.h:149
char type
Definition zend.h:148
zend_class_entry * parent
Definition zend.h:152
const zend_object_iterator_funcs * funcs
zend_class_entry * ce
Definition zend_types.h:560
Definition file.h:177
php_period_obj * object
Definition php_date.c:1551
zend_object_iterator intern
Definition php_date.c:1549
long suseconds_t
Definition time.h:44
void timelib_time_offset_dtor(timelib_time_offset *t)
Definition timelib.c:141
timelib_time * timelib_time_ctor(void)
Definition timelib.c:61
timelib_long timelib_date_to_int(timelib_time *d, int *error)
Definition timelib.c:170
timelib_time * timelib_time_clone(timelib_time *orig)
Definition timelib.c:88
int timelib_time_compare(timelib_time *t1, timelib_time *t2)
Definition timelib.c:75
void timelib_error_container_dtor(timelib_error_container *errors)
Definition timelib.c:155
timelib_rel_time * timelib_rel_time_clone(timelib_rel_time *rel)
Definition timelib.c:114
void timelib_time_dtor(timelib_time *t)
Definition timelib.c:69
timelib_time_offset * timelib_time_offset_ctor(void)
Definition timelib.c:133
void timelib_rel_time_dtor(timelib_rel_time *t)
Definition timelib.c:109
timelib_rel_time * timelib_rel_time_ctor(void)
Definition timelib.c:101
#define TIMELIB_UNSET
Definition timelib.h:382
void timelib_unixtime2local(timelib_time *tm, timelib_sll ts)
#define timelib_malloc
Definition timelib.h:365
#define TIMELIB_ZONETYPE_ID
Definition timelib.h:329
#define TIMELIB_LONG_MIN
Definition timelib.h:124
void timelib_unixtime2gmt(timelib_time *tm, timelib_sll ts)
Definition unixtime2tm.c:57
void timelib_set_timezone_from_offset(timelib_time *t, timelib_sll utc_offset)
#define TIMELIB_LONG_MAX
Definition timelib.h:123
#define TIMELIB_LONG_FMT
Definition timelib.h:126
#define TIMELIB_NO_CLONE
Definition timelib.h:380
struct _timelib_error_container timelib_error_container
#define TIMELIB_OVERRIDE_TIME
Definition timelib.h:379
void timelib_unixtime2date(timelib_sll ts, timelib_sll *y, timelib_sll *m, timelib_sll *d)
Definition unixtime2tm.c:29
void timelib_update_ts(timelib_time *time, timelib_tzinfo *tzi)
void timelib_update_from_sse(timelib_time *tm)
Definition unixtime2tm.c:83
#define TIMELIB_ZONETYPE_OFFSET
Definition timelib.h:327
struct _timelib_tzdb timelib_tzdb
#define TIMELIB_ASCII_VERSION
Definition timelib.h:35
#define timelib_strdup
Definition timelib.h:368
struct _timelib_time timelib_time
void timelib_set_timezone(timelib_time *t, timelib_tzinfo *tz)
struct _timelib_rel_time timelib_rel_time
struct _timelib_tzdb_index_entry timelib_tzdb_index_entry
signed long long timelib_sll
Definition timelib.h:136
#define timelib_free
Definition timelib.h:369
struct _timelib_time_offset timelib_time_offset
struct _timelib_tzinfo timelib_tzinfo
struct _timelib_tz_lookup_table timelib_tz_lookup_table
#define TIMELIB_ZONETYPE_ABBR
Definition timelib.h:328
struct _timelib_posix_transitions timelib_posix_transitions
void timelib_set_timezone_from_abbr(timelib_time *t, timelib_abbr_info abbr_info)
#define TIMELIB_SPECIAL_WEEKDAY
#define TIMELIB_SPECIAL_FIRST_DAY_OF_MONTH
#define timelib_is_leap(y)
ZEND_API ZEND_COLD ZEND_NORETURN void zend_error_noreturn(int type, const char *format,...)
Definition zend.c:1703
ZEND_API ZEND_COLD void zend_throw_error(zend_class_entry *exception_ce, const char *format,...)
Definition zend.c:1772
ZEND_API ZEND_COLD void zend_type_error(const char *format,...)
Definition zend.c:1824
ZEND_API ZEND_COLD void zend_error(int type, const char *format,...)
Definition zend.c:1666
#define INTERNAL_FUNCTION_PARAMETERS
Definition zend.h:49
@ EH_THROW
Definition zend.h:433
ZEND_API void zend_replace_error_handling(zend_error_handling_t error_handling, zend_class_entry *exception_class, zend_error_handling *current)
Definition zend_API.c:5242
ZEND_API void zend_restore_error_handling(zend_error_handling *saved)
Definition zend_API.c:5253
#define INTERNAL_FUNCTION_PARAM_PASSTHRU
Definition zend.h:50
ZEND_API void add_assoc_bool_ex(zval *arg, const char *key, size_t key_len, bool b)
Definition zend_API.c:1946
ZEND_API zend_result add_next_index_long(zval *arg, zend_long n)
Definition zend_API.c:2132
ZEND_API zend_result object_init_ex(zval *arg, zend_class_entry *class_type)
Definition zend_API.c:1849
ZEND_API ZEND_COLD void zend_argument_error(zend_class_entry *error_ce, uint32_t arg_num, const char *format,...)
Definition zend_API.c:413
ZEND_API void add_index_string(zval *arg, zend_ulong index, const char *str)
Definition zend_API.c:2087
ZEND_API void add_assoc_string_ex(zval *arg, const char *key, size_t key_len, const char *str)
Definition zend_API.c:1982
ZEND_API void zend_update_property(zend_class_entry *scope, zend_object *object, const char *name, size_t name_length, zval *value)
Definition zend_API.c:4991
ZEND_API void object_properties_init(zend_object *object, zend_class_entry *class_type)
Definition zend_API.c:1688
ZEND_API void add_assoc_long_ex(zval *arg, const char *key, size_t key_len, zend_long n)
Definition zend_API.c:1928
ZEND_API zend_result zend_parse_method_parameters(uint32_t num_args, zval *this_ptr, const char *type_spec,...)
Definition zend_API.c:1314
ZEND_API ZEND_COLD void zend_argument_value_error(uint32_t arg_num, const char *format,...)
Definition zend_API.c:433
ZEND_API zend_result add_next_index_string(zval *arg, const char *str)
Definition zend_API.c:2186
ZEND_API void add_assoc_null_ex(zval *arg, const char *key, size_t key_len)
Definition zend_API.c:1937
ZEND_API void add_index_long(zval *arg, zend_ulong index, zend_long n)
Definition zend_API.c:2033
ZEND_API zend_result zend_parse_parameters_ex(int flags, uint32_t num_args, const char *type_spec,...)
Definition zend_API.c:1287
#define Z_PARAM_NUMBER(dest)
Definition zend_API.h:1914
#define Z_PARAM_PATH_STR(dest)
Definition zend_API.h:2041
#define ZEND_NUM_ARGS()
Definition zend_API.h:530
#define RETURN_STRING(s)
Definition zend_API.h:1043
#define RETURN_OBJ(r)
Definition zend_API.h:1052
#define ZEND_PARSE_PARAMS_QUIET
Definition zend_API.h:361
#define ZEND_PARSE_PARAMETERS_END()
Definition zend_API.h:1641
#define RETURN_FALSE
Definition zend_API.h:1058
#define RETVAL_STRING(s)
Definition zend_API.h:1017
#define RETURN_DOUBLE(d)
Definition zend_API.h:1038
#define ZEND_MODULE_POST_ZEND_DEACTIVATE_N(module)
Definition zend_API.h:226
#define ZVAL_STRING(z, s)
Definition zend_API.h:956
#define ZEND_DECLARE_MODULE_GLOBALS(module_name)
Definition zend_API.h:268
#define Z_PARAM_OPTIONAL
Definition zend_API.h:1667
#define Z_PARAM_STRING(dest, dest_len)
Definition zend_API.h:2071
#define Z_PARAM_STR(dest)
Definition zend_API.h:2086
#define Z_PARAM_STRING_OR_NULL(dest, dest_len)
Definition zend_API.h:2074
#define Z_PARAM_DOUBLE_OR_NULL(dest, is_null)
Definition zend_API.h:1806
#define ZEND_PARSE_PARAMETERS_START(min_num_args, max_num_args)
Definition zend_API.h:1620
#define Z_PARAM_LONG(dest)
Definition zend_API.h:1896
#define RETURN_LONG(l)
Definition zend_API.h:1037
#define RETURN_NEW_STR(s)
Definition zend_API.h:1041
#define RETURN_OBJ_COPY(r)
Definition zend_API.h:1053
#define RETURN_THROWS()
Definition zend_API.h:1060
#define ZEND_MODULE_POST_ZEND_DEACTIVATE_D(module)
Definition zend_API.h:236
#define Z_PARAM_DOUBLE(dest)
Definition zend_API.h:1803
#define RETURN_STR(s)
Definition zend_API.h:1039
#define ZEND_THIS
Definition zend_API.h:523
#define Z_PARAM_LONG_OR_NULL(dest, is_null)
Definition zend_API.h:1899
#define RETVAL_LONG(l)
Definition zend_API.h:1011
#define Z_PARAM_OBJECT_OF_CLASS_OR_NULL(dest, _ce)
Definition zend_API.h:1979
#define Z_PARAM_BOOL(dest)
Definition zend_API.h:1726
#define Z_PARAM_OBJECT_OF_CLASS(dest, _ce)
Definition zend_API.h:1976
#define Z_PARAM_PATH(dest, dest_len)
Definition zend_API.h:2026
#define Z_PARAM_ARRAY(dest)
Definition zend_API.h:1682
#define getThis()
Definition zend_API.h:526
#define RETVAL_FALSE
Definition zend_API.h:1032
#define RETURN_TRUE
Definition zend_API.h:1059
#define array_init(arg)
Definition zend_API.h:537
#define estrndup(s, length)
Definition zend_alloc.h:165
#define ecalloc(nmemb, size)
Definition zend_alloc.h:158
#define efree(ptr)
Definition zend_alloc.h:155
#define FREE_HASHTABLE(ht)
Definition zend_alloc.h:234
#define ALLOC_HASHTABLE(ht)
Definition zend_alloc.h:231
#define emalloc(size)
Definition zend_alloc.h:151
struct _zval_struct zval
strlen(string $string)
strcmp(string $string1, string $string2)
zend_string_release_ex(func->internal_function.function_name, 0)
execute_data func
ZEND_API zend_result zend_unmangle_property_name_ex(const zend_string *name, const char **class_name, const char **prop_name, size_t *prop_len)
#define BP_VAR_R
#define ZEND_USER_CLASS
#define ZEND_INTERNAL_CLASS
#define BP_VAR_IS
#define strncasecmp(s1, s2, n)
#define snprintf
#define E_NOTICE
Definition zend_errors.h:26
#define E_ERROR
Definition zend_errors.h:23
#define E_WARNING
Definition zend_errors.h:24
#define E_DEPRECATED
Definition zend_errors.h:37
ZEND_API zend_class_entry * zend_ce_exception
ZEND_API ZEND_COLD zend_object * zend_throw_exception_ex(zend_class_entry *exception_ce, zend_long code, const char *format,...)
ZEND_API zend_class_entry * zend_ce_error
ZEND_API ZEND_COLD void ZEND_FASTCALL zend_readonly_property_modification_error_ex(const char *class_name, const char *prop_name)
ZEND_API zend_class_entry * zend_lookup_class(zend_string *name)
ZEND_API zend_string * get_active_function_or_method_name(void)
#define EG(v)
ZEND_API void ZEND_FASTCALL zend_hash_destroy(HashTable *ht)
Definition zend_hash.c:1727
ZEND_API zval *ZEND_FASTCALL zend_hash_str_find(const HashTable *ht, const char *str, size_t len)
Definition zend_hash.c:2689
ZEND_API zval *ZEND_FASTCALL zend_hash_str_update(HashTable *ht, const char *str, size_t len, zval *pData)
Definition zend_hash.c:1031
ZEND_API HashTable *ZEND_FASTCALL zend_array_dup(HashTable *source)
Definition zend_hash.c:2438
ZEND_API zval *ZEND_FASTCALL zend_hash_add(HashTable *ht, zend_string *key, zval *pData)
Definition zend_hash.c:992
#define zend_hash_init(ht, nSize, pHashFunction, pDestructor, persistent)
Definition zend_hash.h:108
#define ZEND_HASH_FOREACH_STR_KEY_VAL_IND(ht, _key, _val)
Definition zend_hash.h:1193
#define ZEND_HASH_FOREACH_STR_KEY_VAL(ht, _key, _val)
Definition zend_hash.h:1166
#define ZEND_HASH_FOREACH_END()
Definition zend_hash.h:1086
#define UNREGISTER_INI_ENTRIES()
Definition zend_ini.h:204
#define REGISTER_INI_ENTRIES()
Definition zend_ini.h:203
#define INI_FLT(name)
Definition zend_ini.h:194
#define DISPLAY_INI_ENTRIES()
Definition zend_ini.h:205
ZEND_API zend_class_entry * zend_ce_aggregate
ZEND_API zend_result zend_create_internal_iterator_zval(zval *return_value, zval *obj)
ZEND_API void zend_iterator_init(zend_object_iterator *iter)
struct _zend_object_iterator zend_object_iterator
struct _zend_object_iterator_funcs zend_object_iterator_funcs
int32_t zend_long
Definition zend_long.h:42
#define ZEND_LONG_MIN
Definition zend_long.h:46
#define ZEND_LONG_FMT_SPEC
Definition zend_long.h:90
#define ZEND_LONG_FMT
Definition zend_long.h:87
struct _zend_string zend_string
struct _zend_module_entry zend_module_entry
#define STANDARD_MODULE_PROPERTIES_EX
#define STANDARD_MODULE_HEADER_EX
ZEND_API zval * zend_std_get_property_ptr_ptr(zend_object *zobj, zend_string *name, int type, void **cache_slot)
ZEND_API HashTable * zend_std_get_properties_for(zend_object *obj, zend_prop_purpose purpose)
ZEND_API HashTable * zend_std_get_properties(zend_object *zobj)
ZEND_API int zend_std_has_property(zend_object *zobj, zend_string *name, int has_set_exists, void **cache_slot)
ZEND_API const zend_object_handlers std_object_handlers
ZEND_API zval * zend_std_write_property(zend_object *zobj, zend_string *name, zval *value, void **cache_slot)
ZEND_API zval * zend_std_read_property(zend_object *zobj, zend_string *name, int type, void **cache_slot, zval *rv)
enum _zend_prop_purpose zend_prop_purpose
@ ZEND_PROP_PURPOSE_DEBUG
@ ZEND_PROP_PURPOSE_SERIALIZE
@ ZEND_PROP_PURPOSE_ARRAY_CAST
@ ZEND_PROP_PURPOSE_VAR_EXPORT
@ ZEND_PROP_PURPOSE_JSON
#define ZEND_COMPARE_OBJECTS_FALLBACK(op1, op2)
ZEND_API void ZEND_FASTCALL zend_objects_clone_members(zend_object *new_object, zend_object *old_object)
ZEND_API void ZEND_FASTCALL zend_object_std_init(zend_object *object, zend_class_entry *ce)
ZEND_API void zend_object_std_dtor(zend_object *object)
ZEND_API bool ZEND_FASTCALL zend_is_true(const zval *op)
#define ZEND_UNCOMPARABLE
#define zend_finite(a)
#define ZEND_FALLTHROUGH
#define XtOffsetOf(s_type, field)
#define EMPTY_SWITCH_DEFAULT_CASE()
#define UNEXPECTED(condition)
struct _zend_class_entry zend_class_entry
struct _zend_object zend_object
ZEND_API zend_string * zend_string_concat3(const char *str1, size_t str1_len, const char *str2, size_t str2_len, const char *str3, size_t str3_len)
#define ZSTR_VAL(zstr)
Definition zend_string.h:68
#define ZSTR_INIT_LITERAL(s, persistent)
#define zend_string_equals_literal(str, literal)
#define ZSTR_EMPTY_ALLOC()
#define ZSTR_LEN(zstr)
Definition zend_string.h:69
#define d1
#define Z_TYPE_P(zval_p)
Definition zend_types.h:660
#define IS_TRUE
Definition zend_types.h:603
#define ZVAL_STR(z, s)
#define ZVAL_FALSE(z)
#define Z_TRY_ADDREF_P(pz)
#define ZVAL_UNDEF(z)
#define IS_FALSE
Definition zend_types.h:602
#define Z_STRVAL_P(zval_p)
Definition zend_types.h:975
#define IS_UNDEF
Definition zend_types.h:600
#define Z_ARRVAL_P(zval_p)
Definition zend_types.h:987
#define ZVAL_NULL(z)
#define ZVAL_LONG(z, l)
#define IS_STRING
Definition zend_types.h:606
#define ZVAL_STR_COPY(z, s)
struct _zend_array HashTable
Definition zend_types.h:386
#define Z_OBJ_P(zval_p)
Definition zend_types.h:990
#define IS_DOUBLE
Definition zend_types.h:605
#define Z_STR_P(zval_p)
Definition zend_types.h:972
#define Z_PTR_P(zval_p)
#define Z_STRLEN_P(zval_p)
Definition zend_types.h:978
#define IS_NULL
Definition zend_types.h:601
#define Z_OBJCE_P(zval_p)
#define ZVAL_OBJ(z, o)
@ FAILURE
Definition zend_types.h:61
#define IS_OBJECT
Definition zend_types.h:608
#define IS_LONG
Definition zend_types.h:604
#define IS_REFERENCE
Definition zend_types.h:610
#define ZVAL_NEW_STR(z, s)
#define Z_OBJPROP_P(zval_p)
#define ZVAL_DOUBLE(z, d)
#define ZVAL_OBJ_COPY(z, o)
ZEND_RESULT_CODE zend_result
Definition zend_types.h:64
struct _zend_object_handlers zend_object_handlers
Definition zend_types.h:88
#define Z_TYPE(zval)
Definition zend_types.h:659
#define Z_DVAL_P(zval_p)
Definition zend_types.h:969
#define Z_LVAL_P(zval_p)
Definition zend_types.h:966
#define ZVAL_COPY_VALUE(z, v)
#define ZVAL_BOOL(z, b)
#define Z_OBJ(zval)
Definition zend_types.h:989
ZEND_API void zval_ptr_dtor(zval *zval_ptr)
zval retval
double d2
zval * return_value
zend_string * name
execute_data
object
zval * ret
value
zend_object * zobj