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

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

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