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