2005-06-15 05:32:29 +08:00
/*
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
| PHP Version 5 |
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
2006-01-01 20:51:34 +08:00
| Copyright ( c ) 1997 - 2006 The PHP Group |
2005-06-15 05:32:29 +08:00
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
2006-01-01 20:51:34 +08:00
| This source file is subject to version 3.01 of the PHP license , |
2005-06-15 05:32:29 +08:00
| that is bundled with this package in the file LICENSE , and is |
| available through the world - wide - web at the following url : |
2006-01-01 20:51:34 +08:00
| http : //www.php.net/license/3_01.txt |
2005-06-15 05:32:29 +08:00
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world - wide - web , please send a note to |
| license @ php . net so we can mail you a copy immediately . |
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
2005-06-17 22:54:00 +08:00
| Authors : Derick Rethans < derick @ derickrethans . nl > |
2005-06-15 05:32:29 +08:00
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
*/
/* $Id$ */
# include "php.h"
# include "php_streams.h"
# include "php_main.h"
# include "php_globals.h"
# include "php_ini.h"
# include "ext/standard/info.h"
2005-10-04 07:37:10 +08:00
# include "ext/standard/php_versioning.h"
2005-06-15 05:32:29 +08:00
# include "php_date.h"
2005-06-17 01:12:41 +08:00
# include "lib/timelib.h"
2005-06-15 05:32:29 +08:00
# include <time.h>
2005-07-05 05:27:26 +08:00
/* {{{ Function table */
2005-12-06 09:40:06 +08:00
zend_function_entry date_functions [ ] = {
2005-07-04 04:45:08 +08:00
PHP_FE ( strtotime , NULL )
2005-07-01 05:38:06 +08:00
PHP_FE ( date , NULL )
2005-11-30 07:10:15 +08:00
PHP_FE ( idate , NULL )
2005-07-01 05:38:06 +08:00
PHP_FE ( gmdate , NULL )
2005-07-03 22:27:31 +08:00
PHP_FE ( mktime , NULL )
2005-07-04 07:30:52 +08:00
PHP_FE ( gmmktime , NULL )
2005-07-04 03:14:55 +08:00
PHP_FE ( checkdate , NULL )
2005-07-04 04:45:08 +08:00
2005-07-04 07:30:52 +08:00
# ifdef HAVE_STRFTIME
2005-07-04 03:14:55 +08:00
PHP_FE ( strftime , NULL )
2005-07-04 07:30:52 +08:00
PHP_FE ( gmstrftime , NULL )
2005-07-04 04:45:08 +08:00
# endif
PHP_FE ( time , NULL )
PHP_FE ( localtime , NULL )
PHP_FE ( getdate , NULL )
2005-07-20 16:31:02 +08:00
# ifdef EXPERIMENTAL_DATE_SUPPORT
/* Advanced Interface */
PHP_FE ( date_create , NULL )
2006-04-12 02:03:52 +08:00
PHP_FE ( date_parse , NULL )
2005-07-20 16:31:02 +08:00
PHP_FE ( date_format , NULL )
PHP_FE ( date_modify , NULL )
PHP_FE ( date_timezone_get , NULL )
PHP_FE ( date_timezone_set , NULL )
PHP_FE ( date_offset_get , NULL )
2005-09-02 22:58:01 +08:00
PHP_FE ( date_time_set , NULL )
PHP_FE ( date_date_set , NULL )
PHP_FE ( date_isodate_set , NULL )
2005-07-20 16:31:02 +08:00
PHP_FE ( timezone_open , NULL )
PHP_FE ( timezone_name_get , NULL )
2006-04-12 02:03:52 +08:00
PHP_FE ( timezone_name_from_abbr , NULL )
2005-07-20 16:31:02 +08:00
PHP_FE ( timezone_offset_get , NULL )
PHP_FE ( timezone_transistions_get , NULL )
PHP_FE ( timezone_identifiers_list , NULL )
PHP_FE ( timezone_abbreviations_list , NULL )
# endif
/* Options and Configuration */
2005-07-05 05:27:26 +08:00
PHP_FE ( date_default_timezone_set , NULL )
PHP_FE ( date_default_timezone_get , NULL )
2006-01-05 05:31:35 +08:00
/* Astronomical functions */
PHP_FE ( date_sunrise , NULL )
PHP_FE ( date_sunset , NULL )
2006-01-19 05:40:38 +08:00
PHP_FE ( date_sun_info , NULL )
2005-06-15 05:32:29 +08:00
{ NULL , NULL , NULL }
} ;
2005-07-20 16:31:02 +08:00
2005-11-18 05:05:30 +08:00
# ifdef EXPERIMENTAL_DATE_SUPPORT
2005-12-06 09:40:06 +08:00
zend_function_entry date_funcs_date [ ] = {
2005-07-20 16:31:02 +08:00
ZEND_NAMED_FE ( format , ZEND_FN ( date_format ) , NULL )
ZEND_NAMED_FE ( modify , ZEND_FN ( date_modify ) , NULL )
ZEND_NAMED_FE ( getTimezone , ZEND_FN ( date_timezone_get ) , NULL )
ZEND_NAMED_FE ( setTimezone , ZEND_FN ( date_timezone_set ) , NULL )
ZEND_NAMED_FE ( getOffset , ZEND_FN ( date_offset_get ) , NULL )
2005-09-02 22:58:01 +08:00
ZEND_NAMED_FE ( setTime , ZEND_FN ( date_time_set ) , NULL )
ZEND_NAMED_FE ( setDate , ZEND_FN ( date_date_set ) , NULL )
ZEND_NAMED_FE ( setISODate , ZEND_FN ( date_isodate_set ) , NULL )
2005-07-20 16:31:02 +08:00
{ NULL , NULL , NULL }
} ;
2005-12-06 09:40:06 +08:00
zend_function_entry date_funcs_timezone [ ] = {
2005-07-20 16:31:02 +08:00
ZEND_NAMED_FE ( getName , ZEND_FN ( timezone_name_get ) , NULL )
ZEND_NAMED_FE ( getOffset , ZEND_FN ( timezone_offset_get ) , NULL )
ZEND_NAMED_FE ( getTransistions , ZEND_FN ( timezone_transistions_get ) , NULL )
2006-05-10 08:00:13 +08:00
ZEND_ME_MAPPING ( listAbbreviations , timezone_abbreviations_list , NULL , ZEND_ACC_PUBLIC | ZEND_ACC_STATIC )
ZEND_ME_MAPPING ( listIdentifiers , timezone_identifiers_list , NULL , ZEND_ACC_PUBLIC | ZEND_ACC_STATIC )
2005-07-20 16:31:02 +08:00
{ NULL , NULL , NULL }
} ;
2005-11-18 05:05:30 +08:00
static void date_register_classes ( TSRMLS_D ) ;
2005-11-27 14:51:43 +08:00
# endif
2006-05-15 01:36:05 +08:00
static char * guess_timezone ( const timelib_tzdb * tzdb TSRMLS_DC ) ;
2005-07-05 05:27:26 +08:00
/* }}} */
2005-06-15 05:32:29 +08:00
2005-06-19 04:23:19 +08:00
ZEND_DECLARE_MODULE_GLOBALS ( date )
2005-10-03 19:17:28 +08:00
/* True global */
timelib_tzdb * php_date_global_timezone_db ;
int php_date_global_timezone_db_enabled ;
2006-01-05 05:31:35 +08:00
# define DATE_DEFAULT_LATITUDE "31.7667"
# define DATE_DEFAULT_LONGITUDE "35.2333"
/* on 90'35; common sunset declaration (start of sun body appear) */
# define DATE_SUNSET_ZENITH "90.583333"
/* on 90'35; common sunrise declaration (sun body disappeared) */
# define DATE_SUNRISE_ZENITH "90.583333"
2005-07-05 05:27:26 +08:00
/* {{{ INI Settings */
2005-06-15 05:32:29 +08:00
PHP_INI_BEGIN ( )
2005-07-03 05:19:25 +08:00
STD_PHP_INI_ENTRY ( " date.timezone " , " " , PHP_INI_ALL , OnUpdateString , default_timezone , zend_date_globals , date_globals )
2006-01-05 05:31:35 +08:00
PHP_INI_ENTRY ( " date.default_latitude " , DATE_DEFAULT_LATITUDE , PHP_INI_ALL , NULL )
PHP_INI_ENTRY ( " date.default_longitude " , DATE_DEFAULT_LONGITUDE , PHP_INI_ALL , NULL )
PHP_INI_ENTRY ( " date.sunset_zenith " , DATE_SUNSET_ZENITH , PHP_INI_ALL , NULL )
PHP_INI_ENTRY ( " date.sunrise_zenith " , DATE_SUNRISE_ZENITH , PHP_INI_ALL , NULL )
2005-06-15 05:32:29 +08:00
PHP_INI_END ( )
2005-07-05 05:27:26 +08:00
/* }}} */
2005-06-15 05:32:29 +08:00
2005-11-27 14:51:43 +08:00
# ifdef EXPERIMENTAL_DATE_SUPPORT
2005-11-18 05:05:30 +08:00
zend_class_entry * date_ce_date , * date_ce_timezone ;
static zend_object_handlers date_object_handlers_date ;
static zend_object_handlers date_object_handlers_timezone ;
2005-07-20 16:31:02 +08:00
typedef struct _php_date_obj php_date_obj ;
typedef struct _php_timezone_obj php_timezone_obj ;
struct _php_date_obj {
zend_object std ;
timelib_time * time ;
} ;
struct _php_timezone_obj {
zend_object std ;
timelib_tzinfo * tz ;
} ;
# define DATE_SET_CONTEXT \
zval * object ; \
object = getThis ( ) ; \
# define DATE_FETCH_OBJECT \
php_date_obj * obj ; \
DATE_SET_CONTEXT ; \
if ( object ) { \
if ( ZEND_NUM_ARGS ( ) ) { \
WRONG_PARAM_COUNT ; \
} \
} else { \
if ( zend_parse_method_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , NULL , " O " , & object , date_ce_date ) = = FAILURE ) { \
RETURN_FALSE ; \
} \
} \
obj = ( php_date_obj * ) zend_object_store_get_object ( object TSRMLS_CC ) ; \
static void date_object_free_storage_date ( void * object TSRMLS_DC ) ;
static void date_object_free_storage_timezone ( void * object TSRMLS_DC ) ;
2005-11-18 05:05:30 +08:00
static zend_object_value date_object_new_date ( zend_class_entry * class_type TSRMLS_DC ) ;
static zend_object_value date_object_new_timezone ( zend_class_entry * class_type TSRMLS_DC ) ;
2005-11-27 14:51:43 +08:00
# endif
2005-07-20 16:31:02 +08:00
2005-07-05 05:27:26 +08:00
/* {{{ Module struct */
2005-06-15 05:32:29 +08:00
zend_module_entry date_module_entry = {
STANDARD_MODULE_HEADER ,
" date " , /* extension name */
date_functions , /* function list */
PHP_MINIT ( date ) , /* process startup */
PHP_MSHUTDOWN ( date ) , /* process shutdown */
2005-07-03 05:19:25 +08:00
PHP_RINIT ( date ) , /* request startup */
PHP_RSHUTDOWN ( date ) , /* request shutdown */
2005-06-15 05:32:29 +08:00
PHP_MINFO ( date ) , /* extension info */
PHP_VERSION , /* extension version */
STANDARD_MODULE_PROPERTIES
} ;
2005-07-05 05:27:26 +08:00
/* }}} */
2005-06-15 05:32:29 +08:00
2005-06-19 04:23:19 +08:00
/* {{{ php_date_init_globals */
static void php_date_init_globals ( zend_date_globals * date_globals )
{
date_globals - > default_timezone = NULL ;
2005-07-03 05:19:25 +08:00
date_globals - > timezone = NULL ;
2005-06-19 04:23:19 +08:00
}
/* }}} */
2005-06-15 05:32:29 +08:00
2005-10-05 16:20:44 +08:00
static void _php_date_tzinfo_dtor ( void * tzinfo )
{
timelib_tzinfo * * tzi = ( timelib_tzinfo * * ) tzinfo ;
2005-10-13 03:49:59 +08:00
timelib_tzinfo_dtor ( * tzi ) ;
2005-10-05 16:20:44 +08:00
}
2005-07-05 05:27:26 +08:00
/* {{{ PHP_RINIT_FUNCTION */
2005-07-03 05:19:25 +08:00
PHP_RINIT_FUNCTION ( date )
{
if ( DATEG ( timezone ) ) {
efree ( DATEG ( timezone ) ) ;
}
DATEG ( timezone ) = NULL ;
2005-10-05 16:20:44 +08:00
zend_hash_init ( & DATEG ( tzcache ) , 4 , NULL , _php_date_tzinfo_dtor , 0 ) ;
2005-07-03 05:19:25 +08:00
return SUCCESS ;
}
2005-07-05 05:27:26 +08:00
/* }}} */
2005-07-03 05:19:25 +08:00
2005-07-05 05:27:26 +08:00
/* {{{ PHP_RSHUTDOWN_FUNCTION */
2005-07-03 05:19:25 +08:00
PHP_RSHUTDOWN_FUNCTION ( date )
{
if ( DATEG ( timezone ) ) {
efree ( DATEG ( timezone ) ) ;
}
DATEG ( timezone ) = NULL ;
2005-10-05 16:20:44 +08:00
zend_hash_destroy ( & DATEG ( tzcache ) ) ;
2005-07-03 05:19:25 +08:00
return SUCCESS ;
}
2005-07-05 05:27:26 +08:00
/* }}} */
2005-06-15 05:32:29 +08:00
2005-10-03 19:17:28 +08:00
# define DATE_TIMEZONEDB php_date_global_timezone_db ? php_date_global_timezone_db : timelib_builtin_db()
2006-05-30 21:12:21 +08:00
/*
* RFC822 , Section 5.1 : http : //www.ietf.org/rfc/rfc822.txt
* date - time = [ day " , " ] date time ; dd mm yy hh : mm : ss zzz
* day = " Mon " / " Tue " / " Wed " / " Thu " / " Fri " / " Sat " / " Sun "
* date = 1 * 2 DIGIT month 2 DIGIT ; day month year e . g . 20 Jun 82
* month = " Jan " / " Feb " / " Mar " / " Apr " / " May " / " Jun " / " Jul " / " Aug " / " Sep " / " Oct " / " Nov " / " Dec "
* time = hour zone ; ANSI and Military
* hour = 2 DIGIT " : " 2 DIGIT [ " : " 2 DIGIT ] ; 00 : 00 : 00 - 23 : 59 : 59
* zone = " UT " / " GMT " / " EST " / " EDT " / " CST " / " CDT " / " MST " / " MDT " / " PST " / " PDT " / 1 ALPHA / ( ( " + " / " - " ) 4 DIGIT )
*/
# define DATE_FORMAT_RFC822 "D, d M y H:i:s O"
/*
* RFC850 , Section 2.1 .4 : http : //www.ietf.org/rfc/rfc850.txt
* Format must be acceptable both to the ARPANET and to the getdate routine .
* One format that is acceptable to both is Weekday , DD - Mon - YY HH : MM : SS TIMEZONE
* TIMEZONE can be any timezone name ( 3 or more letters )
*/
# define DATE_FORMAT_RFC850 "l, d-M-y H:i:s T"
/*
* RFC1036 , Section 2.1 .2 : http : //www.ietf.org/rfc/rfc1036.txt
* Its format must be acceptable both in RFC - 822 and to the getdate ( 3 )
* Wdy , DD Mon YY HH : MM : SS TIMEZONE
* There is no hope of having a complete list of timezones . Universal
* Time ( GMT ) , the North American timezones ( PST , PDT , MST , MDT , CST ,
* CDT , EST , EDT ) and the + / - hhmm offset specifed in RFC - 822 should be supported .
*/
# define DATE_FORMAT_RFC1036 "D, d M y H:i:s O"
/*
* RFC1123 , Section 5.2 .14 : http : //www.ietf.org/rfc/rfc1123.txt
* RFC - 822 Date and Time Specification : RFC - 822 Section 5
* The syntax for the date is hereby changed to : date = 1 * 2 DIGIT month 2 * 4 DIGIT
*/
# define DATE_FORMAT_RFC1123 "D, d M Y H:i:s O"
/*
* RFC2822 , Section 3.3 : http : //www.ietf.org/rfc/rfc2822.txt
* FWS = ( [ * WSP CRLF ] 1 * WSP ) / ; Folding white space
* CFWS = * ( [ FWS ] comment ) ( ( [ FWS ] comment ) / FWS )
*
* date - time = [ day - of - week " , " ] date FWS time [ CFWS ]
* day - of - week = ( [ FWS ] day - name )
* day - name = " Mon " / " Tue " / " Wed " / " Thu " / " Fri " / " Sat " / " Sun "
* date = day month year
* year = 4 * DIGIT
* month = ( FWS month - name FWS )
* month - name = " Jan " / " Feb " / " Mar " / " Apr " / " May " / " Jun " / " Jul " / " Aug " / " Sep " / " Oct " / " Nov " / " Dec "
* day = ( [ FWS ] 1 * 2 DIGIT )
* time = time - of - day FWS zone
* time - of - day = hour " : " minute [ " : " second ]
* hour = 2 DIGIT
* minute = 2 DIGIT
* second = 2 DIGIT
* zone = ( ( " + " / " - " ) 4 DIGIT )
*/
# define DATE_FORMAT_RFC2822 "D, d M Y H:i:s O"
/*
* RFC3339 , Section 5.6 : http : //www.ietf.org/rfc/rfc3339.txt
* date - fullyear = 4 DIGIT
* date - month = 2 DIGIT ; 01 - 12
* date - mday = 2 DIGIT ; 01 - 28 , 01 - 29 , 01 - 30 , 01 - 31 based on month / year
*
* time - hour = 2 DIGIT ; 00 - 23
* time - minute = 2 DIGIT ; 00 - 59
* time - second = 2 DIGIT ; 00 - 58 , 00 - 59 , 00 - 60 based on leap second rules
*
* time - secfrac = " . " 1 * DIGIT
* time - numoffset = ( " + " / " - " ) time - hour " : " time - minute
* time - offset = " Z " / time - numoffset
*
* partial - time = time - hour " : " time - minute " : " time - second [ time - secfrac ]
* full - date = date - fullyear " - " date - month " - " date - mday
* full - time = partial - time time - offset
*
* date - time = full - date " T " full - time
*/
2006-02-01 02:44:19 +08:00
# define DATE_FORMAT_RFC3339 "Y-m-d\\TH:i:sP"
2006-05-30 21:12:21 +08:00
2005-07-20 16:31:02 +08:00
# define DATE_FORMAT_ISO8601 "Y-m-d\\TH:i:sO"
2005-10-19 19:18:51 +08:00
# define DATE_TZ_ERRMSG \
" It is not safe to rely on the system's timezone settings. Please use " \
" the date.timezone setting, the TZ environment variable or the " \
2005-12-21 03:54:10 +08:00
" date_default_timezone_set() function. In case you used any of those " \
" methods and you are still getting this warning, you most likely " \
" misspelled the timezone identifier. "
2005-10-19 19:18:51 +08:00
2006-01-05 05:31:35 +08:00
# define SUNFUNCS_RET_TIMESTAMP 0
# define SUNFUNCS_RET_STRING 1
# define SUNFUNCS_RET_DOUBLE 2
2005-07-05 05:27:26 +08:00
/* {{{ PHP_MINIT_FUNCTION */
2005-06-15 05:32:29 +08:00
PHP_MINIT_FUNCTION ( date )
{
2005-06-19 04:23:19 +08:00
ZEND_INIT_MODULE_GLOBALS ( date , php_date_init_globals , NULL ) ;
2005-06-15 05:32:29 +08:00
REGISTER_INI_ENTRIES ( ) ;
2005-11-27 14:51:43 +08:00
# ifdef EXPERIMENTAL_DATE_SUPPORT
2005-11-18 05:05:30 +08:00
date_register_classes ( TSRMLS_C ) ;
2005-11-27 14:51:43 +08:00
# endif
2006-05-30 22:46:46 +08:00
/*
* RFC4287 , Section 3.3 : http : //www.ietf.org/rfc/rfc4287.txt
2006-05-30 23:14:22 +08:00
* A Date construct is an element whose content MUST conform to the
* " date-time " production in [ RFC3339 ] . In addition , an uppercase " T "
* character MUST be used to separate date and time , and an uppercase
* " Z " character MUST be present in the absence of a numeric time zone offset .
2006-05-30 22:46:46 +08:00
*/
2006-02-01 02:44:19 +08:00
REGISTER_STRING_CONSTANT ( " DATE_ATOM " , DATE_FORMAT_RFC3339 , CONST_CS | CONST_PERSISTENT ) ;
2006-05-30 22:46:46 +08:00
/*
* Preliminary specification : http : //wp.netscape.com/newsref/std/cookie_spec.html
* " This is based on RFC 822, RFC 850, RFC 1036, and RFC 1123,
* with the variations that the only legal time zone is GMT
* and the separators between the elements of the date must be dashes . "
*/
REGISTER_STRING_CONSTANT ( " DATE_COOKIE " , DATE_FORMAT_RFC850 , CONST_CS | CONST_PERSISTENT ) ;
2005-11-27 14:51:43 +08:00
REGISTER_STRING_CONSTANT ( " DATE_ISO8601 " , DATE_FORMAT_ISO8601 , CONST_CS | CONST_PERSISTENT ) ;
2006-05-30 21:12:21 +08:00
REGISTER_STRING_CONSTANT ( " DATE_RFC822 " , DATE_FORMAT_RFC822 , CONST_CS | CONST_PERSISTENT ) ;
REGISTER_STRING_CONSTANT ( " DATE_RFC850 " , DATE_FORMAT_RFC850 , CONST_CS | CONST_PERSISTENT ) ;
2005-11-27 14:51:43 +08:00
REGISTER_STRING_CONSTANT ( " DATE_RFC1036 " , DATE_FORMAT_RFC1036 , CONST_CS | CONST_PERSISTENT ) ;
REGISTER_STRING_CONSTANT ( " DATE_RFC1123 " , DATE_FORMAT_RFC1123 , CONST_CS | CONST_PERSISTENT ) ;
REGISTER_STRING_CONSTANT ( " DATE_RFC2822 " , DATE_FORMAT_RFC2822 , CONST_CS | CONST_PERSISTENT ) ;
2006-04-12 02:03:52 +08:00
REGISTER_STRING_CONSTANT ( " DATE_RFC3339 " , DATE_FORMAT_RFC3339 , CONST_CS | CONST_PERSISTENT ) ;
2006-05-30 22:46:46 +08:00
/*
* RSS 2.0 Specification : http : //blogs.law.harvard.edu/tech/rss
2006-05-30 23:14:22 +08:00
* " All date-times in RSS conform to the Date and Time Specification of RFC 822,
* with the exception that the year may be expressed with two characters or four characters ( four preferred ) "
2006-05-30 22:46:46 +08:00
*/
2006-05-30 23:14:22 +08:00
REGISTER_STRING_CONSTANT ( " DATE_RSS " , DATE_FORMAT_RFC1123 , CONST_CS | CONST_PERSISTENT ) ;
2006-03-03 15:52:55 +08:00
REGISTER_STRING_CONSTANT ( " DATE_W3C " , DATE_FORMAT_RFC3339 , CONST_CS | CONST_PERSISTENT ) ;
2005-07-20 16:31:02 +08:00
2006-01-05 05:31:35 +08:00
REGISTER_LONG_CONSTANT ( " SUNFUNCS_RET_TIMESTAMP " , SUNFUNCS_RET_TIMESTAMP , CONST_CS | CONST_PERSISTENT ) ;
REGISTER_LONG_CONSTANT ( " SUNFUNCS_RET_STRING " , SUNFUNCS_RET_STRING , CONST_CS | CONST_PERSISTENT ) ;
REGISTER_LONG_CONSTANT ( " SUNFUNCS_RET_DOUBLE " , SUNFUNCS_RET_DOUBLE , CONST_CS | CONST_PERSISTENT ) ;
2005-10-03 19:17:28 +08:00
php_date_global_timezone_db = NULL ;
php_date_global_timezone_db_enabled = 0 ;
2005-06-15 05:32:29 +08:00
return SUCCESS ;
}
2005-07-05 05:27:26 +08:00
/* }}} */
2005-06-15 05:32:29 +08:00
2005-07-05 05:27:26 +08:00
/* {{{ PHP_MSHUTDOWN_FUNCTION */
2005-06-15 05:32:29 +08:00
PHP_MSHUTDOWN_FUNCTION ( date )
{
UNREGISTER_INI_ENTRIES ( ) ;
return SUCCESS ;
}
2005-07-05 05:27:26 +08:00
/* }}} */
2005-06-15 05:32:29 +08:00
2005-07-05 05:27:26 +08:00
/* {{{ PHP_MINFO_FUNCTION */
2005-06-15 05:32:29 +08:00
PHP_MINFO_FUNCTION ( date )
{
2006-05-15 01:36:05 +08:00
const timelib_tzdb * tzdb = DATE_TIMEZONEDB ;
2005-10-03 19:17:28 +08:00
2005-06-15 05:32:29 +08:00
php_info_print_table_start ( ) ;
php_info_print_table_row ( 2 , " date/time support " , " enabled " ) ;
2005-10-03 19:17:28 +08:00
php_info_print_table_row ( 2 , " Timezone Database Version " , tzdb - > version ) ;
php_info_print_table_row ( 2 , " Timezone Database " , php_date_global_timezone_db_enabled ? " external " : " internal " ) ;
2005-12-21 03:54:10 +08:00
php_info_print_table_row ( 2 , " Default timezone " , guess_timezone ( tzdb TSRMLS_CC ) ) ;
2005-06-15 05:32:29 +08:00
php_info_print_table_end ( ) ;
2005-08-10 05:10:22 +08:00
DISPLAY_INI_ENTRIES ( ) ;
2005-06-15 05:32:29 +08:00
}
2005-07-05 05:27:26 +08:00
/* }}} */
2005-06-15 05:32:29 +08:00
2005-10-05 16:20:44 +08:00
/* {{{ Timezone Cache functions */
2006-05-15 01:36:05 +08:00
static timelib_tzinfo * php_date_parse_tzfile ( char * formal_tzname , const timelib_tzdb * tzdb TSRMLS_DC )
2005-10-05 16:20:44 +08:00
{
timelib_tzinfo * tzi , * * ptzi ;
2005-10-07 21:33:31 +08:00
if ( zend_hash_find ( & DATEG ( tzcache ) , formal_tzname , strlen ( formal_tzname ) + 1 , ( void * * ) & ptzi ) = = SUCCESS ) {
2005-10-05 16:20:44 +08:00
return * ptzi ;
}
2005-10-07 21:33:31 +08:00
tzi = timelib_parse_tzfile ( formal_tzname , tzdb ) ;
2005-10-13 03:49:59 +08:00
if ( tzi ) {
zend_hash_add ( & DATEG ( tzcache ) , formal_tzname , strlen ( formal_tzname ) + 1 , ( void * ) & tzi , sizeof ( timelib_tzinfo * ) , NULL ) ;
}
2005-10-05 16:20:44 +08:00
return tzi ;
}
/* }}} */
2005-07-01 05:38:06 +08:00
2005-07-05 05:27:26 +08:00
/* {{{ Helper functions */
2006-05-15 01:36:05 +08:00
static char * guess_timezone ( const timelib_tzdb * tzdb TSRMLS_DC )
2005-07-01 05:38:06 +08:00
{
char * env ;
2005-07-03 05:19:25 +08:00
/* Checking configure timezone */
2005-12-21 03:58:44 +08:00
if ( DATEG ( timezone ) & & ( strlen ( DATEG ( timezone ) ) > 0 ) ) {
2005-07-03 05:19:25 +08:00
return DATEG ( timezone ) ;
}
/* Check environment variable */
2005-07-01 05:38:06 +08:00
env = getenv ( " TZ " ) ;
2005-12-21 03:54:10 +08:00
if ( env & & * env & & timelib_timezone_id_is_valid ( env , tzdb ) ) {
2005-07-01 05:38:06 +08:00
return env ;
}
2005-07-03 05:19:25 +08:00
/* Check config setting for default timezone */
2005-12-21 03:54:10 +08:00
if ( DATEG ( default_timezone ) & & ( strlen ( DATEG ( default_timezone ) ) > 0 ) & & timelib_timezone_id_is_valid ( DATEG ( default_timezone ) , tzdb ) ) {
2005-07-01 05:38:06 +08:00
return DATEG ( default_timezone ) ;
}
2005-07-03 23:01:29 +08:00
# if HAVE_TM_ZONE
/* Try to guess timezone from system information */
{
struct tm * ta , tmbuf ;
time_t the_time ;
char * tzid ;
the_time = time ( NULL ) ;
ta = php_localtime_r ( & the_time , & tmbuf ) ;
2005-10-01 23:04:07 +08:00
tzid = timelib_timezone_id_from_abbr ( ta - > tm_zone , ta - > tm_gmtoff , ta - > tm_isdst ) ;
2005-07-03 23:01:29 +08:00
if ( ! tzid ) {
tzid = " UTC " ;
}
2005-10-19 19:18:51 +08:00
php_error_docref ( NULL TSRMLS_CC , E_STRICT , DATE_TZ_ERRMSG " We selected '%s' for '%s/%.1f/%s' instead " , tzid , ta - > tm_zone , ( float ) ( ta - > tm_gmtoff / 3600 ) , ta - > tm_isdst ? " DST " : " no DST " ) ;
2005-07-03 23:01:29 +08:00
return tzid ;
}
2005-10-05 16:20:44 +08:00
# endif
# ifdef PHP_WIN32
{
2005-10-05 19:06:56 +08:00
char * tzid ;
2005-10-05 16:20:44 +08:00
TIME_ZONE_INFORMATION tzi ;
switch ( GetTimeZoneInformation ( & tzi ) )
{
2005-10-16 02:12:29 +08:00
/* no DST or not in effect */
2005-10-05 16:20:44 +08:00
case TIME_ZONE_ID_UNKNOWN :
case TIME_ZONE_ID_STANDARD :
2005-10-16 02:12:29 +08:00
php_win_std_time :
2005-10-05 19:06:56 +08:00
tzid = timelib_timezone_id_from_abbr ( " " , ( tzi . Bias + tzi . StandardBias ) * - 60 , 0 ) ;
if ( ! tzid ) {
tzid = " UTC " ;
}
2005-10-19 19:18:51 +08:00
php_error_docref ( NULL TSRMLS_CC , E_STRICT , DATE_TZ_ERRMSG " We selected '%s' for '%.1f/no DST' instead " , tzid , ( ( tzi . Bias + tzi . StandardBias ) / - 60.0 ) ) ;
2005-10-05 16:20:44 +08:00
break ;
2005-10-16 02:12:29 +08:00
/* DST in effect */
2005-10-05 16:23:39 +08:00
case TIME_ZONE_ID_DAYLIGHT :
2005-10-16 02:12:29 +08:00
/* If user has disabled DST in the control panel, Windows returns 0 here */
if ( tzi . DaylightBias = = 0 ) {
goto php_win_std_time ;
}
2005-10-05 19:06:56 +08:00
tzid = timelib_timezone_id_from_abbr ( " " , ( tzi . Bias + tzi . DaylightBias ) * - 60 , 1 ) ;
if ( ! tzid ) {
tzid = " UTC " ;
}
2005-10-19 19:18:51 +08:00
php_error_docref ( NULL TSRMLS_CC , E_STRICT , DATE_TZ_ERRMSG " We selected '%s' for '%.1f/DST' instead " , tzid , ( ( tzi . Bias + tzi . DaylightBias ) / - 60.0 ) ) ;
2005-10-05 16:20:44 +08:00
break ;
}
2005-10-08 04:32:17 +08:00
return tzid ;
2005-10-05 16:20:44 +08:00
}
2005-07-03 23:01:29 +08:00
# endif
2005-07-03 05:19:25 +08:00
/* Fallback to UTC */
2005-10-19 19:18:51 +08:00
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 " ) ;
2005-07-03 05:19:25 +08:00
return " UTC " ;
}
2005-11-21 04:14:24 +08:00
PHPAPI timelib_tzinfo * get_timezone_info ( TSRMLS_D )
2005-07-03 05:19:25 +08:00
{
char * tz ;
timelib_tzinfo * tzi ;
2005-12-21 03:54:10 +08:00
tz = guess_timezone ( DATE_TIMEZONEDB TSRMLS_CC ) ;
2005-10-05 19:06:56 +08:00
tzi = php_date_parse_tzfile ( tz , DATE_TIMEZONEDB TSRMLS_CC ) ;
2005-07-03 05:19:25 +08:00
if ( ! tzi ) {
2005-12-21 03:54:10 +08:00
php_error_docref ( NULL TSRMLS_CC , E_ERROR , " Timezone database is corrupt - this should *never* happen! " ) ;
2005-07-03 05:19:25 +08:00
}
return tzi ;
2005-07-01 05:38:06 +08:00
}
2005-07-05 05:27:26 +08:00
/* }}} */
2005-07-01 05:38:06 +08:00
2005-07-05 05:27:26 +08:00
/* {{{ date() and gmdate() data */
2005-07-01 05:38:06 +08:00
# include "ext/standard/php_smart_str.h"
static char * mon_full_names [ ] = {
" January " , " February " , " March " , " April " ,
" May " , " June " , " July " , " August " ,
" September " , " October " , " November " , " December "
} ;
static char * mon_short_names [ ] = {
" Jan " , " Feb " , " Mar " , " Apr " , " May " , " Jun " , " Jul " , " Aug " , " Sep " , " Oct " , " Nov " , " Dec "
} ;
static char * day_full_names [ ] = {
" Sunday " , " Monday " , " Tuesday " , " Wednesday " , " Thursday " , " Friday " , " Saturday "
} ;
static char * day_short_names [ ] = {
" Sun " , " Mon " , " Tue " , " Wed " , " Thu " , " Fri " , " Sat "
} ;
2005-08-25 17:47:28 +08:00
static char * english_suffix ( timelib_sll number )
2005-07-01 05:38:06 +08:00
{
if ( number > = 10 & & number < = 19 ) {
return " th " ;
} else {
switch ( number % 10 ) {
case 1 : return " st " ;
case 2 : return " nd " ;
case 3 : return " rd " ;
}
}
return " th " ;
}
2005-07-05 05:27:26 +08:00
/* }}} */
2005-07-01 05:38:06 +08:00
2005-07-08 20:26:30 +08:00
/* {{{ date_format - (gm)date helper */
static char * date_format ( char * format , int format_len , timelib_time * t , int localtime )
2005-07-01 05:38:06 +08:00
{
smart_str string = { 0 } ;
int i ;
char buffer [ 33 ] ;
timelib_time_offset * offset ;
timelib_sll isoweek , isoyear ;
2006-02-01 02:44:19 +08:00
int rfc_colon = 0 ;
2005-07-01 05:38:06 +08:00
2005-08-09 00:49:30 +08:00
if ( ! format_len ) {
return estrdup ( " " ) ;
}
2005-07-01 05:38:06 +08:00
if ( localtime ) {
2005-07-20 16:31:02 +08:00
if ( t - > zone_type = = TIMELIB_ZONETYPE_ABBR ) {
offset = timelib_time_offset_ctor ( ) ;
offset - > offset = ( t - > z - ( t - > dst * 60 ) ) * - 60 ;
offset - > leap_secs = 0 ;
offset - > is_dst = t - > dst ;
offset - > abbr = strdup ( t - > tz_abbr ) ;
} else if ( t - > zone_type = = TIMELIB_ZONETYPE_OFFSET ) {
offset = timelib_time_offset_ctor ( ) ;
offset - > offset = ( t - > z - ( t - > dst * 60 ) ) * - 60 ;
offset - > leap_secs = 0 ;
offset - > is_dst = t - > dst ;
offset - > abbr = malloc ( 9 ) ; /* GMT<4D> xxxx\0 */
snprintf ( offset - > abbr , 9 , " GMT%c%02d%02d " ,
localtime ? ( ( offset - > offset < 0 ) ? ' - ' : ' + ' ) : ' + ' ,
localtime ? abs ( offset - > offset / 3600 ) : 0 ,
localtime ? abs ( ( offset - > offset % 3600 ) / 60 ) : 0 ) ;
} else {
offset = timelib_get_time_zone_info ( t - > sse , t - > tz_info ) ;
}
2005-07-01 05:38:06 +08:00
}
buffer [ 32 ] = ' \0 ' ;
timelib_isoweek_from_date ( t - > y , t - > m , t - > d , & isoweek , & isoyear ) ;
for ( i = 0 ; i < format_len ; i + + ) {
switch ( format [ i ] ) {
/* day */
2005-07-01 06:47:39 +08:00
case ' d ' : snprintf ( buffer , 32 , " %02d " , ( int ) t - > d ) ; break ;
case ' D ' : snprintf ( buffer , 32 , " %s " , day_short_names [ timelib_day_of_week ( t - > y , t - > m , t - > d ) ] ) ; break ;
case ' j ' : snprintf ( buffer , 32 , " %d " , ( int ) t - > d ) ; break ;
case ' l ' : snprintf ( buffer , 32 , " %s " , day_full_names [ timelib_day_of_week ( t - > y , t - > m , t - > d ) ] ) ; break ;
case ' S ' : snprintf ( buffer , 32 , " %s " , english_suffix ( t - > d ) ) ; break ;
case ' w ' : snprintf ( buffer , 32 , " %d " , ( int ) timelib_day_of_week ( t - > y , t - > m , t - > d ) ) ; break ;
2005-09-02 17:33:08 +08:00
case ' N ' : snprintf ( buffer , 32 , " %d " , ( int ) timelib_iso_day_of_week ( t - > y , t - > m , t - > d ) ) ; break ;
2005-07-01 06:47:39 +08:00
case ' z ' : snprintf ( buffer , 32 , " %d " , ( int ) timelib_day_of_year ( t - > y , t - > m , t - > d ) ) ; break ;
2005-07-01 05:38:06 +08:00
/* week */
2005-08-30 17:17:09 +08:00
case ' W ' : snprintf ( buffer , 32 , " %02d " , ( int ) isoweek ) ; break ; /* iso weeknr */
2005-07-01 06:47:39 +08:00
case ' o ' : snprintf ( buffer , 32 , " %d " , ( int ) isoyear ) ; break ; /* iso year */
2005-07-01 05:38:06 +08:00
/* month */
2005-07-01 06:47:39 +08:00
case ' F ' : snprintf ( buffer , 32 , " %s " , mon_full_names [ t - > m - 1 ] ) ; break ;
case ' m ' : snprintf ( buffer , 32 , " %02d " , ( int ) t - > m ) ; break ;
case ' M ' : snprintf ( buffer , 32 , " %s " , mon_short_names [ t - > m - 1 ] ) ; break ;
case ' n ' : snprintf ( buffer , 32 , " %d " , ( int ) t - > m ) ; break ;
case ' t ' : snprintf ( buffer , 32 , " %d " , ( int ) timelib_days_in_month ( t - > y , t - > m ) ) ; break ;
2005-07-01 05:38:06 +08:00
/* year */
2005-07-01 06:47:39 +08:00
case ' L ' : snprintf ( buffer , 32 , " %d " , timelib_is_leap ( ( int ) t - > y ) ) ; break ;
case ' y ' : snprintf ( buffer , 32 , " %02d " , ( int ) t - > y % 100 ) ; break ;
case ' Y ' : snprintf ( buffer , 32 , " %04d " , ( int ) t - > y ) ; break ;
2005-07-01 05:38:06 +08:00
/* time */
2005-07-01 06:47:39 +08:00
case ' a ' : snprintf ( buffer , 32 , " %s " , t - > h > = 12 ? " pm " : " am " ) ; break ;
case ' A ' : snprintf ( buffer , 32 , " %s " , t - > h > = 12 ? " PM " : " AM " ) ; break ;
2005-11-30 04:43:53 +08:00
case ' B ' : {
int retval = ( ( ( ( ( long ) t - > sse ) - ( ( ( long ) t - > sse ) - ( ( ( ( long ) t - > sse ) % 86400 ) + 3600 ) ) ) * 10 ) / 864 ) ;
while ( retval < 0 ) {
retval + = 1000 ;
}
retval = retval % 1000 ;
snprintf ( buffer , 32 , " %03d " , retval ) ; break ;
break ;
}
2005-07-01 06:47:39 +08:00
case ' g ' : snprintf ( buffer , 32 , " %d " , ( t - > h % 12 ) ? ( int ) t - > h % 12 : 12 ) ; break ;
case ' G ' : snprintf ( buffer , 32 , " %d " , ( int ) t - > h ) ; break ;
case ' h ' : snprintf ( buffer , 32 , " %02d " , ( t - > h % 12 ) ? ( int ) t - > h % 12 : 12 ) ; break ;
case ' H ' : snprintf ( buffer , 32 , " %02d " , ( int ) t - > h ) ; break ;
case ' i ' : snprintf ( buffer , 32 , " %02d " , ( int ) t - > i ) ; break ;
case ' s ' : snprintf ( buffer , 32 , " %02d " , ( int ) t - > s ) ; break ;
2005-07-01 05:38:06 +08:00
/* timezone */
2005-07-01 06:47:39 +08:00
case ' I ' : snprintf ( buffer , 32 , " %d " , localtime ? offset - > is_dst : 0 ) ; break ;
2006-02-01 02:44:19 +08:00
case ' P ' : rfc_colon = 1 ; /* break intentionally missing */
case ' O ' : snprintf ( buffer , 32 , " %c%02d%s%02d " ,
2005-07-01 05:38:06 +08:00
localtime ? ( ( offset - > offset < 0 ) ? ' - ' : ' + ' ) : ' + ' ,
localtime ? abs ( offset - > offset / 3600 ) : 0 ,
2006-02-01 02:44:19 +08:00
rfc_colon ? " : " : " " ,
2005-07-01 05:38:06 +08:00
localtime ? abs ( ( offset - > offset % 3600 ) / 60 ) : 0
) ;
break ;
2005-07-01 06:47:39 +08:00
case ' T ' : snprintf ( buffer , 32 , " %s " , localtime ? offset - > abbr : " GMT " ) ; break ;
case ' e ' : snprintf ( buffer , 32 , " %s " , localtime ? t - > tz_info - > name : " UTC " ) ; break ;
case ' Z ' : snprintf ( buffer , 32 , " %d " , localtime ? offset - > offset : 0 ) ; break ;
2005-07-01 05:38:06 +08:00
/* full date/time */
2005-07-01 06:47:39 +08:00
case ' c ' : snprintf ( buffer , 32 , " %04d-%02d-%02dT%02d:%02d:%02d%c%02d:%02d " ,
2005-07-01 05:38:06 +08:00
( int ) t - > y , ( int ) t - > m , ( int ) t - > d ,
( int ) t - > h , ( int ) t - > i , ( int ) t - > s ,
localtime ? ( ( offset - > offset < 0 ) ? ' - ' : ' + ' ) : ' + ' ,
localtime ? abs ( offset - > offset / 3600 ) : 0 ,
localtime ? abs ( ( offset - > offset % 3600 ) / 60 ) : 0
) ;
break ;
2005-07-01 06:47:39 +08:00
case ' r ' : snprintf ( buffer , 32 , " %3s, %02d %3s %04d %02d:%02d:%02d %c%02d%02d " ,
2005-07-01 05:38:06 +08:00
day_short_names [ timelib_day_of_week ( t - > y , t - > m , t - > d ) ] ,
( int ) t - > d , mon_short_names [ t - > m - 1 ] ,
( int ) t - > y , ( int ) t - > h , ( int ) t - > i , ( int ) t - > s ,
localtime ? ( ( offset - > offset < 0 ) ? ' - ' : ' + ' ) : ' + ' ,
localtime ? abs ( offset - > offset / 3600 ) : 0 ,
localtime ? abs ( ( offset - > offset % 3600 ) / 60 ) : 0
) ;
break ;
2005-07-01 16:59:57 +08:00
case ' U ' : snprintf ( buffer , 32 , " %lld " , ( timelib_sll ) t - > sse ) ; break ;
2005-07-01 05:38:06 +08:00
case ' \\ ' : if ( i < format_len ) i + + ; buffer [ 0 ] = format [ i ] ; buffer [ 1 ] = ' \0 ' ; break ;
default : buffer [ 0 ] = format [ i ] ; buffer [ 1 ] = ' \0 ' ;
}
smart_str_appends ( & string , buffer ) ;
buffer [ 0 ] = ' \0 ' ;
}
smart_str_0 ( & string ) ;
2005-07-01 07:33:37 +08:00
if ( localtime ) {
timelib_time_offset_dtor ( offset ) ;
}
2005-07-01 05:38:06 +08:00
return string . c ;
}
static void php_date ( INTERNAL_FUNCTION_PARAMETERS , int localtime )
{
2005-10-05 16:20:44 +08:00
char * format ;
int format_len ;
2005-12-29 18:54:07 +08:00
long ts ;
2005-10-05 16:20:44 +08:00
char * string ;
2005-07-01 05:38:06 +08:00
2005-10-05 16:20:44 +08:00
if ( ZEND_NUM_ARGS ( ) = = 1 ) {
ts = time ( NULL ) ;
}
2005-07-01 05:38:06 +08:00
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " s|l " , & format , & format_len , & ts ) = = FAILURE ) {
RETURN_FALSE ;
}
2005-07-09 02:16:46 +08:00
string = php_format_date ( format , format_len , ts , localtime TSRMLS_CC ) ;
2005-07-08 20:26:30 +08:00
RETVAL_STRING ( string , 0 ) ;
}
/* }}} */
2005-08-25 17:47:28 +08:00
PHPAPI char * php_format_date ( char * format , int format_len , time_t ts , int localtime TSRMLS_DC ) /* { { { */
2005-07-08 20:26:30 +08:00
{
timelib_time * t ;
timelib_tzinfo * tzi ;
char * string ;
2005-07-01 06:44:28 +08:00
t = timelib_time_ctor ( ) ;
2005-07-01 05:38:06 +08:00
if ( localtime ) {
2005-07-03 05:19:25 +08:00
tzi = get_timezone_info ( TSRMLS_C ) ;
2005-12-19 21:00:37 +08:00
t - > tz_info = tzi ;
t - > zone_type = TIMELIB_ZONETYPE_ID ;
timelib_unixtime2local ( t , ts ) ;
2005-07-01 05:38:06 +08:00
} else {
tzi = NULL ;
timelib_unixtime2gmt ( t , ts ) ;
}
2005-07-08 20:26:30 +08:00
string = date_format ( format , format_len , t , localtime ) ;
2005-07-01 05:38:06 +08:00
timelib_time_dtor ( t ) ;
2005-07-08 20:26:30 +08:00
return string ;
2005-07-01 05:38:06 +08:00
}
2005-07-05 05:27:26 +08:00
/* }}} */
2005-07-01 05:38:06 +08:00
2005-11-30 04:19:56 +08:00
/* {{{ php_idate
*/
PHPAPI int php_idate ( char format , time_t ts , int localtime )
{
timelib_time * t ;
timelib_tzinfo * tzi ;
int retval = - 1 ;
timelib_time_offset * offset ;
timelib_sll isoweek , isoyear ;
t = timelib_time_ctor ( ) ;
if ( ! localtime ) {
TSRMLS_FETCH ( ) ;
tzi = get_timezone_info ( TSRMLS_C ) ;
2005-12-19 21:00:37 +08:00
t - > tz_info = tzi ;
t - > zone_type = TIMELIB_ZONETYPE_ID ;
timelib_unixtime2local ( t , ts ) ;
2005-11-30 04:19:56 +08:00
} else {
tzi = NULL ;
timelib_unixtime2gmt ( t , ts ) ;
}
if ( ! localtime ) {
if ( t - > zone_type = = TIMELIB_ZONETYPE_ABBR ) {
offset = timelib_time_offset_ctor ( ) ;
offset - > offset = ( t - > z - ( t - > dst * 60 ) ) * - 60 ;
offset - > leap_secs = 0 ;
offset - > is_dst = t - > dst ;
offset - > abbr = strdup ( t - > tz_abbr ) ;
} else if ( t - > zone_type = = TIMELIB_ZONETYPE_OFFSET ) {
offset = timelib_time_offset_ctor ( ) ;
offset - > offset = ( t - > z - ( t - > dst * 60 ) ) * - 60 ;
offset - > leap_secs = 0 ;
offset - > is_dst = t - > dst ;
offset - > abbr = malloc ( 9 ) ; /* GMT<4D> xxxx\0 */
snprintf ( offset - > abbr , 9 , " GMT%c%02d%02d " ,
! localtime ? ( ( offset - > offset < 0 ) ? ' - ' : ' + ' ) : ' + ' ,
! localtime ? abs ( offset - > offset / 3600 ) : 0 ,
! localtime ? abs ( ( offset - > offset % 3600 ) / 60 ) : 0 ) ;
} else {
offset = timelib_get_time_zone_info ( t - > sse , t - > tz_info ) ;
}
}
timelib_isoweek_from_date ( t - > y , t - > m , t - > d , & isoweek , & isoyear ) ;
switch ( format ) {
/* day */
case ' d ' : case ' j ' : retval = ( int ) t - > d ; break ;
case ' w ' : retval = ( int ) timelib_day_of_week ( t - > y , t - > m , t - > d ) ; break ;
case ' z ' : retval = ( int ) timelib_day_of_year ( t - > y , t - > m , t - > d ) ; break ;
/* week */
case ' W ' : retval = ( int ) isoweek ; break ; /* iso weeknr */
/* month */
case ' m ' : case ' n ' : retval = ( int ) t - > m ; break ;
case ' t ' : retval = ( int ) timelib_days_in_month ( t - > y , t - > m ) ; break ;
/* year */
case ' L ' : retval = ( int ) timelib_is_leap ( ( int ) t - > y ) ; break ;
case ' y ' : retval = ( int ) ( t - > y % 100 ) ; break ;
case ' Y ' : retval = ( int ) t - > y ; break ;
/* Swatch Beat a.k.a. Internet Time */
case ' B ' :
retval = ( ( ( ( ( long ) t - > sse ) - ( ( ( long ) t - > sse ) - ( ( ( ( long ) t - > sse ) % 86400 ) + 3600 ) ) ) * 10 ) / 864 ) ;
while ( retval < 0 ) {
retval + = 1000 ;
}
retval = retval % 1000 ;
break ;
/* time */
case ' g ' : case ' h ' : retval = ( int ) ( ( t - > h % 12 ) ? ( int ) t - > h % 12 : 12 ) ; break ;
case ' H ' : case ' G ' : retval = ( int ) t - > h ; break ;
case ' i ' : retval = ( int ) t - > i ; break ;
case ' s ' : retval = ( int ) t - > s ; break ;
/* timezone */
case ' I ' : retval = ( int ) ( ! localtime ? offset - > is_dst : 0 ) ; break ;
case ' Z ' : retval = ( int ) ( ! localtime ? offset - > offset : 0 ) ; break ;
case ' U ' : retval = ( int ) t - > sse ; break ;
}
if ( ! localtime ) {
timelib_time_offset_dtor ( offset ) ;
}
timelib_time_dtor ( t ) ;
return retval ;
}
/* }}} */
2005-07-05 05:27:26 +08:00
/* {{{ proto string date(string format [, long timestamp])
Format a local date / time */
2005-07-01 05:38:06 +08:00
PHP_FUNCTION ( date )
{
php_date ( INTERNAL_FUNCTION_PARAM_PASSTHRU , 1 ) ;
}
2005-07-05 05:27:26 +08:00
/* }}} */
2005-07-01 05:38:06 +08:00
2005-07-05 05:27:26 +08:00
/* {{{ proto string gmdate(string format [, long timestamp])
Format a GMT date / time */
2005-07-01 05:38:06 +08:00
PHP_FUNCTION ( gmdate )
{
php_date ( INTERNAL_FUNCTION_PARAM_PASSTHRU , 0 ) ;
}
2005-07-05 05:27:26 +08:00
/* }}} */
2005-07-01 05:38:06 +08:00
2005-11-30 04:19:56 +08:00
/* {{{ proto int idate(string format [, int timestamp])
Format a local time / date as integer */
PHP_FUNCTION ( idate )
{
char * format ;
int format_len ;
2005-12-29 18:54:07 +08:00
long ts ;
2005-11-30 07:10:15 +08:00
int ret ;
2005-11-30 04:19:56 +08:00
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " s|l " , & format , & format_len , & ts ) = = FAILURE ) {
RETURN_FALSE ;
}
if ( format_len ! = 1 ) {
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " idate format is one char " ) ;
RETURN_FALSE ;
}
if ( ZEND_NUM_ARGS ( ) = = 1 ) {
ts = time ( NULL ) ;
}
2005-11-30 07:10:15 +08:00
ret = php_idate ( format [ 0 ] , ts , 0 ) ;
if ( ret = = - 1 ) {
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " Unrecognized date format token. " ) ;
RETURN_FALSE ;
}
RETURN_LONG ( ret ) ;
2005-11-30 04:19:56 +08:00
}
/* }}} */
2005-10-03 19:17:28 +08:00
/* {{{ php_date_set_tzdb - NOT THREADSAFE */
PHPAPI void php_date_set_tzdb ( timelib_tzdb * tzdb )
{
2006-05-15 01:36:05 +08:00
const timelib_tzdb * builtin = timelib_builtin_db ( ) ;
2005-10-03 19:34:51 +08:00
if ( php_version_compare ( tzdb - > version , builtin - > version ) > 0 ) {
php_date_global_timezone_db = tzdb ;
php_date_global_timezone_db_enabled = 1 ;
}
2005-10-03 19:17:28 +08:00
}
/* }}} */
2005-07-05 05:27:26 +08:00
/* {{{ php_parse_date: Backwards compability function */
2006-01-28 14:18:01 +08:00
PHPAPI signed long php_parse_date ( char * string , signed long * now )
2005-06-20 06:15:27 +08:00
{
timelib_time * parsed_time ;
2006-04-12 02:03:52 +08:00
int error2 ;
2005-06-20 06:15:27 +08:00
signed long retval ;
2006-04-12 02:03:52 +08:00
parsed_time = timelib_strtotime ( string , strlen ( string ) , NULL , DATE_TIMEZONEDB ) ;
2005-06-20 06:15:27 +08:00
timelib_update_ts ( parsed_time , NULL ) ;
2005-07-04 05:38:54 +08:00
retval = timelib_date_to_int ( parsed_time , & error2 ) ;
2005-06-20 06:15:27 +08:00
timelib_time_dtor ( parsed_time ) ;
2006-04-12 02:03:52 +08:00
if ( error2 ) {
2005-06-20 06:15:27 +08:00
return - 1 ;
}
return retval ;
}
2005-07-05 05:27:26 +08:00
/* }}} */
2005-06-20 06:15:27 +08:00
2005-06-15 05:32:29 +08:00
2006-04-12 02:03:52 +08:00
/* {{{ proto int strtotime(string time [, int now ])
2005-06-15 05:32:29 +08:00
Convert string representation of date and time to a timestamp */
PHP_FUNCTION ( strtotime )
{
char * times , * initial_ts ;
2005-07-04 05:38:54 +08:00
int time_len , error1 , error2 ;
2006-04-12 02:03:52 +08:00
struct timelib_error_container * error ;
2005-06-15 05:32:29 +08:00
long preset_ts , ts ;
timelib_time * t , * now ;
timelib_tzinfo * tzi ;
2005-07-03 05:19:25 +08:00
tzi = get_timezone_info ( TSRMLS_C ) ;
2005-06-15 05:32:29 +08:00
if ( zend_parse_parameters_ex ( ZEND_PARSE_PARAMS_QUIET , ZEND_NUM_ARGS ( ) TSRMLS_CC , " sl " , & times , & time_len , & preset_ts ) ! = FAILURE ) {
/* We have an initial timestamp */
now = timelib_time_ctor ( ) ;
initial_ts = emalloc ( 25 ) ;
2006-03-07 05:44:58 +08:00
snprintf ( initial_ts , 24 , " @%ld " , preset_ts ) ;
2006-04-12 02:03:52 +08:00
t = timelib_strtotime ( initial_ts , strlen ( initial_ts ) , NULL , DATE_TIMEZONEDB ) ; /* we ignore the error here, as this should never fail */
2005-06-15 05:32:29 +08:00
timelib_update_ts ( t , tzi ) ;
2005-12-19 21:00:37 +08:00
now - > tz_info = tzi ;
now - > zone_type = TIMELIB_ZONETYPE_ID ;
timelib_unixtime2local ( now , t - > sse ) ;
2005-06-15 05:32:29 +08:00
timelib_time_dtor ( t ) ;
efree ( initial_ts ) ;
} else if ( zend_parse_parameters_ex ( ZEND_PARSE_PARAMS_QUIET , ZEND_NUM_ARGS ( ) TSRMLS_CC , " s " , & times , & time_len ) ! = FAILURE ) {
/* We have no initial timestamp */
now = timelib_time_ctor ( ) ;
2005-12-19 21:00:37 +08:00
now - > tz_info = tzi ;
now - > zone_type = TIMELIB_ZONETYPE_ID ;
timelib_unixtime2local ( now , ( timelib_sll ) time ( NULL ) ) ;
2005-06-15 05:32:29 +08:00
} else {
RETURN_FALSE ;
}
2006-04-12 02:03:52 +08:00
t = timelib_strtotime ( times , time_len , & error , DATE_TIMEZONEDB ) ;
error1 = error - > error_count ;
timelib_error_container_dtor ( error ) ;
2005-06-15 05:32:29 +08:00
timelib_fill_holes ( t , now , 0 ) ;
timelib_update_ts ( t , tzi ) ;
2005-07-04 05:38:54 +08:00
ts = timelib_date_to_int ( t , & error2 ) ;
2005-06-15 07:40:57 +08:00
/* if tz_info is not a copy, avoid double free */
2005-12-19 21:00:37 +08:00
if ( now - > tz_info ! = tzi & & now - > tz_info ) {
2005-07-06 02:30:30 +08:00
timelib_tzinfo_dtor ( now - > tz_info ) ;
2005-06-15 07:40:57 +08:00
}
2005-07-06 02:30:30 +08:00
if ( t - > tz_info ! = tzi ) {
timelib_tzinfo_dtor ( t - > tz_info ) ;
2005-06-16 07:30:20 +08:00
}
2005-06-15 07:40:57 +08:00
timelib_time_dtor ( now ) ;
timelib_time_dtor ( t ) ;
2005-07-04 05:38:54 +08:00
if ( error1 | | error2 ) {
2005-06-15 05:32:29 +08:00
RETURN_FALSE ;
} else {
RETURN_LONG ( ts ) ;
}
}
/* }}} */
2005-07-05 05:27:26 +08:00
/* {{{ php_mktime - (gm)mktime helper */
2005-07-04 21:21:39 +08:00
PHPAPI void php_mktime ( INTERNAL_FUNCTION_PARAMETERS , int gmt )
2005-07-03 22:27:31 +08:00
{
2005-07-04 21:22:27 +08:00
long hou , min , sec , mon , day , yea , dst = - 1 ;
2005-07-03 22:27:31 +08:00
timelib_time * now ;
timelib_tzinfo * tzi ;
long ts , adjust_seconds = 0 ;
int error ;
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " |lllllll " , & hou , & min , & sec , & mon , & day , & yea , & dst ) = = FAILURE ) {
RETURN_FALSE ;
}
/* Initialize structure with current time */
now = timelib_time_ctor ( ) ;
if ( gmt ) {
timelib_unixtime2gmt ( now , ( timelib_sll ) time ( NULL ) ) ;
} else {
tzi = get_timezone_info ( TSRMLS_C ) ;
2005-12-19 21:00:37 +08:00
now - > tz_info = tzi ;
now - > zone_type = TIMELIB_ZONETYPE_ID ;
timelib_unixtime2local ( now , ( timelib_sll ) time ( NULL ) ) ;
2005-07-03 22:27:31 +08:00
}
/* Fill in the new data */
switch ( ZEND_NUM_ARGS ( ) ) {
case 7 :
/* break intentionally missing */
case 6 :
2005-07-21 18:09:40 +08:00
if ( yea > = 0 & & yea < 70 ) {
yea + = 2000 ;
2005-12-06 01:27:02 +08:00
} else if ( yea > = 70 & & yea < = 110 ) {
2005-07-21 18:09:40 +08:00
yea + = 1900 ;
}
2005-07-03 22:27:31 +08:00
now - > y = yea ;
/* break intentionally missing again */
case 5 :
now - > d = day ;
/* break missing intentionally here too */
case 4 :
now - > m = mon ;
/* and here */
case 3 :
now - > s = sec ;
/* yup, this break isn't here on purpose too */
case 2 :
now - > i = min ;
/* last intentionally missing break */
case 1 :
now - > h = hou ;
break ;
default :
2005-10-19 19:18:51 +08:00
php_error_docref ( NULL TSRMLS_CC , E_STRICT , " You should be using the time() function instead " ) ;
2005-07-03 22:27:31 +08:00
}
/* Update the timestamp */
if ( gmt ) {
timelib_update_ts ( now , NULL ) ;
} else {
timelib_update_ts ( now , tzi ) ;
}
/* Support for the deprecated is_dst parameter */
if ( dst ! = - 1 ) {
2005-10-19 19:18:51 +08:00
php_error_docref ( NULL TSRMLS_CC , E_STRICT , " The is_dst parameter is deprecated " ) ;
2005-07-03 22:27:31 +08:00
if ( gmt ) {
/* GMT never uses DST */
if ( dst = = 1 ) {
adjust_seconds = - 3600 ;
}
} else {
/* Figure out is_dst for current TS */
timelib_time_offset * tmp_offset ;
tmp_offset = timelib_get_time_zone_info ( now - > sse , tzi ) ;
if ( dst = = 1 & & tmp_offset - > is_dst = = 0 ) {
adjust_seconds = - 3600 ;
}
if ( dst = = 0 & & tmp_offset - > is_dst = = 1 ) {
adjust_seconds = + 3600 ;
}
2005-07-03 22:36:59 +08:00
timelib_time_offset_dtor ( tmp_offset ) ;
2005-07-03 22:27:31 +08:00
}
}
/* Clean up and return */
ts = timelib_date_to_int ( now , & error ) ;
ts + = adjust_seconds ;
timelib_time_dtor ( now ) ;
if ( error ) {
RETURN_FALSE ;
} else {
RETURN_LONG ( ts ) ;
}
}
2005-07-05 05:27:26 +08:00
/* }}} */
2005-07-03 22:27:31 +08:00
/* {{{ proto int mktime(int hour, int min, int sec, int mon, int day, int year)
Get UNIX timestamp for a date */
PHP_FUNCTION ( mktime )
{
php_mktime ( INTERNAL_FUNCTION_PARAM_PASSTHRU , 0 ) ;
}
/* }}} */
/* {{{ proto int gmmktime(int hour, int min, int sec, int mon, int day, int year)
Get UNIX timestamp for a GMT date */
PHP_FUNCTION ( gmmktime )
{
php_mktime ( INTERNAL_FUNCTION_PARAM_PASSTHRU , 1 ) ;
}
/* }}} */
2005-07-05 05:27:26 +08:00
2005-07-04 03:14:55 +08:00
/* {{{ proto bool checkdate(int month, int day, int year)
Returns true ( 1 ) if it is a valid date in gregorian calendar */
PHP_FUNCTION ( checkdate )
{
long m , d , y ;
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " lll " , & m , & d , & y ) = = FAILURE ) {
RETURN_FALSE ;
}
if ( y < 1 | | y > 32767 | | m < 1 | | m > 12 | | d < 1 | | d > timelib_days_in_month ( y , m ) ) {
RETURN_FALSE ;
}
RETURN_TRUE ; /* True : This month, day, year arguments are valid */
}
/* }}} */
2005-07-04 07:30:52 +08:00
# ifdef HAVE_STRFTIME
2005-07-05 05:27:26 +08:00
/* {{{ php_strftime - (gm)strftime helper */
2005-07-04 03:14:55 +08:00
PHPAPI void php_strftime ( INTERNAL_FUNCTION_PARAMETERS , int gmt )
{
char * format , * buf ;
int format_len ;
long timestamp ;
struct tm ta ;
int max_reallocs = 5 ;
size_t buf_len = 64 , real_len ;
timelib_time * ts ;
timelib_tzinfo * tzi ;
timelib_time_offset * offset ;
timestamp = ( long ) time ( NULL ) ;
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " s|l " , & format , & format_len , & timestamp ) = = FAILURE ) {
RETURN_FALSE ;
}
if ( format_len = = 0 ) {
RETURN_FALSE ;
}
ts = timelib_time_ctor ( ) ;
if ( gmt ) {
tzi = NULL ;
timelib_unixtime2gmt ( ts , ( timelib_sll ) timestamp ) ;
} else {
tzi = get_timezone_info ( TSRMLS_C ) ;
2005-12-19 21:00:37 +08:00
ts - > tz_info = tzi ;
ts - > zone_type = TIMELIB_ZONETYPE_ID ;
timelib_unixtime2local ( ts , ( timelib_sll ) timestamp ) ;
2005-07-04 03:14:55 +08:00
}
ta . tm_sec = ts - > s ;
ta . tm_min = ts - > i ;
ta . tm_hour = ts - > h ;
ta . tm_mday = ts - > d ;
ta . tm_mon = ts - > m - 1 ;
ta . tm_year = ts - > y - 1900 ;
ta . tm_wday = timelib_day_of_week ( ts - > y , ts - > m , ts - > d ) ;
ta . tm_yday = timelib_day_of_year ( ts - > y , ts - > m , ts - > d ) ;
if ( gmt ) {
ta . tm_isdst = 0 ;
# if HAVE_TM_GMTOFF
ta . tm_gmtoff = 0 ;
# endif
# if HAVE_TM_ZONE
ta . tm_zone = " GMT " ;
# endif
} else {
offset = timelib_get_time_zone_info ( timestamp , tzi ) ;
ta . tm_isdst = offset - > is_dst ;
# if HAVE_TM_GMTOFF
ta . tm_gmtoff = offset - > offset ;
# endif
# if HAVE_TM_ZONE
ta . tm_zone = offset - > abbr ;
# endif
}
buf = ( char * ) emalloc ( buf_len ) ;
while ( ( real_len = strftime ( buf , buf_len , format , & ta ) ) = = buf_len | | real_len = = 0 ) {
buf_len * = 2 ;
buf = ( char * ) erealloc ( buf , buf_len ) ;
if ( ! - - max_reallocs ) {
break ;
}
}
timelib_time_dtor ( ts ) ;
2005-07-04 22:32:50 +08:00
if ( ! gmt ) {
2005-07-04 03:14:55 +08:00
timelib_time_offset_dtor ( offset ) ;
}
if ( real_len & & real_len ! = buf_len ) {
buf = ( char * ) erealloc ( buf , real_len + 1 ) ;
RETURN_STRINGL ( buf , real_len , 0 ) ;
}
efree ( buf ) ;
RETURN_FALSE ;
}
/* }}} */
/* {{{ proto string strftime(string format [, int timestamp])
Format a local time / date according to locale settings */
PHP_FUNCTION ( strftime )
{
2005-07-05 05:27:26 +08:00
php_strftime ( INTERNAL_FUNCTION_PARAM_PASSTHRU , 0 ) ;
2005-07-04 03:14:55 +08:00
}
/* }}} */
/* {{{ proto string gmstrftime(string format [, int timestamp])
Format a GMT / UCT time / date according to locale settings */
PHP_FUNCTION ( gmstrftime )
{
2005-07-05 05:27:26 +08:00
php_strftime ( INTERNAL_FUNCTION_PARAM_PASSTHRU , 1 ) ;
2005-07-04 03:14:55 +08:00
}
/* }}} */
# endif
2005-07-04 04:45:08 +08:00
/* {{{ proto int time(void)
Return current UNIX timestamp */
PHP_FUNCTION ( time )
{
RETURN_LONG ( ( long ) time ( NULL ) ) ;
}
/* }}} */
/* {{{ proto array localtime([int timestamp [, bool associative_array]])
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 */
PHP_FUNCTION ( localtime )
{
long timestamp = ( long ) time ( NULL ) ;
int associative = 0 ;
timelib_tzinfo * tzi ;
timelib_time * ts ;
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " |lb " , & timestamp , & associative ) = = FAILURE ) {
RETURN_FALSE ;
}
tzi = get_timezone_info ( TSRMLS_C ) ;
ts = timelib_time_ctor ( ) ;
2005-12-19 21:00:37 +08:00
ts - > tz_info = tzi ;
ts - > zone_type = TIMELIB_ZONETYPE_ID ;
timelib_unixtime2local ( ts , ( timelib_sll ) timestamp ) ;
2005-07-04 04:45:08 +08:00
array_init ( return_value ) ;
if ( associative ) {
add_assoc_long ( return_value , " tm_sec " , ts - > s ) ;
add_assoc_long ( return_value , " tm_min " , ts - > i ) ;
add_assoc_long ( return_value , " tm_hour " , ts - > h ) ;
add_assoc_long ( return_value , " tm_mday " , ts - > d ) ;
add_assoc_long ( return_value , " tm_mon " , ts - > m - 1 ) ;
add_assoc_long ( return_value , " tm_year " , ts - > y - 1900 ) ;
add_assoc_long ( return_value , " tm_wday " , timelib_day_of_week ( ts - > y , ts - > m , ts - > d ) ) ;
add_assoc_long ( return_value , " tm_yday " , timelib_day_of_year ( ts - > y , ts - > m , ts - > d ) ) ;
add_assoc_long ( return_value , " tm_isdst " , ts - > dst ) ;
} else {
add_next_index_long ( return_value , ts - > s ) ;
add_next_index_long ( return_value , ts - > i ) ;
add_next_index_long ( return_value , ts - > h ) ;
add_next_index_long ( return_value , ts - > d ) ;
add_next_index_long ( return_value , ts - > m - 1 ) ;
add_next_index_long ( return_value , ts - > y - 1900 ) ;
add_next_index_long ( return_value , timelib_day_of_week ( ts - > y , ts - > m , ts - > d ) ) ;
add_next_index_long ( return_value , timelib_day_of_year ( ts - > y , ts - > m , ts - > d ) ) ;
add_next_index_long ( return_value , ts - > dst ) ;
}
timelib_time_dtor ( ts ) ;
}
/* }}} */
/* {{{ proto array getdate([int timestamp])
Get date / time information */
PHP_FUNCTION ( getdate )
{
long timestamp = ( long ) time ( NULL ) ;
timelib_tzinfo * tzi ;
timelib_time * ts ;
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " |l " , & timestamp ) = = FAILURE ) {
RETURN_FALSE ;
}
tzi = get_timezone_info ( TSRMLS_C ) ;
ts = timelib_time_ctor ( ) ;
2005-12-19 21:00:37 +08:00
ts - > tz_info = tzi ;
ts - > zone_type = TIMELIB_ZONETYPE_ID ;
timelib_unixtime2local ( ts , ( timelib_sll ) timestamp ) ;
2005-07-04 04:45:08 +08:00
array_init ( return_value ) ;
add_assoc_long ( return_value , " seconds " , ts - > s ) ;
add_assoc_long ( return_value , " minutes " , ts - > i ) ;
add_assoc_long ( return_value , " hours " , ts - > h ) ;
add_assoc_long ( return_value , " mday " , ts - > d ) ;
add_assoc_long ( return_value , " wday " , timelib_day_of_week ( ts - > y , ts - > m , ts - > d ) ) ;
add_assoc_long ( return_value , " mon " , ts - > m ) ;
add_assoc_long ( return_value , " year " , ts - > y ) ;
add_assoc_long ( return_value , " yday " , timelib_day_of_year ( ts - > y , ts - > m , ts - > d ) ) ;
add_assoc_string ( return_value , " weekday " , day_full_names [ timelib_day_of_week ( ts - > y , ts - > m , ts - > d ) ] , 1 ) ;
add_assoc_string ( return_value , " month " , mon_full_names [ ts - > m - 1 ] , 1 ) ;
add_index_long ( return_value , 0 , timestamp ) ;
timelib_time_dtor ( ts ) ;
}
/* }}} */
2005-11-27 14:51:43 +08:00
# ifdef EXPERIMENTAL_DATE_SUPPORT
2005-11-18 05:05:30 +08:00
static void date_register_classes ( TSRMLS_D )
{
zend_class_entry ce_date , ce_timezone ;
INIT_CLASS_ENTRY ( ce_date , " date " , date_funcs_date ) ;
ce_date . create_object = date_object_new_date ;
date_ce_date = zend_register_internal_class_ex ( & ce_date , NULL , NULL TSRMLS_CC ) ;
memcpy ( & date_object_handlers_date , zend_get_std_object_handlers ( ) , sizeof ( zend_object_handlers ) ) ;
date_object_handlers_date . clone_obj = NULL ;
# define REGISTER_DATE_CLASS_CONST_STRING(const_name, value) \
zend_declare_class_constant_stringl ( date_ce_date , const_name , sizeof ( const_name ) - 1 , value , sizeof ( value ) - 1 TSRMLS_CC ) ;
2006-02-01 02:44:19 +08:00
REGISTER_DATE_CLASS_CONST_STRING ( " ATOM " , DATE_FORMAT_RFC3339 ) ;
2006-05-30 22:46:46 +08:00
REGISTER_DATE_CLASS_CONST_STRING ( " COOKIE " , DATE_FORMAT_RFC850 ) ;
2005-11-18 05:05:30 +08:00
REGISTER_DATE_CLASS_CONST_STRING ( " ISO8601 " , DATE_FORMAT_ISO8601 ) ;
2006-05-30 21:12:21 +08:00
REGISTER_DATE_CLASS_CONST_STRING ( " RFC822 " , DATE_FORMAT_RFC822 ) ;
REGISTER_DATE_CLASS_CONST_STRING ( " RFC850 " , DATE_FORMAT_RFC850 ) ;
2005-11-18 05:05:30 +08:00
REGISTER_DATE_CLASS_CONST_STRING ( " RFC1036 " , DATE_FORMAT_RFC1036 ) ;
REGISTER_DATE_CLASS_CONST_STRING ( " RFC1123 " , DATE_FORMAT_RFC1123 ) ;
REGISTER_DATE_CLASS_CONST_STRING ( " RFC2822 " , DATE_FORMAT_RFC2822 ) ;
2006-02-01 02:44:19 +08:00
REGISTER_DATE_CLASS_CONST_STRING ( " RFC3339 " , DATE_FORMAT_RFC3339 ) ;
2006-05-30 22:46:46 +08:00
REGISTER_DATE_CLASS_CONST_STRING ( " RSS " , DATE_FORMAT_RFC822 ) ;
2006-05-30 21:12:21 +08:00
REGISTER_DATE_CLASS_CONST_STRING ( " W3C " , DATE_FORMAT_RFC3339 ) ;
2005-11-18 05:05:30 +08:00
INIT_CLASS_ENTRY ( ce_timezone , " timezone " , date_funcs_timezone ) ;
ce_timezone . create_object = date_object_new_timezone ;
date_ce_timezone = zend_register_internal_class_ex ( & ce_timezone , NULL , NULL TSRMLS_CC ) ;
memcpy ( & date_object_handlers_timezone , zend_get_std_object_handlers ( ) , sizeof ( zend_object_handlers ) ) ;
date_object_handlers_timezone . clone_obj = NULL ;
}
2005-07-20 16:31:02 +08:00
static zend_object_value date_object_new_date ( zend_class_entry * class_type TSRMLS_DC )
{
php_date_obj * intern ;
zend_object_value retval ;
2005-11-26 17:40:54 +08:00
zval * tmp ;
2005-07-20 16:31:02 +08:00
intern = emalloc ( sizeof ( php_date_obj ) ) ;
memset ( intern , 0 , sizeof ( php_date_obj ) ) ;
2005-11-26 17:40:54 +08:00
2006-03-29 22:28:43 +08:00
zend_object_std_init ( & intern - > std , class_type TSRMLS_CC ) ;
2005-11-26 17:40:54 +08:00
zend_hash_copy ( intern - > std . properties , & class_type - > default_properties , ( copy_ctor_func_t ) zval_add_ref , ( void * ) & tmp , sizeof ( zval * ) ) ;
2005-11-15 22:08:03 +08:00
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 ) ;
2005-07-20 16:31:02 +08:00
retval . handlers = & date_object_handlers_date ;
return retval ;
}
static zend_object_value date_object_new_timezone ( zend_class_entry * class_type TSRMLS_DC )
{
php_timezone_obj * intern ;
zend_object_value retval ;
2005-11-26 20:35:27 +08:00
zval * tmp ;
2005-07-20 16:31:02 +08:00
intern = emalloc ( sizeof ( php_timezone_obj ) ) ;
memset ( intern , 0 , sizeof ( php_timezone_obj ) ) ;
2006-03-29 22:28:43 +08:00
zend_object_std_init ( & intern - > std , class_type TSRMLS_CC ) ;
2005-11-26 20:35:27 +08:00
zend_hash_copy ( intern - > std . properties , & class_type - > default_properties , ( copy_ctor_func_t ) zval_add_ref , ( void * ) & tmp , sizeof ( zval * ) ) ;
2005-11-15 22:08:03 +08:00
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 ) ;
2005-07-20 16:31:02 +08:00
retval . handlers = & date_object_handlers_timezone ;
return retval ;
}
static void date_object_free_storage_date ( void * object TSRMLS_DC )
{
php_date_obj * intern = ( php_date_obj * ) object ;
2005-11-15 22:08:03 +08:00
if ( intern - > time ) {
if ( intern - > time - > tz_info ) {
timelib_tzinfo_dtor ( intern - > time - > tz_info ) ;
}
timelib_time_dtor ( intern - > time ) ;
2005-07-20 16:31:02 +08:00
}
2006-03-29 22:28:43 +08:00
zend_object_std_dtor ( & intern - > std TSRMLS_CC ) ;
2005-07-20 16:31:02 +08:00
efree ( object ) ;
}
static void date_object_free_storage_timezone ( void * object TSRMLS_DC )
{
2005-12-19 21:00:37 +08:00
php_timezone_obj * intern = ( php_timezone_obj * ) object ;
2006-03-29 22:28:43 +08:00
zend_object_std_dtor ( & intern - > std TSRMLS_CC ) ;
2005-07-20 16:31:02 +08:00
efree ( object ) ;
}
/* Advanced Interface */
2006-05-11 11:47:55 +08:00
static zval * date_instantiate ( zend_class_entry * pce , zval * object TSRMLS_DC )
2005-07-20 16:31:02 +08:00
{
if ( ! object ) {
ALLOC_ZVAL ( object ) ;
}
Z_TYPE_P ( object ) = IS_OBJECT ;
object_init_ex ( object , pce ) ;
object - > refcount = 1 ;
object - > is_ref = 1 ;
return object ;
}
PHP_FUNCTION ( date_create )
{
php_date_obj * dateobj ;
zval * timezone_object = NULL ;
timelib_time * now ;
timelib_tzinfo * tzi ;
char * time_str ;
2005-10-05 16:20:44 +08:00
int time_str_len = 0 , free_tzi = 0 ; ;
2005-07-20 16:31:02 +08:00
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " |sO " , & time_str , & time_str_len , & timezone_object , date_ce_timezone ) = = FAILURE ) {
RETURN_FALSE ;
}
2006-05-11 11:47:55 +08:00
date_instantiate ( date_ce_date , return_value TSRMLS_CC ) ;
2005-07-20 16:31:02 +08:00
dateobj = ( php_date_obj * ) zend_object_store_get_object ( return_value TSRMLS_CC ) ;
2006-04-12 02:03:52 +08:00
dateobj - > time = timelib_strtotime ( time_str_len ? time_str : " now " , time_str_len ? time_str_len : sizeof ( " now " ) - 1 , NULL , DATE_TIMEZONEDB ) ;
2005-07-20 16:31:02 +08:00
if ( timezone_object ) {
php_timezone_obj * tzobj ;
tzobj = ( php_timezone_obj * ) zend_object_store_get_object ( timezone_object TSRMLS_CC ) ;
tzi = timelib_tzinfo_clone ( tzobj - > tz ) ;
2005-10-05 16:20:44 +08:00
free_tzi = 1 ;
2005-07-20 16:31:02 +08:00
} else if ( dateobj - > time - > tz_info ) {
tzi = timelib_tzinfo_clone ( dateobj - > time - > tz_info ) ;
2005-10-05 16:20:44 +08:00
free_tzi = 1 ;
2005-07-20 16:31:02 +08:00
} else {
tzi = get_timezone_info ( TSRMLS_C ) ;
}
now = timelib_time_ctor ( ) ;
2005-12-19 21:00:37 +08:00
now - > tz_info = tzi ;
now - > zone_type = TIMELIB_ZONETYPE_ID ;
timelib_unixtime2local ( now , ( timelib_sll ) time ( NULL ) ) ;
2005-07-20 16:31:02 +08:00
timelib_fill_holes ( dateobj - > time , now , 0 ) ;
timelib_update_ts ( dateobj - > time , tzi ) ;
if ( now - > tz_info ! = tzi ) {
timelib_tzinfo_dtor ( now - > tz_info ) ;
}
2005-10-05 16:20:44 +08:00
if ( free_tzi ) {
timelib_tzinfo_dtor ( tzi ) ;
}
2005-07-20 16:31:02 +08:00
timelib_time_dtor ( now ) ;
}
2006-04-12 02:03:52 +08:00
PHP_FUNCTION ( date_parse )
{
char * date ;
int date_len , i ;
struct timelib_error_container * error ;
timelib_time * parsed_time ;
zval * element ;
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " s " , & date , & date_len ) = = FAILURE ) {
RETURN_FALSE ;
}
parsed_time = timelib_strtotime ( date , date_len , & error , DATE_TIMEZONEDB ) ;
array_init ( return_value ) ;
# define PHP_DATE_PARSE_DATE_SET_TIME_ELEMENT(name, elem) \
if ( parsed_time - > elem = = - 1 ) { \
add_assoc_bool ( return_value , # name , 0 ) ; \
} else { \
add_assoc_long ( return_value , # name , parsed_time - > elem ) ; \
}
PHP_DATE_PARSE_DATE_SET_TIME_ELEMENT ( year , y ) ;
PHP_DATE_PARSE_DATE_SET_TIME_ELEMENT ( month , m ) ;
PHP_DATE_PARSE_DATE_SET_TIME_ELEMENT ( day , d ) ;
PHP_DATE_PARSE_DATE_SET_TIME_ELEMENT ( hour , h ) ;
PHP_DATE_PARSE_DATE_SET_TIME_ELEMENT ( minute , i ) ;
PHP_DATE_PARSE_DATE_SET_TIME_ELEMENT ( second , s ) ;
if ( parsed_time - > f = = - 1 ) {
add_assoc_bool ( return_value , " fraction " , 0 ) ;
} else {
add_assoc_double ( return_value , " fraction " , parsed_time - > f ) ;
}
add_assoc_long ( return_value , " warning_count " , error - > warning_count ) ;
MAKE_STD_ZVAL ( element ) ;
array_init ( element ) ;
for ( i = 0 ; i < error - > warning_count ; i + + ) {
add_index_string ( element , error - > warning_messages [ i ] . position , error - > warning_messages [ i ] . message , 1 ) ;
}
add_assoc_zval ( return_value , " warnings " , element ) ;
add_assoc_long ( return_value , " error_count " , error - > error_count ) ;
MAKE_STD_ZVAL ( element ) ;
array_init ( element ) ;
for ( i = 0 ; i < error - > error_count ; i + + ) {
add_index_string ( element , error - > error_messages [ i ] . position , error - > error_messages [ i ] . message , 1 ) ;
}
add_assoc_zval ( return_value , " errors " , element ) ;
timelib_error_container_dtor ( error ) ;
add_assoc_bool ( return_value , " is_localtime " , parsed_time - > is_localtime ) ;
if ( parsed_time - > is_localtime ) {
PHP_DATE_PARSE_DATE_SET_TIME_ELEMENT ( zone_type , zone_type ) ;
switch ( parsed_time - > zone_type ) {
case TIMELIB_ZONETYPE_OFFSET :
PHP_DATE_PARSE_DATE_SET_TIME_ELEMENT ( zone , z ) ;
add_assoc_bool ( return_value , " is_dst " , parsed_time - > dst ) ;
break ;
case TIMELIB_ZONETYPE_ID :
if ( parsed_time - > tz_abbr ) {
add_assoc_string ( return_value , " tz_abbr " , parsed_time - > tz_abbr , 1 ) ;
}
if ( parsed_time - > tz_info ) {
add_assoc_string ( return_value , " tz_id " , parsed_time - > tz_info - > name , 1 ) ;
}
break ;
case TIMELIB_ZONETYPE_ABBR :
PHP_DATE_PARSE_DATE_SET_TIME_ELEMENT ( zone , z ) ;
add_assoc_bool ( return_value , " is_dst " , parsed_time - > dst ) ;
add_assoc_string ( return_value , " tz_abbr " , parsed_time - > tz_abbr , 1 ) ;
break ;
}
}
if ( parsed_time - > have_relative | | parsed_time - > have_weekday_relative ) {
MAKE_STD_ZVAL ( element ) ;
array_init ( element ) ;
}
if ( parsed_time - > have_relative ) {
add_assoc_long ( element , " year " , parsed_time - > relative . y ) ;
add_assoc_long ( element , " month " , parsed_time - > relative . m ) ;
add_assoc_long ( element , " day " , parsed_time - > relative . d ) ;
add_assoc_long ( element , " hour " , parsed_time - > relative . h ) ;
add_assoc_long ( element , " minute " , parsed_time - > relative . i ) ;
add_assoc_long ( element , " second " , parsed_time - > relative . s ) ;
}
if ( parsed_time - > have_weekday_relative ) {
add_assoc_long ( element , " weekday " , parsed_time - > relative . weekday ) ;
}
if ( parsed_time - > have_relative | | parsed_time - > have_weekday_relative ) {
add_assoc_zval ( return_value , " relative " , element ) ;
}
timelib_time_dtor ( parsed_time ) ;
}
2005-07-20 16:31:02 +08:00
PHP_FUNCTION ( date_format )
{
zval * object ;
php_date_obj * dateobj ;
char * format ;
int format_len ;
if ( zend_parse_method_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , getThis ( ) , " Os " , & object , date_ce_date , & format , & format_len ) = = FAILURE ) {
RETURN_FALSE ;
}
dateobj = ( php_date_obj * ) zend_object_store_get_object ( object TSRMLS_CC ) ;
RETURN_STRING ( date_format ( format , format_len , dateobj - > time , dateobj - > time - > is_localtime ) , 0 ) ;
}
PHP_FUNCTION ( date_modify )
{
zval * object ;
php_date_obj * dateobj ;
char * modify ;
int modify_len ;
timelib_time * tmp_time ;
if ( zend_parse_method_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , getThis ( ) , " Os " , & object , date_ce_date , & modify , & modify_len ) = = FAILURE ) {
RETURN_FALSE ;
}
dateobj = ( php_date_obj * ) zend_object_store_get_object ( object TSRMLS_CC ) ;
2006-04-12 02:03:52 +08:00
tmp_time = timelib_strtotime ( modify , modify_len , NULL , DATE_TIMEZONEDB ) ;
2005-07-20 16:31:02 +08:00
dateobj - > time - > relative . y = tmp_time - > relative . y ;
dateobj - > time - > relative . m = tmp_time - > relative . m ;
dateobj - > time - > relative . d = tmp_time - > relative . d ;
dateobj - > time - > relative . h = tmp_time - > relative . h ;
dateobj - > time - > relative . i = tmp_time - > relative . i ;
dateobj - > time - > relative . s = tmp_time - > relative . s ;
dateobj - > time - > relative . weekday = tmp_time - > relative . weekday ;
dateobj - > time - > have_relative = tmp_time - > have_relative ;
dateobj - > time - > have_weekday_relative = tmp_time - > have_weekday_relative ;
dateobj - > time - > sse_uptodate = 0 ;
timelib_time_dtor ( tmp_time ) ;
timelib_update_ts ( dateobj - > time , NULL ) ;
timelib_update_from_sse ( dateobj - > time ) ;
}
PHP_FUNCTION ( date_timezone_get )
{
zval * object ;
php_date_obj * dateobj ;
php_timezone_obj * tzobj ;
if ( zend_parse_method_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , getThis ( ) , " O " , & object , date_ce_date ) = = FAILURE ) {
RETURN_FALSE ;
}
dateobj = ( php_date_obj * ) zend_object_store_get_object ( object TSRMLS_CC ) ;
if ( dateobj - > time - > is_localtime & & dateobj - > time - > tz_info ) {
2006-05-11 11:47:55 +08:00
date_instantiate ( date_ce_timezone , return_value TSRMLS_CC ) ;
2005-07-20 16:31:02 +08:00
tzobj = ( php_timezone_obj * ) zend_object_store_get_object ( return_value TSRMLS_CC ) ;
tzobj - > tz = timelib_tzinfo_clone ( dateobj - > time - > tz_info ) ;
} else {
RETURN_FALSE ;
}
}
PHP_FUNCTION ( date_timezone_set )
{
zval * object ;
zval * timezone_object ;
php_date_obj * dateobj ;
php_timezone_obj * tzobj ;
if ( zend_parse_method_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , getThis ( ) , " O|O " , & object , date_ce_date , & timezone_object , date_ce_timezone ) = = FAILURE ) {
RETURN_FALSE ;
}
dateobj = ( php_date_obj * ) zend_object_store_get_object ( object TSRMLS_CC ) ;
tzobj = ( php_timezone_obj * ) zend_object_store_get_object ( timezone_object TSRMLS_CC ) ;
if ( dateobj - > time - > tz_info ) {
timelib_tzinfo_dtor ( dateobj - > time - > tz_info ) ;
}
timelib_set_timezone ( dateobj - > time , timelib_tzinfo_clone ( tzobj - > tz ) ) ;
2005-12-19 21:00:37 +08:00
timelib_unixtime2local ( dateobj - > time , dateobj - > time - > sse ) ;
2005-07-20 16:31:02 +08:00
}
2005-07-05 05:27:26 +08:00
2005-07-20 16:31:02 +08:00
PHP_FUNCTION ( date_offset_get )
{
zval * object ;
php_date_obj * dateobj ;
timelib_time_offset * offset ;
if ( zend_parse_method_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , getThis ( ) , " O " , & object , date_ce_date ) = = FAILURE ) {
RETURN_FALSE ;
}
dateobj = ( php_date_obj * ) zend_object_store_get_object ( object TSRMLS_CC ) ;
if ( dateobj - > time - > is_localtime & & dateobj - > time - > tz_info ) {
offset = timelib_get_time_zone_info ( dateobj - > time - > sse , dateobj - > time - > tz_info ) ;
RETVAL_LONG ( offset - > offset ) ;
timelib_time_offset_dtor ( offset ) ;
return ;
} else {
RETURN_LONG ( 0 ) ;
}
}
2005-09-02 22:58:01 +08:00
PHP_FUNCTION ( date_time_set )
{
zval * object ;
php_date_obj * dateobj ;
long h , i , s = 0 ;
if ( zend_parse_method_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , getThis ( ) , " Oll|l " , & object , date_ce_date , & h , & i , & s ) = = FAILURE ) {
RETURN_FALSE ;
}
dateobj = ( php_date_obj * ) zend_object_store_get_object ( object TSRMLS_CC ) ;
dateobj - > time - > h = h ;
dateobj - > time - > i = i ;
dateobj - > time - > s = s ;
timelib_update_ts ( dateobj - > time , NULL ) ;
}
PHP_FUNCTION ( date_date_set )
{
zval * object ;
php_date_obj * dateobj ;
long y , m , d ;
if ( zend_parse_method_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , getThis ( ) , " Olll " , & object , date_ce_date , & y , & m , & d ) = = FAILURE ) {
RETURN_FALSE ;
}
dateobj = ( php_date_obj * ) zend_object_store_get_object ( object TSRMLS_CC ) ;
dateobj - > time - > y = y ;
dateobj - > time - > m = m ;
dateobj - > time - > d = d ;
timelib_update_ts ( dateobj - > time , NULL ) ;
}
PHP_FUNCTION ( date_isodate_set )
{
zval * object ;
php_date_obj * dateobj ;
long y , w , d = 1 ;
if ( zend_parse_method_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , getThis ( ) , " Oll|l " , & object , date_ce_date , & y , & w , & d ) = = FAILURE ) {
RETURN_FALSE ;
}
dateobj = ( php_date_obj * ) zend_object_store_get_object ( object TSRMLS_CC ) ;
dateobj - > time - > y = y ;
dateobj - > time - > m = 1 ;
dateobj - > time - > d = 1 ;
dateobj - > time - > relative . d = timelib_daynr_from_weeknr ( y , w , d ) ;
dateobj - > time - > have_relative = 1 ;
timelib_update_ts ( dateobj - > time , NULL ) ;
}
2005-07-20 16:31:02 +08:00
PHP_FUNCTION ( timezone_open )
{
php_timezone_obj * tzobj ;
char * tz ;
int tz_len ;
timelib_tzinfo * tzi = NULL ;
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " s " , & tz , & tz_len ) = = FAILURE ) {
RETURN_FALSE ;
}
/* Try finding the tz information as "Timezone Abbreviation" */
if ( ! tzi ) {
char * tzid ;
2005-10-01 23:04:07 +08:00
tzid = timelib_timezone_id_from_abbr ( tz , - 1 , 0 ) ;
2005-07-20 16:31:02 +08:00
if ( tzid ) {
2005-10-05 19:06:56 +08:00
tzi = php_date_parse_tzfile ( tzid , DATE_TIMEZONEDB TSRMLS_CC ) ;
2005-07-20 16:31:02 +08:00
}
}
/* Try finding the tz information as "Timezone Identifier" */
if ( ! tzi ) {
2005-10-05 19:06:56 +08:00
tzi = php_date_parse_tzfile ( tz , DATE_TIMEZONEDB TSRMLS_CC ) ;
2005-07-20 16:31:02 +08:00
}
/* If we find it we instantiate the object otherwise, well, we don't and return false */
if ( tzi ) {
2006-05-11 11:47:55 +08:00
date_instantiate ( date_ce_timezone , return_value TSRMLS_CC ) ;
2005-07-20 16:31:02 +08:00
tzobj = ( php_timezone_obj * ) zend_object_store_get_object ( return_value TSRMLS_CC ) ;
tzobj - > tz = tzi ;
} else {
RETURN_FALSE ;
}
}
PHP_FUNCTION ( timezone_name_get )
{
zval * object ;
php_timezone_obj * tzobj ;
if ( zend_parse_method_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , getThis ( ) , " O " , & object , date_ce_timezone ) = = FAILURE ) {
RETURN_FALSE ;
}
tzobj = ( php_timezone_obj * ) zend_object_store_get_object ( object TSRMLS_CC ) ;
RETURN_STRING ( tzobj - > tz - > name , 1 ) ;
}
2006-04-12 02:03:52 +08:00
PHP_FUNCTION ( timezone_name_from_abbr )
{
char * abbr ;
char * tzname ;
int abbr_len ;
long gmtoffset = - 1 ;
long isdst = - 1 ;
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " s|ll " , & abbr , & abbr_len , & gmtoffset , & isdst ) = = FAILURE ) {
RETURN_FALSE ;
}
tzname = timelib_timezone_id_from_abbr ( abbr , gmtoffset , isdst ) ;
if ( tzname ) {
RETURN_STRING ( tzname , 1 ) ;
} else {
RETURN_FALSE ;
}
}
2005-07-20 16:31:02 +08:00
PHP_FUNCTION ( timezone_offset_get )
{
zval * object , * dateobject ;
php_timezone_obj * tzobj ;
php_date_obj * dateobj ;
timelib_time_offset * offset ;
if ( zend_parse_method_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , getThis ( ) , " OO " , & object , date_ce_timezone , & dateobject , date_ce_date ) = = FAILURE ) {
RETURN_FALSE ;
}
tzobj = ( php_timezone_obj * ) zend_object_store_get_object ( object TSRMLS_CC ) ;
dateobj = ( php_date_obj * ) zend_object_store_get_object ( dateobject TSRMLS_CC ) ;
offset = timelib_get_time_zone_info ( dateobj - > time - > sse , tzobj - > tz ) ;
RETVAL_LONG ( offset - > offset ) ;
timelib_time_offset_dtor ( offset ) ;
}
PHP_FUNCTION ( timezone_transistions_get )
{
zval * object , * element ;
php_timezone_obj * tzobj ;
int i ;
if ( zend_parse_method_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , getThis ( ) , " O " , & object , date_ce_timezone ) = = FAILURE ) {
RETURN_FALSE ;
}
tzobj = ( php_timezone_obj * ) zend_object_store_get_object ( object TSRMLS_CC ) ;
array_init ( return_value ) ;
for ( i = 0 ; i < tzobj - > tz - > timecnt ; + + i ) {
MAKE_STD_ZVAL ( element ) ;
array_init ( element ) ;
add_assoc_long ( element , " ts " , tzobj - > tz - > trans [ i ] ) ;
add_assoc_string ( element , " time " , php_format_date ( DATE_FORMAT_ISO8601 , 13 , tzobj - > tz - > trans [ i ] , 0 TSRMLS_CC ) , 0 ) ;
add_assoc_long ( element , " offset " , tzobj - > tz - > type [ tzobj - > tz - > trans_idx [ i ] ] . offset ) ;
add_assoc_bool ( element , " isdst " , tzobj - > tz - > type [ tzobj - > tz - > trans_idx [ i ] ] . isdst ) ;
add_assoc_string ( element , " abbr " , & tzobj - > tz - > timezone_abbr [ tzobj - > tz - > type [ tzobj - > tz - > trans_idx [ i ] ] . abbr_idx ] , 1 ) ;
add_next_index_zval ( return_value , element ) ;
}
}
PHP_FUNCTION ( timezone_identifiers_list )
{
2006-05-15 01:36:05 +08:00
const timelib_tzdb * tzdb ;
const timelib_tzdb_index_entry * table ;
int i , item_count ;
2005-10-03 19:17:28 +08:00
tzdb = DATE_TIMEZONEDB ;
item_count = tzdb - > index_size ;
table = tzdb - > index ;
2005-07-20 16:31:02 +08:00
array_init ( return_value ) ;
for ( i = 0 ; i < item_count ; + + i ) {
add_next_index_string ( return_value , table [ i ] . id , 1 ) ;
} ;
}
PHP_FUNCTION ( timezone_abbreviations_list )
{
2006-05-15 01:36:05 +08:00
const timelib_tz_lookup_table * table , * entry ;
zval * element , * * abbr_array_pp , * abbr_array ;
2005-07-20 16:31:02 +08:00
table = timelib_timezone_abbreviations_list ( ) ;
array_init ( return_value ) ;
entry = table ;
2005-10-03 19:17:28 +08:00
2005-07-20 16:31:02 +08:00
do {
MAKE_STD_ZVAL ( element ) ;
array_init ( element ) ;
add_assoc_bool ( element , " dst " , entry - > type ) ;
2005-10-01 23:04:07 +08:00
add_assoc_long ( element , " offset " , entry - > gmtoffset ) ;
2005-07-20 16:31:02 +08:00
if ( entry - > full_tz_name ) {
add_assoc_string ( element , " timezone_id " , entry - > full_tz_name , 1 ) ;
} else {
add_assoc_null ( element , " timezone_id " ) ;
}
2005-10-03 19:17:28 +08:00
if ( zend_hash_find ( HASH_OF ( return_value ) , entry - > name , strlen ( entry - > name ) + 1 , ( void * * ) & abbr_array_pp ) = = FAILURE ) {
MAKE_STD_ZVAL ( abbr_array ) ;
array_init ( abbr_array ) ;
add_assoc_zval ( return_value , entry - > name , abbr_array ) ;
} else {
abbr_array = * abbr_array_pp ;
}
add_next_index_zval ( abbr_array , element ) ;
2005-07-20 16:31:02 +08:00
entry + + ;
} while ( entry - > name ) ;
}
# endif
/* {{{ proto bool date_default_timezone_set(string timezone_identifier)
2005-07-05 05:27:26 +08:00
Sets the default timezone used by all date / time functions in a script */
PHP_FUNCTION ( date_default_timezone_set )
2005-07-03 05:19:25 +08:00
{
char * zone ;
int zone_len ;
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " s " , & zone , & zone_len ) = = FAILURE ) {
RETURN_FALSE ;
}
2005-12-21 03:54:10 +08:00
if ( ! timelib_timezone_id_is_valid ( zone , DATE_TIMEZONEDB ) ) {
php_error_docref ( NULL TSRMLS_CC , E_NOTICE , " Timezone ID '%s' is invalid " , zone ) ;
RETURN_FALSE ;
}
2005-07-03 05:19:25 +08:00
if ( DATEG ( timezone ) ) {
efree ( DATEG ( timezone ) ) ;
2005-07-05 02:13:15 +08:00
DATEG ( timezone ) = NULL ;
2005-07-03 05:19:25 +08:00
}
2005-07-04 02:56:57 +08:00
DATEG ( timezone ) = estrndup ( zone , zone_len ) ;
2005-07-03 05:19:25 +08:00
RETURN_TRUE ;
}
2005-07-05 05:27:26 +08:00
/* }}} */
2005-07-03 05:19:25 +08:00
2005-07-20 16:31:02 +08:00
/* {{{ proto string date_default_timezone_get()
2005-07-05 05:27:26 +08:00
Gets the default timezone used by all date / time functions in a script */
PHP_FUNCTION ( date_default_timezone_get )
2005-07-03 05:19:25 +08:00
{
2005-07-20 16:31:02 +08:00
timelib_tzinfo * default_tz ;
default_tz = get_timezone_info ( TSRMLS_C ) ;
RETVAL_STRING ( default_tz - > name , 1 ) ;
2005-07-03 05:19:25 +08:00
}
2005-07-05 05:27:26 +08:00
/* }}} */
2005-07-03 05:19:25 +08:00
2006-01-05 05:31:35 +08:00
/* {{{ php_do_date_sunrise_sunset
* Common for date_sunrise ( ) and date_sunset ( ) functions
*/
static void php_do_date_sunrise_sunset ( INTERNAL_FUNCTION_PARAMETERS , int calc_sunset )
{
double latitude , longitude , zenith , gmt_offset = 0 , altitude ;
double h_rise , h_set , N ;
timelib_sll rise , set , transit ;
long time , retformat ;
int rs ;
timelib_time * t ;
timelib_tzinfo * tzi ;
char retstr [ 6 ] ;
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " l|ldddd " , & time , & retformat , & latitude , & longitude , & zenith , & gmt_offset ) = = FAILURE ) {
RETURN_FALSE ;
}
switch ( ZEND_NUM_ARGS ( ) ) {
case 1 :
retformat = SUNFUNCS_RET_STRING ;
case 2 :
latitude = INI_FLT ( " date.default_latitude " ) ;
case 3 :
longitude = INI_FLT ( " date.default_longitude " ) ;
case 4 :
if ( calc_sunset ) {
zenith = INI_FLT ( " date.sunset_zenith " ) ;
} else {
zenith = INI_FLT ( " date.sunrise_zenith " ) ;
}
case 5 :
case 6 :
break ;
default :
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " invalid format " ) ;
RETURN_FALSE ;
break ;
}
if ( retformat ! = SUNFUNCS_RET_TIMESTAMP & &
retformat ! = SUNFUNCS_RET_STRING & &
retformat ! = SUNFUNCS_RET_DOUBLE )
{
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 " ) ;
RETURN_FALSE ;
}
altitude = 90 - zenith ;
/* Initialize time struct */
t = timelib_time_ctor ( ) ;
tzi = get_timezone_info ( TSRMLS_C ) ;
t - > tz_info = tzi ;
t - > zone_type = TIMELIB_ZONETYPE_ID ;
if ( ZEND_NUM_ARGS ( ) < = 5 ) {
gmt_offset = timelib_get_current_offset ( t ) / 3600 ;
}
timelib_unixtime2local ( t , time ) ;
rs = timelib_astro_rise_set_altitude ( t , longitude , latitude , altitude , altitude > - 1 ? 1 : 0 , & h_rise , & h_set , & rise , & set , & transit ) ;
2006-03-19 07:43:48 +08:00
timelib_time_dtor ( t ) ;
2006-01-05 05:31:35 +08:00
if ( rs ! = 0 ) {
RETURN_FALSE ;
}
if ( retformat = = SUNFUNCS_RET_TIMESTAMP ) {
RETURN_LONG ( calc_sunset ? set : rise ) ;
}
N = ( calc_sunset ? h_set : h_rise ) + gmt_offset ;
while ( N > 24 ) {
N - = 24 ;
}
while ( N < 0 ) {
N + = 24 ;
}
switch ( retformat ) {
case SUNFUNCS_RET_STRING :
sprintf ( retstr , " %02d:%02d " , ( int ) N , ( int ) ( 60 * ( N - ( int ) N ) ) ) ;
RETURN_STRINGL ( retstr , 5 , 1 ) ;
break ;
case SUNFUNCS_RET_DOUBLE :
RETURN_DOUBLE ( N ) ;
break ;
}
}
/* }}} */
/* {{{ proto mixed date_sunrise(mixed time [, int format [, float latitude [, float longitude [, float zenith [, float gmt_offset]]]]])
Returns time of sunrise for a given day and location */
PHP_FUNCTION ( date_sunrise )
{
php_do_date_sunrise_sunset ( INTERNAL_FUNCTION_PARAM_PASSTHRU , 0 ) ;
}
/* }}} */
/* {{{ proto mixed date_sunset(mixed time [, int format [, float latitude [, float longitude [, float zenith [, float gmt_offset]]]]])
Returns time of sunset for a given day and location */
PHP_FUNCTION ( date_sunset )
{
php_do_date_sunrise_sunset ( INTERNAL_FUNCTION_PARAM_PASSTHRU , 1 ) ;
}
/* }}} */
/* {{{ proto array date_sun_info(long time, float latitude, float longitude)
Returns an array with information about sun set / rise and twilight begin / end */
PHP_FUNCTION ( date_sun_info )
{
long time ;
double latitude , longitude ;
timelib_time * t , * t2 ;
timelib_tzinfo * tzi ;
int rs ;
timelib_sll rise , set , transit ;
int dummy ;
double ddummy ;
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " ldd " , & time , & latitude , & longitude ) = = FAILURE ) {
RETURN_FALSE ;
}
/* Initialize time struct */
t = timelib_time_ctor ( ) ;
tzi = get_timezone_info ( TSRMLS_C ) ;
t - > tz_info = tzi ;
t - > zone_type = TIMELIB_ZONETYPE_ID ;
timelib_unixtime2local ( t , time ) ;
/* Setup */
t2 = timelib_time_ctor ( ) ;
array_init ( return_value ) ;
/* Get sun up/down and transit */
rs = timelib_astro_rise_set_altitude ( t , latitude , longitude , - 35.0 / 60 , 1 , & ddummy , & ddummy , & rise , & set , & transit ) ;
switch ( rs ) {
case - 1 : /* always below */
add_assoc_bool ( return_value , " sunrise " , 0 ) ;
add_assoc_bool ( return_value , " sunset " , 0 ) ;
break ;
case 1 : /* always above */
add_assoc_bool ( return_value , " sunrise " , 1 ) ;
add_assoc_bool ( return_value , " sunset " , 1 ) ;
break ;
default :
t2 - > sse = rise ;
add_assoc_long ( return_value , " sunrise " , timelib_date_to_int ( t2 , & dummy ) ) ;
t2 - > sse = set ;
add_assoc_long ( return_value , " sunset " , timelib_date_to_int ( t2 , & dummy ) ) ;
}
t2 - > sse = transit ;
add_assoc_long ( return_value , " transit " , timelib_date_to_int ( t2 , & dummy ) ) ;
/* Get civil twilight */
rs = timelib_astro_rise_set_altitude ( t , latitude , longitude , - 6.0 , 0 , & ddummy , & ddummy , & rise , & set , & transit ) ;
switch ( rs ) {
case - 1 : /* always below */
add_assoc_bool ( return_value , " civil_twilight_begin " , 0 ) ;
add_assoc_bool ( return_value , " civil_twilight_end " , 0 ) ;
break ;
case 1 : /* always above */
add_assoc_bool ( return_value , " civil_twilight_begin " , 1 ) ;
add_assoc_bool ( return_value , " civil_twilight_end " , 1 ) ;
break ;
default :
t2 - > sse = rise ;
add_assoc_long ( return_value , " civil_twilight_begin " , timelib_date_to_int ( t2 , & dummy ) ) ;
t2 - > sse = set ;
add_assoc_long ( return_value , " civil_twilight_end " , timelib_date_to_int ( t2 , & dummy ) ) ;
}
/* Get nautical twilight */
rs = timelib_astro_rise_set_altitude ( t , latitude , longitude , - 12.0 , 0 , & ddummy , & ddummy , & rise , & set , & transit ) ;
switch ( rs ) {
case - 1 : /* always below */
add_assoc_bool ( return_value , " nautical_twilight_begin " , 0 ) ;
add_assoc_bool ( return_value , " nautical_twilight_end " , 0 ) ;
break ;
case 1 : /* always above */
add_assoc_bool ( return_value , " nautical_twilight_begin " , 1 ) ;
add_assoc_bool ( return_value , " nautical_twilight_end " , 1 ) ;
break ;
default :
t2 - > sse = rise ;
add_assoc_long ( return_value , " nautical_twilight_begin " , timelib_date_to_int ( t2 , & dummy ) ) ;
t2 - > sse = set ;
add_assoc_long ( return_value , " nautical_twilight_end " , timelib_date_to_int ( t2 , & dummy ) ) ;
}
/* Get astronomical twilight */
rs = timelib_astro_rise_set_altitude ( t , latitude , longitude , - 18.0 , 0 , & ddummy , & ddummy , & rise , & set , & transit ) ;
switch ( rs ) {
case - 1 : /* always below */
add_assoc_bool ( return_value , " astronomical_twilight_begin " , 0 ) ;
add_assoc_bool ( return_value , " astronomical_twilight_end " , 0 ) ;
break ;
case 1 : /* always above */
add_assoc_bool ( return_value , " astronomical_twilight_begin " , 1 ) ;
add_assoc_bool ( return_value , " astronomical_twilight_end " , 1 ) ;
break ;
default :
t2 - > sse = rise ;
add_assoc_long ( return_value , " astronomical_twilight_begin " , timelib_date_to_int ( t2 , & dummy ) ) ;
t2 - > sse = set ;
add_assoc_long ( return_value , " astronomical_twilight_end " , timelib_date_to_int ( t2 , & dummy ) ) ;
}
2006-03-19 07:43:48 +08:00
timelib_time_dtor ( t ) ;
timelib_time_dtor ( t2 ) ;
2006-01-05 05:31:35 +08:00
}
/* }}} */
2005-06-15 05:32:29 +08:00
/*
* Local variables :
* tab - width : 4
* c - basic - offset : 4
* End :
* vim600 : fdm = marker
* vim : noet sw = 4 ts = 4
*/