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

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

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