@@ -2045,6 +2045,11 @@ static zend_object *date_object_clone_interval(zend_object *this_ptr) /* {{{ */
20452045 php_interval_obj * new_obj = php_interval_obj_from_obj (date_object_new_interval (old_obj -> std .ce ));
20462046
20472047 zend_objects_clone_members (& new_obj -> std , & old_obj -> std );
2048+ new_obj -> civil_or_wall = old_obj -> civil_or_wall ;
2049+ new_obj -> from_string = old_obj -> from_string ;
2050+ if (old_obj -> date_string ) {
2051+ new_obj -> date_string = zend_string_copy (old_obj -> date_string );
2052+ }
20482053 new_obj -> initialized = old_obj -> initialized ;
20492054 if (old_obj -> diff ) {
20502055 new_obj -> diff = timelib_rel_time_clone (old_obj -> diff );
@@ -2061,16 +2066,17 @@ static HashTable *date_object_get_gc_interval(zend_object *object, zval **table,
20612066 return zend_std_get_properties (object );
20622067} /* }}} */
20632068
2064- static HashTable * date_object_get_properties_interval ( zend_object * object ) /* {{{ */
2069+ static void date_interval_object_to_hash ( php_interval_obj * intervalobj , HashTable * props )
20652070{
2066- HashTable * props ;
20672071 zval zv ;
2068- php_interval_obj * intervalobj ;
20692072
2070- intervalobj = php_interval_obj_from_obj (object );
2071- props = zend_std_get_properties (object );
2072- if (!intervalobj -> initialized ) {
2073- return props ;
2073+ /* Records whether this is a special relative interval that needs to be recreated from a string */
2074+ if (intervalobj -> from_string ) {
2075+ ZVAL_BOOL (& zv , (zend_bool )intervalobj -> from_string );
2076+ zend_hash_str_update (props , "from_string" , strlen ("from_string" ), & zv );
2077+ ZVAL_STR_COPY (& zv , intervalobj -> date_string );
2078+ zend_hash_str_update (props , "date_string" , strlen ("date_string" ), & zv );
2079+ return ;
20742080 }
20752081
20762082#define PHP_DATE_INTERVAL_ADD_PROPERTY (n ,f ) \
@@ -2085,20 +2091,31 @@ static HashTable *date_object_get_properties_interval(zend_object *object) /* {{
20852091 PHP_DATE_INTERVAL_ADD_PROPERTY ("s" , s );
20862092 ZVAL_DOUBLE (& zv , (double )intervalobj -> diff -> us / 1000000.0 );
20872093 zend_hash_str_update (props , "f" , sizeof ("f" ) - 1 , & zv );
2088- PHP_DATE_INTERVAL_ADD_PROPERTY ("weekday" , weekday );
2089- PHP_DATE_INTERVAL_ADD_PROPERTY ("weekday_behavior" , weekday_behavior );
2090- PHP_DATE_INTERVAL_ADD_PROPERTY ("first_last_day_of" , first_last_day_of );
20912094 PHP_DATE_INTERVAL_ADD_PROPERTY ("invert" , invert );
20922095 if (intervalobj -> diff -> days != -99999 ) {
20932096 PHP_DATE_INTERVAL_ADD_PROPERTY ("days" , days );
20942097 } else {
20952098 ZVAL_FALSE (& zv );
20962099 zend_hash_str_update (props , "days" , sizeof ("days" )- 1 , & zv );
20972100 }
2098- PHP_DATE_INTERVAL_ADD_PROPERTY ("special_type" , special .type );
2099- PHP_DATE_INTERVAL_ADD_PROPERTY ("special_amount" , special .amount );
2100- PHP_DATE_INTERVAL_ADD_PROPERTY ("have_weekday_relative" , have_weekday_relative );
2101- PHP_DATE_INTERVAL_ADD_PROPERTY ("have_special_relative" , have_special_relative );
2101+ ZVAL_BOOL (& zv , (zend_bool )intervalobj -> from_string );
2102+ zend_hash_str_update (props , "from_string" , strlen ("from_string" ), & zv );
2103+
2104+ #undef PHP_DATE_INTERVAL_ADD_PROPERTY
2105+ }
2106+
2107+ static HashTable * date_object_get_properties_interval (zend_object * object ) /* {{{ */
2108+ {
2109+ HashTable * props ;
2110+ php_interval_obj * intervalobj ;
2111+
2112+ intervalobj = php_interval_obj_from_obj (object );
2113+ props = zend_std_get_properties (object );
2114+ if (!intervalobj -> initialized ) {
2115+ return props ;
2116+ }
2117+
2118+ date_interval_object_to_hash (intervalobj , props );
21022119
21032120 return props ;
21042121} /* }}} */
@@ -2166,6 +2183,10 @@ static void date_object_free_storage_interval(zend_object *object) /* {{{ */
21662183{
21672184 php_interval_obj * intern = php_interval_obj_from_obj (object );
21682185
2186+ if (intern -> date_string ) {
2187+ zend_string_release (intern -> date_string );
2188+ intern -> date_string = NULL ;
2189+ }
21692190 timelib_rel_time_dtor (intern -> diff );
21702191 zend_object_std_dtor (& intern -> std );
21712192} /* }}} */
@@ -3082,7 +3103,7 @@ static void php_date_sub(zval *object, zval *interval, zval *return_value) /* {{
30823103 intobj = Z_PHPINTERVAL_P (interval );
30833104 DATE_CHECK_INITIALIZED (intobj -> initialized , DateInterval );
30843105
3085- if (intobj -> diff -> have_special_relative ) {
3106+ if (intobj -> diff -> have_weekday_relative || intobj -> diff -> have_special_relative ) {
30863107 php_error_docref (NULL , E_WARNING , "Only non-special relative time specifications are supported for subtraction" );
30873108 return ;
30883109 }
@@ -4092,6 +4113,41 @@ PHP_METHOD(DateInterval, __construct)
40924113
40934114static void php_date_interval_initialize_from_hash (zval * * return_value , php_interval_obj * * intobj , HashTable * myht ) /* {{{ */
40944115{
4116+ /* If ->diff is already set, then we need to free it first */
4117+ if ((* intobj )-> diff ) {
4118+ timelib_rel_time_dtor ((* intobj )-> diff );
4119+ }
4120+
4121+ /* If we have a date_string, use that instead */
4122+ zval * date_str = zend_hash_str_find (myht , "date_string" , strlen ("date_string" ));
4123+ if (date_str && Z_TYPE_P (date_str ) == IS_STRING ) {
4124+ timelib_time * time ;
4125+ timelib_error_container * err = NULL ;
4126+
4127+ time = timelib_strtotime (Z_STRVAL_P (date_str ), Z_STRLEN_P (date_str ), & err , DATE_TIMEZONEDB , php_date_parse_tzfile_wrapper );
4128+
4129+ if (err -> error_count > 0 ) {
4130+ php_error_docref (NULL ,
4131+ E_WARNING ,
4132+ "Unknown or bad format (%s) at position %d (%c) while unserializing: %s" ,
4133+ Z_STRVAL_P (date_str ),
4134+ err -> error_messages [0 ].position ,
4135+ err -> error_messages [0 ].character ? err -> error_messages [0 ].character : ' ' , err -> error_messages [0 ].message );
4136+ }
4137+
4138+ (* intobj )-> diff = timelib_rel_time_clone (& time -> relative );
4139+ (* intobj )-> initialized = 1 ;
4140+ (* intobj )-> civil_or_wall = PHP_DATE_CIVIL ;
4141+ (* intobj )-> from_string = true;
4142+ (* intobj )-> date_string = zend_string_copy (Z_STR_P (date_str ));
4143+
4144+ timelib_time_dtor (time );
4145+ timelib_error_container_dtor (err );
4146+
4147+ return ;
4148+ }
4149+
4150+ /* Set new value */
40954151 (* intobj )-> diff = timelib_rel_time_ctor ();
40964152
40974153#define PHP_DATE_INTERVAL_READ_PROPERTY (element , member , itype , def ) \
@@ -4170,6 +4226,7 @@ static void php_date_interval_initialize_from_hash(zval **return_value, php_inte
41704226 (* intobj )-> civil_or_wall = val ;
41714227 }
41724228 }
4229+
41734230 (* intobj )-> initialized = 1 ;
41744231} /* }}} */
41754232
@@ -4192,6 +4249,44 @@ PHP_METHOD(DateInterval, __set_state)
41924249}
41934250/* }}} */
41944251
4252+ /* {{{ */
4253+ PHP_METHOD (DateInterval , __serialize )
4254+ {
4255+ zval * object = ZEND_THIS ;
4256+ php_interval_obj * intervalobj ;
4257+ HashTable * myht ;
4258+
4259+ ZEND_PARSE_PARAMETERS_NONE ();
4260+
4261+ intervalobj = Z_PHPINTERVAL_P (object );
4262+ DATE_CHECK_INITIALIZED (intervalobj -> initialized , DateInterval );
4263+
4264+ array_init (return_value );
4265+ myht = Z_ARRVAL_P (return_value );
4266+ date_interval_object_to_hash (intervalobj , myht );
4267+ }
4268+ /* }}} */
4269+
4270+
4271+ /* {{{ */
4272+ PHP_METHOD (DateInterval , __unserialize )
4273+ {
4274+ zval * object = ZEND_THIS ;
4275+ php_interval_obj * intervalobj ;
4276+ zval * array ;
4277+ HashTable * myht ;
4278+
4279+ ZEND_PARSE_PARAMETERS_START (1 , 1 )
4280+ Z_PARAM_ARRAY (array )
4281+ ZEND_PARSE_PARAMETERS_END ();
4282+
4283+ intervalobj = Z_PHPINTERVAL_P (object );
4284+ myht = Z_ARRVAL_P (array );
4285+
4286+ php_date_interval_initialize_from_hash (& object , & intervalobj , myht );
4287+ }
4288+ /* }}} */
4289+
41954290/* {{{ */
41964291PHP_METHOD (DateInterval , __wakeup )
41974292{
@@ -4235,6 +4330,8 @@ PHP_FUNCTION(date_interval_create_from_date_string)
42354330 diobj -> diff = timelib_rel_time_clone (& time -> relative );
42364331 diobj -> initialized = 1 ;
42374332 diobj -> civil_or_wall = PHP_DATE_CIVIL ;
4333+ diobj -> from_string = true;
4334+ diobj -> date_string = zend_string_copy (time_str );
42384335
42394336cleanup :
42404337 timelib_time_dtor (time );
0 commit comments