Annotation of embedaddon/php/ext/date/php_date.c, revision 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>