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

Reply via email to