derick Fri Apr 25 12:36:11 2008 UTC
Added files: (Branch: PHP_5_3)
/php-src/ext/date/lib interval.c parse_iso_intervals.c
parse_iso_intervals.re
/php-src/ext/date/tests bug44742.phpt
Modified files:
/php-src NEWS
/php-src/ext/date config.m4 php_date.c php_date.h
/php-src/ext/date/lib README parse_date.c timelib.c timelib.h
timelib_structs.h tm2unixtime.c
Log:
- Added new date/time functionality:
. support for diffing date/times through date_diff() / DateTime::diff().
. added DateInterval class to represent the difference between two
date/times.
. support for parsing ISO intervals for use with DateInterval.
. date_add() / DateTime::add(), date_sub() / DateTime::sub() for applying an
interval to an existing date/time.
- MFH: Fixed bug #44742 (timezone_offset_get() causes segmentation faults).
http://cvs.php.net/viewvc.cgi/php-src/NEWS?r1=1.2027.2.547.2.965.2.162&r2=1.2027.2.547.2.965.2.163&diff_format=u
Index: php-src/NEWS
diff -u php-src/NEWS:1.2027.2.547.2.965.2.162
php-src/NEWS:1.2027.2.547.2.965.2.163
--- php-src/NEWS:1.2027.2.547.2.965.2.162 Thu Apr 24 07:45:01 2008
+++ php-src/NEWS Fri Apr 25 12:35:40 2008
@@ -49,6 +49,11 @@
. support for "first/last day of <month>" style texts.
. support for date/time strings returned by MS SQL.
. support for serialization and unserialization of DateTime objects.
+ . support for diffing date/times through date_diff() / DateTime::diff().
+ . added DateInterval class to represent the difference between two
date/times.
+ . support for parsing ISO intervals for use with DateInterval.
+ . date_add() / DateTime::add(), date_sub() / DateTime::sub() for applying an
+ interval to an existing date/time.
- Added functionality to SPL extension:
. Added SPL to list of standard extensions that cannot be disabled. (Marcus)
. Added ability to store associative information with objects in
@@ -149,6 +154,7 @@
- Fixed PECL bug #12431 (OCI8 ping functionality is broken). (Oracle Corp.)
- Fixed bug #44805 (rename() function is not portable to Windows). (Pierre)
+- Fixed bug #44742 (timezone_offset_get() causes segmentation faults). (Derick)
- Fixed bug #44648 (Attribute names not checked for wellformedness). (Rob)
- Fixed bug #44414 (Incomplete reporting about abstract methods). (Dmitry)
- Fixed bug #44390 (mysqli_bind_param/bind_result and Object member variables)
http://cvs.php.net/viewvc.cgi/php-src/ext/date/config.m4?r1=1.10.2.2&r2=1.10.2.2.4.1&diff_format=u
Index: php-src/ext/date/config.m4
diff -u php-src/ext/date/config.m4:1.10.2.2
php-src/ext/date/config.m4:1.10.2.2.4.1
--- php-src/ext/date/config.m4:1.10.2.2 Mon Dec 19 13:00:32 2005
+++ php-src/ext/date/config.m4 Fri Apr 25 12:35:40 2008
@@ -1,4 +1,4 @@
-dnl $Id: config.m4,v 1.10.2.2 2005/12/19 13:00:32 derick Exp $
+dnl $Id: config.m4,v 1.10.2.2.4.1 2008/04/25 12:35:40 derick Exp $
dnl config.m4 for date extension
sinclude(ext/date/lib/timelib.m4)
@@ -6,7 +6,7 @@
PHP_DATE_CFLAGS="[EMAIL PROTECTED]@/lib"
timelib_sources="lib/astro.c lib/dow.c lib/parse_date.c lib/parse_tz.c
- lib/timelib.c lib/tm2unixtime.c lib/unixtime2tm.c"
+ lib/timelib.c lib/tm2unixtime.c lib/unixtime2tm.c
lib/parse_iso_intervals.c lib/interval.c"
PHP_NEW_EXTENSION(date, php_date.c $timelib_sources, no,, $PHP_DATE_CFLAGS)
http://cvs.php.net/viewvc.cgi/php-src/ext/date/php_date.c?r1=1.43.2.45.2.51.2.29&r2=1.43.2.45.2.51.2.30&diff_format=u
Index: php-src/ext/date/php_date.c
diff -u php-src/ext/date/php_date.c:1.43.2.45.2.51.2.29
php-src/ext/date/php_date.c:1.43.2.45.2.51.2.30
--- php-src/ext/date/php_date.c:1.43.2.45.2.51.2.29 Mon Mar 31 09:11:30 2008
+++ php-src/ext/date/php_date.c Fri Apr 25 12:35:40 2008
@@ -16,7 +16,7 @@
+----------------------------------------------------------------------+
*/
-/* $Id: php_date.c,v 1.43.2.45.2.51.2.29 2008/03/31 09:11:30 derick Exp $ */
+/* $Id: php_date.c,v 1.43.2.45.2.51.2.30 2008/04/25 12:35:40 derick Exp $ */
#include "php.h"
#include "php_streams.h"
@@ -174,9 +174,12 @@
PHP_FE(date_get_last_errors, NULL)
PHP_FE(date_format, NULL)
PHP_FE(date_modify, NULL)
+ PHP_FE(date_add, NULL)
+ PHP_FE(date_sub, NULL)
PHP_FE(date_timezone_get, NULL)
PHP_FE(date_timezone_set, NULL)
PHP_FE(date_offset_get, NULL)
+ PHP_FE(date_diff, NULL)
PHP_FE(date_time_set, NULL)
PHP_FE(date_date_set, NULL)
@@ -192,6 +195,8 @@
PHP_FE(timezone_identifiers_list, NULL)
PHP_FE(timezone_abbreviations_list, NULL)
+ PHP_FE(date_interval_format, NULL)
+
/* Options and Configuration */
PHP_FE(date_default_timezone_set, arginfo_date_default_timezone_set)
PHP_FE(date_default_timezone_get, arginfo_date_default_timezone_get)
@@ -211,6 +216,8 @@
PHP_ME_MAPPING(getLastErrors, date_get_last_errors, NULL,
ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
PHP_ME_MAPPING(format, date_format, NULL, 0)
PHP_ME_MAPPING(modify, date_modify, NULL, 0)
+ PHP_ME_MAPPING(add, date_add,
NULL, 0)
+ PHP_ME_MAPPING(sub, date_sub,
NULL, 0)
PHP_ME_MAPPING(getTimezone, date_timezone_get, NULL, 0)
PHP_ME_MAPPING(setTimezone, date_timezone_set, NULL, 0)
PHP_ME_MAPPING(getOffset, date_offset_get, NULL, 0)
@@ -219,6 +226,7 @@
PHP_ME_MAPPING(setISODate, date_isodate_set, NULL, 0)
PHP_ME_MAPPING(setTimestamp, date_timestamp_set, NULL, 0)
PHP_ME_MAPPING(getTimestamp, date_timestamp_get, NULL, 0)
+ PHP_ME_MAPPING(diff, date_diff, NULL, 0)
{NULL, NULL, NULL}
};
@@ -232,9 +240,14 @@
{NULL, NULL, NULL}
};
+const zend_function_entry date_funcs_interval[] = {
+ PHP_ME(DateInterval, __construct, NULL,
ZEND_ACC_CTOR|ZEND_ACC_PUBLIC)
+ PHP_ME_MAPPING(format, date_interval_format, NULL, 0)
+ {NULL, NULL, NULL}
+};
+
static char* guess_timezone(const timelib_tzdb *tzdb TSRMLS_DC);
static void date_register_classes(TSRMLS_D);
-static char* guess_timezone(const timelib_tzdb *tzdb TSRMLS_DC);
/* }}} */
ZEND_DECLARE_MODULE_GLOBALS(date)
@@ -263,13 +276,15 @@
PHP_INI_END()
/* }}} */
-zend_class_entry *date_ce_date, *date_ce_timezone;
+zend_class_entry *date_ce_date, *date_ce_timezone, *date_ce_interval;
static zend_object_handlers date_object_handlers_date;
static zend_object_handlers date_object_handlers_timezone;
+static zend_object_handlers date_object_handlers_interval;
typedef struct _php_date_obj php_date_obj;
typedef struct _php_timezone_obj php_timezone_obj;
+typedef struct _php_interval_obj php_interval_obj;
struct _php_date_obj {
zend_object std;
@@ -293,6 +308,13 @@
} tzi;
};
+struct _php_interval_obj {
+ zend_object std;
+ timelib_rel_time *diff;
+ HashTable *props;
+ int initialized;
+};
+
#define DATE_SET_CONTEXT \
zval *object; \
object = getThis(); \
@@ -319,12 +341,21 @@
static void date_object_free_storage_date(void *object TSRMLS_DC);
static void date_object_free_storage_timezone(void *object TSRMLS_DC);
+static void date_object_free_storage_interval(void *object TSRMLS_DC);
+
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);
+static zend_object_value date_object_new_interval(zend_class_entry *class_type
TSRMLS_DC);
+
static zend_object_value date_object_clone_date(zval *this_ptr TSRMLS_DC);
+static zend_object_value date_object_clone_timezone(zval *this_ptr TSRMLS_DC);
+static zend_object_value date_object_clone_interval(zval *this_ptr TSRMLS_DC);
+
static int date_object_compare_date(zval *d1, zval *d2 TSRMLS_DC);
static HashTable *date_object_get_properties(zval *object TSRMLS_DC);
-static zend_object_value date_object_clone_timezone(zval *this_ptr TSRMLS_DC);
+
+zval *date_interval_read_property(zval *object, zval *member, int type
TSRMLS_DC);
+void date_interval_write_property(zval *object, zval *member, zval *value
TSRMLS_DC);
/* This is need to ensure that session extension request shutdown occurs 1st,
because it uses the date extension */
static const zend_module_dep date_deps[] = {
@@ -1520,7 +1551,7 @@
static void date_register_classes(TSRMLS_D)
{
- zend_class_entry ce_date, ce_timezone;
+ zend_class_entry ce_date, ce_timezone, ce_interval;
INIT_CLASS_ENTRY(ce_date, "DateTime", date_funcs_date);
ce_date.create_object = date_object_new_date;
@@ -1568,6 +1599,14 @@
REGISTER_TIMEZONE_CLASS_CONST_STRING("UTC",
PHP_DATE_TIMEZONE_GROUP_UTC);
REGISTER_TIMEZONE_CLASS_CONST_STRING("ALL",
PHP_DATE_TIMEZONE_GROUP_ALL);
REGISTER_TIMEZONE_CLASS_CONST_STRING("ALL_WITH_BC",
PHP_DATE_TIMEZONE_GROUP_ALL_W_BC);
+
+ INIT_CLASS_ENTRY(ce_interval, "DateInterval", date_funcs_interval);
+ ce_interval.create_object = date_object_new_interval;
+ date_ce_interval = zend_register_internal_class_ex(&ce_interval, NULL,
NULL TSRMLS_CC);
+ memcpy(&date_object_handlers_interval, zend_get_std_object_handlers(),
sizeof(zend_object_handlers));
+ date_object_handlers_interval.clone_obj = date_object_clone_interval;
+ date_object_handlers_interval.read_property =
date_interval_read_property;
+ date_object_handlers_interval.write_property =
date_interval_write_property;
}
static inline zend_object_value date_object_new_date_ex(zend_class_entry
*class_type, php_date_obj **ptr TSRMLS_DC)
@@ -1743,6 +1782,44 @@
return new_ov;
}
+static inline zend_object_value date_object_new_interval_ex(zend_class_entry
*class_type, php_interval_obj **ptr TSRMLS_DC)
+{
+ php_interval_obj *intern;
+ zend_object_value retval;
+ zval *tmp;
+
+ intern = emalloc(sizeof(php_interval_obj));
+ memset(intern, 0, sizeof(php_interval_obj));
+ if (ptr) {
+ *ptr = intern;
+ }
+
+ zend_object_std_init(&intern->std, class_type TSRMLS_CC);
+ zend_hash_copy(intern->std.properties, &class_type->default_properties,
(copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));
+
+ 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);
+ retval.handlers = &date_object_handlers_interval;
+
+ return retval;
+}
+
+static zend_object_value date_object_new_interval(zend_class_entry *class_type
TSRMLS_DC)
+{
+ return date_object_new_interval_ex(class_type, NULL TSRMLS_CC);
+}
+
+static zend_object_value date_object_clone_interval(zval *this_ptr TSRMLS_DC)
+{
+ php_interval_obj *new_obj = NULL;
+ php_interval_obj *old_obj = (php_interval_obj *)
zend_object_store_get_object(this_ptr TSRMLS_CC);
+ zend_object_value new_ov = date_object_new_interval_ex(old_obj->std.ce,
&new_obj TSRMLS_CC);
+
+ zend_objects_clone_members(&new_obj->std, new_ov, &old_obj->std,
Z_OBJ_HANDLE_P(this_ptr) TSRMLS_CC);
+
+ /** FIX ME ADD CLONE STUFF **/
+ return new_ov;
+}
+
static void date_object_free_storage_date(void *object TSRMLS_DC)
{
php_date_obj *intern = (php_date_obj *)object;
@@ -1769,6 +1846,15 @@
efree(object);
}
+static void date_object_free_storage_interval(void *object TSRMLS_DC)
+{
+ php_interval_obj *intern = (php_interval_obj *)object;
+
+ timelib_rel_time_dtor(intern->diff);
+ zend_object_std_dtor(&intern->std TSRMLS_CC);
+ efree(object);
+}
+
/* Advanced Interface */
static zval * date_instantiate(zend_class_entry *pce, zval *object TSRMLS_DC)
{
@@ -2233,6 +2319,82 @@
}
/* }}} */
+/* {{{ proto void date_add(DateTime object, DateInterval interval)
+ Adds an interval to the current date in object.
+*/
+PHP_FUNCTION(date_add)
+{
+ zval *object, *interval;
+ php_date_obj *dateobj;
+ php_interval_obj *intobj;
+ int bias = 1;
+
+ if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(),
"OO", &object, date_ce_date, &interval, date_ce_interval) == FAILURE) {
+ RETURN_FALSE;
+ }
+ dateobj = (php_date_obj *) zend_object_store_get_object(object
TSRMLS_CC);
+ DATE_CHECK_INITIALIZED(dateobj->time, DateTime);
+ intobj = (php_interval_obj *) zend_object_store_get_object(interval
TSRMLS_CC);
+ DATE_CHECK_INITIALIZED(intobj->initialized, DateInterval);
+
+ if (intobj->diff->invert) {
+ bias = -1;
+ }
+
+ dateobj->time->relative.y = intobj->diff->y * bias;
+ dateobj->time->relative.m = intobj->diff->m * bias;
+ dateobj->time->relative.d = intobj->diff->d * bias;
+ dateobj->time->relative.h = intobj->diff->h * bias;
+ dateobj->time->relative.i = intobj->diff->i * bias;
+ dateobj->time->relative.s = intobj->diff->s * bias;
+ dateobj->time->relative.weekday = 0;
+ dateobj->time->have_relative = 1;
+ dateobj->time->have_weekday_relative = 0;
+ dateobj->time->sse_uptodate = 0;
+
+ timelib_update_ts(dateobj->time, NULL);
+ timelib_update_from_sse(dateobj->time);
+}
+/* }}} */
+
+/* {{{ proto void date_sub(DateTime object, DateInterval interval)
+ Subtracts an interval to the current date in object.
+*/
+PHP_FUNCTION(date_sub)
+{
+ zval *object, *interval;
+ php_date_obj *dateobj;
+ php_interval_obj *intobj;
+ int bias = 1;
+
+ if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(),
"OO", &object, date_ce_date, &interval, date_ce_interval) == FAILURE) {
+ RETURN_FALSE;
+ }
+ dateobj = (php_date_obj *) zend_object_store_get_object(object
TSRMLS_CC);
+ DATE_CHECK_INITIALIZED(dateobj->time, DateTime);
+ intobj = (php_interval_obj *) zend_object_store_get_object(interval
TSRMLS_CC);
+ DATE_CHECK_INITIALIZED(intobj->initialized, DateInterval);
+
+ if (intobj->diff->invert) {
+ bias = -1;
+ }
+
+ dateobj->time->relative.y = 0 - (intobj->diff->y * bias);
+ dateobj->time->relative.m = 0 - (intobj->diff->m * bias);
+ dateobj->time->relative.d = 0 - (intobj->diff->d * bias);
+ dateobj->time->relative.h = 0 - (intobj->diff->h * bias);
+ dateobj->time->relative.i = 0 - (intobj->diff->i * bias);
+ dateobj->time->relative.s = 0 - (intobj->diff->s * bias);
+ dateobj->time->relative.weekday = 0;
+ dateobj->time->have_relative = 1;
+ dateobj->time->have_weekday_relative = 0;
+ dateobj->time->sse_uptodate = 0;
+
+ timelib_update_ts(dateobj->time, NULL);
+ timelib_update_from_sse(dateobj->time);
+}
+/* }}} */
+
/* {{{ proto DateTimeZone date_timezone_get(DateTime object)
Return new DateTimeZone object relative to give DateTime
*/
@@ -2444,6 +2606,36 @@
}
/* }}} */
+/* {{{ proto DateInterval date_diff(DateTime object [, bool absolute])
+ Returns the difference between two DateTime objects.
+*/
+PHP_FUNCTION(date_diff)
+{
+ zval *object1, *object2;
+ php_date_obj *dateobj1, *dateobj2;
+ php_interval_obj *interval;
+ long absolute = 0;
+
+ if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(),
"OO|l", &object1, date_ce_date, &object2, date_ce_date, &absolute) == FAILURE) {
+ RETURN_FALSE;
+ }
+ dateobj1 = (php_date_obj *) zend_object_store_get_object(object1
TSRMLS_CC);
+ dateobj2 = (php_date_obj *) zend_object_store_get_object(object2
TSRMLS_CC);
+ DATE_CHECK_INITIALIZED(dateobj1->time, DateTime);
+ DATE_CHECK_INITIALIZED(dateobj2->time, DateTime);
+ timelib_update_ts(dateobj1->time, NULL);
+ timelib_update_ts(dateobj2->time, NULL);
+
+ date_instantiate(date_ce_interval, return_value TSRMLS_CC);
+ interval = zend_object_store_get_object(return_value TSRMLS_CC);
+ interval->diff = timelib_diff(dateobj1->time, dateobj2->time);
+ if (absolute) {
+ interval->diff->invert = 0;
+ }
+ interval->initialized = 1;
+}
+/* }}} */
+
static int timezone_initialize(timelib_tzinfo **tzi, /*const*/ char *tz
TSRMLS_DC)
{
char *tzid;
@@ -2464,6 +2656,119 @@
}
}
+static int date_interval_initialize(timelib_rel_time **rt, /*const*/ char
*format, int format_length TSRMLS_DC)
+{
+ timelib_time *b = NULL, *e = NULL;
+ timelib_rel_time *p = NULL;
+ int r = 0;
+ int retval = 0;
+ struct timelib_error_container *errors;
+
+ timelib_strtointerval(format, format_length, &b, &e, &p, &r, &errors);
+
+ if (errors->error_count > 0) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown or bad
format (%s)", format);
+ retval = FAILURE;
+ } else {
+ *rt = p;
+ retval = SUCCESS;
+ }
+ timelib_error_container_dtor(errors);
+ return retval;
+}
+
+/* {{{ date_interval_read_property */
+zval *date_interval_read_property(zval *object, zval *member, int type
TSRMLS_DC)
+{
+ php_interval_obj *obj;
+ zval *retval;
+ zval tmp_member;
+ timelib_sll value = -1;
+
+ if (member->type != IS_STRING) {
+ tmp_member = *member;
+ zval_copy_ctor(&tmp_member);
+ convert_to_string(&tmp_member);
+ member = &tmp_member;
+ }
+
+ obj = (php_interval_obj *)zend_objects_get_address(object TSRMLS_CC);
+
+#define GET_VALUE_FROM_STRUCT(n,m) \
+ if (strcmp(Z_STRVAL_P(member), m) == 0) { \
+ value = obj->diff->n; \
+ }
+ GET_VALUE_FROM_STRUCT(y, "y");
+ GET_VALUE_FROM_STRUCT(m, "m");
+ GET_VALUE_FROM_STRUCT(d, "d");
+ GET_VALUE_FROM_STRUCT(h, "h");
+ GET_VALUE_FROM_STRUCT(i, "i");
+ GET_VALUE_FROM_STRUCT(s, "s");
+ GET_VALUE_FROM_STRUCT(invert, "invert");
+ GET_VALUE_FROM_STRUCT(days, "days");
+
+ if (value == -1) {
+ php_error_docref(NULL TSRMLS_CC, E_ERROR, "Unknown property
(%s)", Z_STRVAL_P(member));
+ }
+
+ ALLOC_INIT_ZVAL(retval);
+ ZVAL_LONG(retval, value);
+
+ if (member == &tmp_member) {
+ zval_dtor(member);
+ }
+
+ return retval;
+}
+/* }}} */
+
+/* {{{ date_interval_write_property */
+void date_interval_write_property(zval *object, zval *member, zval *value
TSRMLS_DC)
+{
+ php_interval_obj *obj;
+ zval tmp_member, tmp_value;
+
+ if (member->type != IS_STRING) {
+ tmp_member = *member;
+ zval_copy_ctor(&tmp_member);
+ convert_to_string(&tmp_member);
+ member = &tmp_member;
+ }
+ obj = (php_interval_obj *)zend_objects_get_address(object TSRMLS_CC);
+
+#define SET_VALUE_FROM_STRUCT(n,m) \
+ if (strcmp(Z_STRVAL_P(member), m) == 0) { \
+ if (value->type != IS_LONG) { \
+ tmp_value = *value; \
+ zval_copy_ctor(&tmp_value); \
+ convert_to_long(&tmp_value); \
+ value = &tmp_value; \
+ } \
+ obj->diff->n = Z_LVAL_P(value); \
+ if (value == &tmp_value) { \
+ zval_dtor(value); \
+ } \
+ }
+
+ SET_VALUE_FROM_STRUCT(y, "y");
+ SET_VALUE_FROM_STRUCT(m, "m");
+ SET_VALUE_FROM_STRUCT(d, "d");
+ SET_VALUE_FROM_STRUCT(h, "h");
+ SET_VALUE_FROM_STRUCT(i, "i");
+ SET_VALUE_FROM_STRUCT(s, "s");
+ SET_VALUE_FROM_STRUCT(invert, "invert");
+
+ if (value == -1) {
+ php_error_docref(NULL TSRMLS_CC, E_ERROR, "Unknown property
(%s)", Z_STRVAL_P(member));
+ }
+
+ if (member == &tmp_member) {
+ zval_dtor(member);
+ }
+}
+/* }}} */
+
+
/* {{{ proto DateTimeZone timezone_open(string timezone)
Returns new DateTimeZone object
*/
@@ -2591,9 +2896,19 @@
dateobj = (php_date_obj *) zend_object_store_get_object(dateobject
TSRMLS_CC);
DATE_CHECK_INITIALIZED(dateobj->time, DateTime);
- offset = timelib_get_time_zone_info(dateobj->time->sse, tzobj->tzi.tz);
- RETVAL_LONG(offset->offset);
- timelib_time_offset_dtor(offset);
+ switch (tzobj->type) {
+ case TIMELIB_ZONETYPE_ID:
+ offset = timelib_get_time_zone_info(dateobj->time->sse,
tzobj->tzi.tz);
+ RETVAL_LONG(offset->offset);
+ timelib_time_offset_dtor(offset);
+ break;
+ case TIMELIB_ZONETYPE_OFFSET:
+ RETURN_LONG(tzobj->tzi.utc_offset * -60);
+ break;
+ case TIMELIB_ZONETYPE_ABBR:
+ RETURN_LONG((tzobj->tzi.z.utc_offset -
(tzobj->tzi.z.dst*60)) * -60);
+ break;
+ }
}
/* }}} */
@@ -2679,6 +2994,105 @@
}
/* }}} */
+/* {{{ proto DateInterval::__construct([string interval_spec])
+ Creates new DateInterval object.
+*/
+PHP_METHOD(DateInterval, __construct)
+{
+ char *interval_string = NULL;
+ int interval_string_length;
+ php_interval_obj *diobj;
+ timelib_rel_time *reltime;
+
+ php_set_error_handling(EH_THROW, NULL TSRMLS_CC);
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s",
&interval_string, &interval_string_length) == SUCCESS) {
+ if (date_interval_initialize(&reltime, interval_string,
interval_string_length TSRMLS_CC) == SUCCESS) {
+ diobj = zend_object_store_get_object(getThis()
TSRMLS_CC);
+ diobj->diff = reltime;
+ diobj->initialized = 1;
+ } else {
+ ZVAL_NULL(getThis());
+ }
+ }
+ php_set_error_handling(EH_NORMAL, NULL TSRMLS_CC);
+}
+/* }}} */
+
+/* {{{ date_interval_format - */
+static char *date_interval_format(char *format, int format_len,
timelib_rel_time *t)
+{
+ smart_str string = {0};
+ int i, length, have_format_spec = 0;
+ char buffer[33];
+
+ if (!format_len) {
+ return estrdup("");
+ }
+
+ for (i = 0; i < format_len; i++) {
+ if (have_format_spec) {
+ switch (format[i]) {
+ case 'Y': length = slprintf(buffer, 32, "%02d",
(int) t->y); break;
+ case 'y': length = slprintf(buffer, 32, "%d",
(int) t->y); break;
+
+ case 'M': length = slprintf(buffer, 32, "%02d",
(int) t->m); break;
+ case 'm': length = slprintf(buffer, 32, "%d",
(int) t->m); break;
+
+ case 'D': length = slprintf(buffer, 32, "%02d",
(int) t->d); break;
+ case 'd': length = slprintf(buffer, 32, "%d",
(int) t->d); break;
+
+ case 'H': length = slprintf(buffer, 32, "%02d",
(int) t->h); break;
+ case 'h': length = slprintf(buffer, 32, "%d",
(int) t->h); break;
+
+ case 'I': length = slprintf(buffer, 32, "%02d",
(int) t->i); break;
+ case 'i': length = slprintf(buffer, 32, "%d",
(int) t->i); break;
+
+ case 'S': length = slprintf(buffer, 32, "%02d",
(int) t->s); break;
+ case 's': length = slprintf(buffer, 32, "%d",
(int) t->s); break;
+
+ case 'a': length = slprintf(buffer, 32, "%d",
(int) t->days); break;
+ case 'r': length = slprintf(buffer, 32, "%s",
t->invert ? "-" : ""); break;
+ case 'R': length = slprintf(buffer, 32, "%c",
t->invert ? '-' : '+'); break;
+
+ case '%': length = slprintf(buffer, 32, "%%");
break;
+ default: buffer[0] = '%'; buffer[1] =
format[i]; buffer[2] = '\0'; length = 2; break;
+ }
+ smart_str_appendl(&string, buffer, length);
+ have_format_spec = 0;
+ } else {
+ if (format[i] == '%') {
+ have_format_spec = 1;
+ } else {
+ smart_str_appendc(&string, format[i]);
+ }
+ }
+ }
+
+ smart_str_0(&string);
+
+ return string.c;
+}
+/* }}} */
+
+/* {{{ proto string date_interval_format(DateInterval object)
+ Formats the interval.
+*/
+PHP_FUNCTION(date_interval_format)
+{
+ zval *object;
+ php_interval_obj *diobj;
+ char *format;
+ int format_len;
+
+ if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(),
"Os", &object, date_ce_interval, &format, &format_len) == FAILURE) {
+ RETURN_FALSE;
+ }
+ diobj = (php_interval_obj *) zend_object_store_get_object(object
TSRMLS_CC);
+ DATE_CHECK_INITIALIZED(diobj->initialized, DateInterval);
+
+ RETURN_STRING(date_interval_format(format, format_len, diobj->diff), 0);
+}
+/* }}} */
static int check_id_allowed(char *id, long what)
{
if (what & PHP_DATE_TIMEZONE_GROUP_AFRICA && strncasecmp(id,
"Africa/", 7) == 0) return 1;
http://cvs.php.net/viewvc.cgi/php-src/ext/date/php_date.h?r1=1.17.2.11.2.3.2.5&r2=1.17.2.11.2.3.2.6&diff_format=u
Index: php-src/ext/date/php_date.h
diff -u php-src/ext/date/php_date.h:1.17.2.11.2.3.2.5
php-src/ext/date/php_date.h:1.17.2.11.2.3.2.6
--- php-src/ext/date/php_date.h:1.17.2.11.2.3.2.5 Fri Mar 14 16:19:52 2008
+++ php-src/ext/date/php_date.h Fri Apr 25 12:35:40 2008
@@ -16,7 +16,7 @@
+----------------------------------------------------------------------+
*/
-/* $Id: php_date.h,v 1.17.2.11.2.3.2.5 2008/03/14 16:19:52 derick Exp $ */
+/* $Id: php_date.h,v 1.17.2.11.2.3.2.6 2008/04/25 12:35:40 derick Exp $ */
#ifndef PHP_DATE_H
#define PHP_DATE_H
@@ -57,9 +57,12 @@
PHP_FUNCTION(date_get_last_errors);
PHP_FUNCTION(date_format);
PHP_FUNCTION(date_modify);
+PHP_FUNCTION(date_add);
+PHP_FUNCTION(date_sub);
PHP_FUNCTION(date_timezone_get);
PHP_FUNCTION(date_timezone_set);
PHP_FUNCTION(date_offset_get);
+PHP_FUNCTION(date_diff);
PHP_FUNCTION(date_time_set);
PHP_FUNCTION(date_date_set);
@@ -76,6 +79,9 @@
PHP_FUNCTION(timezone_identifiers_list);
PHP_FUNCTION(timezone_abbreviations_list);
+PHP_METHOD(DateInterval, __construct);
+PHP_FUNCTION(date_interval_format);
+
/* Options and Configuration */
PHP_FUNCTION(date_default_timezone_set);
PHP_FUNCTION(date_default_timezone_get);
http://cvs.php.net/viewvc.cgi/php-src/ext/date/lib/README?r1=1.4.2.2&r2=1.4.2.2.4.1&diff_format=u
Index: php-src/ext/date/lib/README
diff -u php-src/ext/date/lib/README:1.4.2.2
php-src/ext/date/lib/README:1.4.2.2.4.1
--- php-src/ext/date/lib/README:1.4.2.2 Thu Nov 17 12:33:36 2005
+++ php-src/ext/date/lib/README Fri Apr 25 12:35:40 2008
@@ -3,4 +3,5 @@
Make sure you use re2c 0.9.10 or higher:
-/dat/dev/sf/re2c/re2c -d -b -o ext/date/lib/parse_date.c
ext/date/lib/parse_date.re
+re2c -d -b -o ext/date/lib/parse_date.c ext/date/lib/parse_date.re
+re2c -d -b -o ext/date/lib/parse_iso_intervals.c
ext/date/lib/parse_iso_intervals.re
http://cvs.php.net/viewvc.cgi/php-src/ext/date/lib/parse_date.c?r1=1.29.2.30.2.14.2.11&r2=1.29.2.30.2.14.2.12&diff_format=u
Index: php-src/ext/date/lib/parse_date.c
diff -u php-src/ext/date/lib/parse_date.c:1.29.2.30.2.14.2.11
php-src/ext/date/lib/parse_date.c:1.29.2.30.2.14.2.12
--- php-src/ext/date/lib/parse_date.c:1.29.2.30.2.14.2.11 Sun Mar 23
15:48:10 2008
+++ php-src/ext/date/lib/parse_date.c Fri Apr 25 12:35:40 2008
@@ -1,4 +1,4 @@
-/* Generated by re2c 0.13.3 on Sun Mar 23 11:46:55 2008 */
+/* Generated by re2c 0.13.3 on Mon Apr 7 19:58:18 2008 */
#line 1 "ext/date/lib/parse_date.re"
/*
+----------------------------------------------------------------------+
@@ -18,7 +18,7 @@
+----------------------------------------------------------------------+
*/
-/* $Id: parse_date.c,v 1.29.2.30.2.14.2.11 2008/03/23 15:48:10 iliaa Exp $ */
+/* $Id: parse_date.c,v 1.29.2.30.2.14.2.12 2008/04/25 12:35:40 derick Exp $ */
#include "timelib.h"
http://cvs.php.net/viewvc.cgi/php-src/ext/date/lib/timelib.c?r1=1.7.2.4.2.6.2.2&r2=1.7.2.4.2.6.2.3&diff_format=u
Index: php-src/ext/date/lib/timelib.c
diff -u php-src/ext/date/lib/timelib.c:1.7.2.4.2.6.2.2
php-src/ext/date/lib/timelib.c:1.7.2.4.2.6.2.3
--- php-src/ext/date/lib/timelib.c:1.7.2.4.2.6.2.2 Sun Feb 3 14:15:07 2008
+++ php-src/ext/date/lib/timelib.c Fri Apr 25 12:35:57 2008
@@ -16,7 +16,7 @@
+----------------------------------------------------------------------+
*/
-/* $Id: timelib.c,v 1.7.2.4.2.6.2.2 2008/02/03 14:15:07 derick Exp $ */
+/* $Id: timelib.c,v 1.7.2.4.2.6.2.3 2008/04/25 12:35:57 derick Exp $ */
#include "timelib.h"
#include <ctype.h>
@@ -38,6 +38,14 @@
return t;
}
+timelib_rel_time* timelib_rel_time_ctor(void)
+{
+ timelib_rel_time *t;
+ t = calloc(1, sizeof(timelib_rel_time));
+
+ return t;
+}
+
void timelib_time_tz_abbr_update(timelib_time* tm, char* tz_abbr)
{
unsigned int i;
@@ -55,6 +63,11 @@
TIMELIB_TIME_FREE(t);
}
+void timelib_rel_time_dtor(timelib_rel_time* t)
+{
+ TIMELIB_TIME_FREE(t);
+}
+
timelib_time_offset* timelib_time_offset_ctor(void)
{
timelib_time_offset *t;
@@ -114,6 +127,7 @@
TIMELIB_TIME_FREE(tz->timezone_abbr);
TIMELIB_TIME_FREE(tz->leap_times);
TIMELIB_TIME_FREE(tz);
+ tz = NULL;
}
char *timelib_get_tz_abbr_ptr(timelib_time *t)
@@ -228,3 +242,20 @@
printf("\n");
}
+void timelib_dump_rel_time(timelib_rel_time *d)
+{
+ printf("%3lldY %3lldM %3lldD / %3lldH %3lldM %3lldS (days: %lld)%s",
+ d->y, d->m, d->d, d->h, d->i, d->s, d->days, d->invert ? "
inverted" : "");
+ if (d->first_last_day_of != 0) {
+ switch (d->first_last_day_of) {
+ case 1:
+ printf(" / first day of");
+ break;
+ case 2:
+ printf(" / last day of");
+ break;
+ }
+ }
+ printf("\n");
+}
+
http://cvs.php.net/viewvc.cgi/php-src/ext/date/lib/timelib.h?r1=1.10.2.11.2.3.2.3&r2=1.10.2.11.2.3.2.4&diff_format=u
Index: php-src/ext/date/lib/timelib.h
diff -u php-src/ext/date/lib/timelib.h:1.10.2.11.2.3.2.3
php-src/ext/date/lib/timelib.h:1.10.2.11.2.3.2.4
--- php-src/ext/date/lib/timelib.h:1.10.2.11.2.3.2.3 Fri Feb 22 09:47:19 2008
+++ php-src/ext/date/lib/timelib.h Fri Apr 25 12:35:57 2008
@@ -16,7 +16,7 @@
+----------------------------------------------------------------------+
*/
-/* $Id: timelib.h,v 1.10.2.11.2.3.2.3 2008/02/22 09:47:19 derick Exp $ */
+/* $Id: timelib.h,v 1.10.2.11.2.3.2.4 2008/04/25 12:35:57 derick Exp $ */
#ifndef __TIMELIB_H__
#define __TIMELIB_H__
@@ -62,8 +62,16 @@
char *timelib_timezone_id_from_abbr(const char *abbr, long gmtoffset, int
isdst);
const timelib_tz_lookup_table *timelib_timezone_abbreviations_list(void);
+/* From parse_iso_intervals.re */
+void timelib_strtointerval(char *s, int len,
+ timelib_time **begin, timelib_time **end,
+ timelib_rel_time **period,
int *recurrences,
+ struct
timelib_error_container **errors);
+
+
/* From tm2unixtime.c */
void timelib_update_ts(timelib_time* time, timelib_tzinfo* tzi);
+void timelib_do_rel_normalize(timelib_time *base, timelib_rel_time *rt);
/* From unixtime2tm.c */
int timelib_apply_localtime(timelib_time *t, unsigned int localtime);
@@ -89,6 +97,9 @@
void timelib_tzinfo_dtor(timelib_tzinfo *tz);
timelib_tzinfo* timelib_tzinfo_clone(timelib_tzinfo *tz);
+timelib_rel_time* timelib_rel_time_ctor(void);
+void timelib_rel_time_dtor(timelib_rel_time* t);
+
timelib_time* timelib_time_ctor(void);
void timelib_time_set_option(timelib_time* tm, int option, void* option_value);
void timelib_time_dtor(timelib_time* t);
@@ -100,6 +111,7 @@
signed long timelib_date_to_int(timelib_time *d, int *error);
void timelib_dump_date(timelib_time *d, int options);
+void timelib_dump_rel_time(timelib_rel_time *d);
void timelib_decimal_hour_to_hms(double h, int *hour, int *min, int *sec);
@@ -107,4 +119,7 @@
double timelib_ts_to_juliandate(timelib_sll ts);
int timelib_astro_rise_set_altitude(timelib_time *time, double lon, double
lat, double altit, int upper_limb, double *h_rise, double *h_set, timelib_sll
*ts_rise, timelib_sll *ts_set, timelib_sll *ts_transit);
+/* from interval.c */
+timelib_rel_time *timelib_diff(timelib_time *one, timelib_time *two);
+
#endif
http://cvs.php.net/viewvc.cgi/php-src/ext/date/lib/timelib_structs.h?r1=1.13.2.6.2.3.2.3&r2=1.13.2.6.2.3.2.4&diff_format=u
Index: php-src/ext/date/lib/timelib_structs.h
diff -u php-src/ext/date/lib/timelib_structs.h:1.13.2.6.2.3.2.3
php-src/ext/date/lib/timelib_structs.h:1.13.2.6.2.3.2.4
--- php-src/ext/date/lib/timelib_structs.h:1.13.2.6.2.3.2.3 Thu Mar 13
15:59:48 2008
+++ php-src/ext/date/lib/timelib_structs.h Fri Apr 25 12:35:58 2008
@@ -16,7 +16,7 @@
+----------------------------------------------------------------------+
*/
-/* $Id: timelib_structs.h,v 1.13.2.6.2.3.2.3 2008/03/13 15:59:48 derick Exp $
*/
+/* $Id: timelib_structs.h,v 1.13.2.6.2.3.2.4 2008/04/25 12:35:58 derick Exp $
*/
#ifndef __TIMELIB_STRUCTS_H__
#define __TIMELIB_STRUCTS_H__
@@ -124,6 +124,8 @@
int weekday_behavior; /* 0: the current day should *not* be counted
when advancing forwards; 1: the current day *should* be counted */
int first_last_day_of;
+ int invert; /* Whether the difference should be inverted */
+ timelib_sll days; /* Contains the number of *days*, instead of Y-M-D
differences */
} timelib_rel_time;
typedef struct timelib_time_offset {
http://cvs.php.net/viewvc.cgi/php-src/ext/date/lib/tm2unixtime.c?r1=1.13.2.3.2.2.2.3&r2=1.13.2.3.2.2.2.4&diff_format=u
Index: php-src/ext/date/lib/tm2unixtime.c
diff -u php-src/ext/date/lib/tm2unixtime.c:1.13.2.3.2.2.2.3
php-src/ext/date/lib/tm2unixtime.c:1.13.2.3.2.2.2.4
--- php-src/ext/date/lib/tm2unixtime.c:1.13.2.3.2.2.2.3 Sun Feb 3 14:15:07 2008
+++ php-src/ext/date/lib/tm2unixtime.c Fri Apr 25 12:35:58 2008
@@ -16,7 +16,7 @@
+----------------------------------------------------------------------+
*/
-/* $Id: tm2unixtime.c,v 1.13.2.3.2.2.2.3 2008/02/03 14:15:07 derick Exp $ */
+/* $Id: tm2unixtime.c,v 1.13.2.3.2.2.2.4 2008/04/25 12:35:58 derick Exp $ */
#include "timelib.h"
@@ -49,6 +49,41 @@
return 0;
}
+static int do_range_limit_days_relative(timelib_sll *base_y, timelib_sll
*base_m, timelib_sll *y, timelib_sll *m, timelib_sll *d)
+{
+ timelib_sll leapyear;
+ timelib_sll days_this_month;
+ timelib_sll next_month, next_year;
+ timelib_sll days_next_month;
+
+ do_range_limit(1, 13, 12, base_m, base_y);
+
+ leapyear = timelib_is_leap(*base_y);
+ days_this_month = leapyear ? days_in_month_leap[*base_m] :
days_in_month[*base_m];
+ next_month = (*base_m) + 1;
+
+ if (next_month > 12) {
+ next_month -= 12;
+ next_year = (*base_y) + 1;
+ } else {
+ next_year = (*base_y);
+ }
+ leapyear = timelib_is_leap(next_year);
+ days_next_month = leapyear ? days_in_month_leap[next_month] :
days_in_month[next_month];
+
+ if (*d < 0) {
+ *d += days_this_month;
+ (*m)--;
+ return 1;
+ }
+ if (*d > days_next_month) {
+ *d -= days_next_month;
+ (*m)++;
+ return 1;
+ }
+ return 0;
+}
+
static int do_range_limit_days(timelib_sll *y, timelib_sll *m, timelib_sll *d)
{
timelib_sll leapyear;
@@ -101,6 +136,17 @@
time->have_weekday_relative = 0;
}
+void timelib_do_rel_normalize(timelib_time *base, timelib_rel_time *rt)
+{
+ do {} while (do_range_limit(0, 60, 60, &rt->s, &rt->i));
+ do {} while (do_range_limit(0, 60, 60, &rt->i, &rt->h));
+ do {} while (do_range_limit(0, 24, 24, &rt->h, &rt->d));
+ do {} while (do_range_limit(0, 12, 12, &rt->m, &rt->y));
+
+ do {} while (do_range_limit_days_relative(&base->y, &base->m, &rt->y,
&rt->m, &rt->d));
+ do {} while (do_range_limit(0, 12, 12, &rt->m, &rt->y));
+}
+
static void do_normalize(timelib_time* time)
{
do {} while (do_range_limit(0, 60, 60, &time->s, &time->i));
@@ -293,7 +339,20 @@
}
timelib_time_offset_dtor(before);
timelib_time_offset_dtor(after);
-
+
+ {
+ timelib_time_offset *gmt_offset;
+
+ gmt_offset =
timelib_get_time_zone_info(tz->sse + tmp, tzi);
+ tz->z = gmt_offset->offset;
+
+ tz->dst = gmt_offset->is_dst;
+ if (tz->tz_abbr) {
+ free(tz->tz_abbr);
+ }
+ tz->tz_abbr = strdup(gmt_offset->abbr);
+ timelib_time_offset_dtor(gmt_offset);
+ }
return tmp;
}
}
http://cvs.php.net/viewvc.cgi/php-src/ext/date/lib/interval.c?view=markup&rev=1.1
Index: php-src/ext/date/lib/interval.c
+++ php-src/ext/date/lib/interval.c
http://cvs.php.net/viewvc.cgi/php-src/ext/date/lib/parse_iso_intervals.c?view=markup&rev=1.1
Index: php-src/ext/date/lib/parse_iso_intervals.c
+++ php-src/ext/date/lib/parse_iso_intervals.c
http://cvs.php.net/viewvc.cgi/php-src/ext/date/lib/parse_iso_intervals.re?view=markup&rev=1.1
Index: php-src/ext/date/lib/parse_iso_intervals.re
+++ php-src/ext/date/lib/parse_iso_intervals.re
http://cvs.php.net/viewvc.cgi/php-src/ext/date/tests/bug44742.phpt?view=markup&rev=1.1
Index: php-src/ext/date/tests/bug44742.phpt
+++ php-src/ext/date/tests/bug44742.phpt
--
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php