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", &times, &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", &times, &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, &timestamp) == 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", &timestamp, &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", &timestamp) == 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, &timestamp) == 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, &timestamp_begin, &timestamp_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>