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

LTP GCOV extension - code coverage report
Current view: directory - date - php_date.c
Test: PHP Code Coverage
Date: 2009-11-23 Instrumented lines: 1700
Code covered: 87.1 % Executed lines: 1481
Legend: not executed executed

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

Generated by: LTP GCOV extension version 1.5

Generated at Mon, 23 Nov 2009 17:39:28 +0000 (33 hours ago)

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