PHP  
 PHP: Test and Code Coverage Analysis
downloads | QA | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | my php.net 
 

LCOV - code coverage report
Current view: top level - ext/date - php_date.c (source / functions) Hit Total Coverage
Test: PHP Code Coverage Lines: 1698 1900 89.4 %
Date: 2014-07-27 Functions: 118 128 92.2 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10

Generated at Sun, 27 Jul 2014 12:58:27 +0000 (31 hours ago)

Copyright © 2005-2014 The PHP Group
All rights reserved.