Annotation of embedaddon/php/ext/date/php_date.c, revision 1.1.1.3

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>