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