diff options
author | Derick Rethans <github@derickrethans.nl> | 2016-10-05 11:24:15 -0400 |
---|---|---|
committer | Derick Rethans <github@derickrethans.nl> | 2016-10-05 15:03:06 -0400 |
commit | 55626549d81d0feadb1d160be78fcf2b898a48cc (patch) | |
tree | a00c6239804f2ad68ccc3470e63e83eb18f7897f /ext/date/php_date.c | |
parent | d5b77d66626b138a83b6c0d16f746893fefa29ee (diff) | |
download | php-git-microseconds.tar.gz |
Improve support for microseconds with Date/Timemicroseconds
It fixes several bugs:
- Fixed bug #45554 (Inconsistent behavior of the u format char).
- Fixed bug #48225 (DateTime parser doesn't set microseconds for "now").
- Fixed bug #52514 (microseconds are missing in DateTime class).
- Fixed bug #52519 (microseconds in DateInterval are missing).
- Fixed bug #68506 (General DateTime improvments needed for microseconds to become useful).
- Fixed bug #73109 (timelib_meridian doesn't parse dots correctly).
- Fixed bug #73247 (DateTime constructor does not initialise microseconds property).
It also updates timelib to 2016.04, and updates a data mapping file, which
causes changes to the volatile abbreviations tests.
Diffstat (limited to 'ext/date/php_date.c')
-rw-r--r-- | ext/date/php_date.c | 73 |
1 files changed, 63 insertions, 10 deletions
diff --git a/ext/date/php_date.c b/ext/date/php_date.c index e960161987..7371590469 100644 --- a/ext/date/php_date.c +++ b/ext/date/php_date.c @@ -253,12 +253,14 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_date_time_set, 0, 0, 3) ZEND_ARG_INFO(0, hour) ZEND_ARG_INFO(0, minute) ZEND_ARG_INFO(0, second) + ZEND_ARG_INFO(0, microseconds) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_date_method_time_set, 0, 0, 2) ZEND_ARG_INFO(0, hour) ZEND_ARG_INFO(0, minute) ZEND_ARG_INFO(0, second) + ZEND_ARG_INFO(0, microseconds) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_date_date_set, 0, 0, 4) @@ -2370,6 +2372,8 @@ static HashTable *date_object_get_properties_interval(zval *object) /* {{{ */ PHP_DATE_INTERVAL_ADD_PROPERTY("h", h); PHP_DATE_INTERVAL_ADD_PROPERTY("i", i); PHP_DATE_INTERVAL_ADD_PROPERTY("s", s); + ZVAL_DOUBLE(&zv, (double)intervalobj->diff->f); + zend_hash_str_update(props, "f", sizeof("f") - 1, &zv); PHP_DATE_INTERVAL_ADD_PROPERTY("weekday", weekday); PHP_DATE_INTERVAL_ADD_PROPERTY("weekday_behavior", weekday_behavior); PHP_DATE_INTERVAL_ADD_PROPERTY("first_last_day_of", first_last_day_of); @@ -2487,6 +2491,23 @@ static void update_errors_warnings(timelib_error_container *last_errors) /* {{{ DATEG(last_errors) = last_errors; } /* }}} */ +static void php_date_set_time_fraction(timelib_time *time, int microseconds) +{ + time->f = microseconds / 1000000; +} + +static void php_date_set_current_time_fraction(timelib_time *time) +{ +#if HAVE_GETTIMEOFDAY + struct timeval tp = {0}; /* For setting microseconds */ + + gettimeofday(&tp, NULL); + timelib_set_fraction_from_timeval(time, tp); +#else + time->f = 0; +#endif +} + PHPAPI int php_date_initialize(php_date_obj *dateobj, /*const*/ char *time_str, size_t time_str_len, char *format, zval *timezone_object, int ctor) /* {{{ */ { timelib_time *now; @@ -2560,7 +2581,7 @@ PHPAPI int php_date_initialize(php_date_obj *dateobj, /*const*/ char *time_str, break; } timelib_unixtime2local(now, (timelib_sll) time(NULL)); - + php_date_set_current_time_fraction(now); timelib_fill_holes(dateobj->time, now, TIMELIB_NO_CLONE); timelib_update_ts(dateobj->time, tzi); timelib_update_from_sse(dateobj->time); @@ -3056,6 +3077,11 @@ static int php_date_modify(zval *object, char *modify, size_t modify_len) /* {{{ dateobj->time->s = 0; } } + + if (tmp_time->f != -99999) { + dateobj->time->f = tmp_time->f; + } + timelib_time_dtor(tmp_time); timelib_update_ts(dateobj->time, NULL); @@ -3355,7 +3381,7 @@ PHP_FUNCTION(date_offset_get) } /* }}} */ -static void php_date_time_set(zval *object, zend_long h, zend_long i, zend_long s, zval *return_value) /* {{{ */ +static void php_date_time_set(zval *object, zend_long h, zend_long i, zend_long s, zend_long ms, zval *return_value) /* {{{ */ { php_date_obj *dateobj; @@ -3364,22 +3390,23 @@ static void php_date_time_set(zval *object, zend_long h, zend_long i, zend_long dateobj->time->h = h; dateobj->time->i = i; dateobj->time->s = s; + dateobj->time->f = ((double) ms) / 1000000; timelib_update_ts(dateobj->time, NULL); } /* }}} */ -/* {{{ proto DateTime date_time_set(DateTime object, long hour, long minute[, long second]) +/* {{{ proto DateTime date_time_set(DateTime object, long hour, long minute[, long second[, long microseconds]]) Sets the time. */ PHP_FUNCTION(date_time_set) { zval *object; - zend_long h, i, s = 0; + zend_long h, i, s = 0, ms = 0; - if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Oll|l", &object, date_ce_date, &h, &i, &s) == FAILURE) { + if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Oll|ll", &object, date_ce_date, &h, &i, &s, &ms) == FAILURE) { RETURN_FALSE; } - php_date_time_set(object, h, i, s, return_value); + php_date_time_set(object, h, i, s, ms, return_value); Z_ADDREF_P(object); ZVAL_COPY_VALUE(return_value, object); @@ -3391,14 +3418,14 @@ PHP_FUNCTION(date_time_set) PHP_METHOD(DateTimeImmutable, setTime) { zval *object, new_object; - zend_long h, i, s = 0; + zend_long h, i, s = 0, ms = 0; - if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Oll|l", &object, date_ce_immutable, &h, &i, &s) == FAILURE) { + if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Oll|ll", &object, date_ce_immutable, &h, &i, &s, &ms) == FAILURE) { RETURN_FALSE; } date_clone_immutable(object, &new_object); - php_date_time_set(&new_object, h, i, s, return_value); + php_date_time_set(&new_object, h, i, s, ms, return_value); ZVAL_OBJ(return_value, Z_OBJ(new_object)); } @@ -3514,6 +3541,7 @@ static void php_date_timestamp_set(zval *object, zend_long timestamp, zval *retu DATE_CHECK_INITIALIZED(dateobj->time, DateTime); timelib_unixtime2local(dateobj->time, (timelib_sll)timestamp); timelib_update_ts(dateobj->time, NULL); + php_date_set_time_fraction(dateobj->time, 0); } /* }}} */ /* {{{ proto DateTime date_timestamp_set(DateTime object, long unixTimestamp) @@ -3979,6 +4007,7 @@ zval *date_interval_read_property(zval *object, zval *member, int type, void **c zval *retval; zval tmp_member; timelib_sll value = -1; + double fvalue = -1; if (Z_TYPE_P(member) != IS_STRING) { tmp_member = *member; @@ -4010,6 +4039,10 @@ zval *date_interval_read_property(zval *object, zval *member, int type, void **c GET_VALUE_FROM_STRUCT(h, "h"); GET_VALUE_FROM_STRUCT(i, "i"); GET_VALUE_FROM_STRUCT(s, "s"); + if (strcmp(Z_STRVAL_P(member), "f") == 0) { + fvalue = obj->diff->f; + break; + } GET_VALUE_FROM_STRUCT(invert, "invert"); GET_VALUE_FROM_STRUCT(days, "days"); /* didn't find any */ @@ -4024,7 +4057,9 @@ zval *date_interval_read_property(zval *object, zval *member, int type, void **c retval = rv; - if (value != -99999) { + if (fvalue != -1) { + ZVAL_DOUBLE(retval, fvalue); + } else if (value != -99999) { ZVAL_LONG(retval, value); } else { ZVAL_FALSE(retval); @@ -4075,6 +4110,10 @@ void date_interval_write_property(zval *object, zval *member, zval *value, void SET_VALUE_FROM_STRUCT(h, "h"); SET_VALUE_FROM_STRUCT(i, "i"); SET_VALUE_FROM_STRUCT(s, "s"); + if (strcmp(Z_STRVAL_P(member), "f") == 0) { + obj->diff->f = zval_get_double(value); + break; + } SET_VALUE_FROM_STRUCT(invert, "invert"); /* didn't find any */ (zend_get_std_object_handlers())->write_property(object, member, value, cache_slot); @@ -4139,12 +4178,23 @@ static int php_date_interval_initialize_from_hash(zval **return_value, php_inter } \ } while (0); +#define PHP_DATE_INTERVAL_READ_PROPERTY_DOUBLE(element, member, def) \ + do { \ + zval *z_arg = zend_hash_str_find(myht, element, sizeof(element) - 1); \ + if (z_arg) { \ + (*intobj)->diff->member = (double)zval_get_double(z_arg); \ + } else { \ + (*intobj)->diff->member = (double)def; \ + } \ + } while (0); + PHP_DATE_INTERVAL_READ_PROPERTY("y", y, timelib_sll, -1) PHP_DATE_INTERVAL_READ_PROPERTY("m", m, timelib_sll, -1) PHP_DATE_INTERVAL_READ_PROPERTY("d", d, timelib_sll, -1) PHP_DATE_INTERVAL_READ_PROPERTY("h", h, timelib_sll, -1) PHP_DATE_INTERVAL_READ_PROPERTY("i", i, timelib_sll, -1) PHP_DATE_INTERVAL_READ_PROPERTY("s", s, timelib_sll, -1) + PHP_DATE_INTERVAL_READ_PROPERTY_DOUBLE("f", f, -1) PHP_DATE_INTERVAL_READ_PROPERTY("weekday", weekday, int, -1) PHP_DATE_INTERVAL_READ_PROPERTY("weekday_behavior", weekday_behavior, int, -1) PHP_DATE_INTERVAL_READ_PROPERTY("first_last_day_of", first_last_day_of, int, -1) @@ -4254,6 +4304,9 @@ static zend_string *date_interval_format(char *format, size_t format_len, timeli case 'S': length = slprintf(buffer, 32, "%02" ZEND_LONG_FMT_SPEC, (zend_long) t->s); break; case 's': length = slprintf(buffer, 32, ZEND_LONG_FMT, (zend_long) t->s); break; + case 'F': length = slprintf(buffer, 32, "%06" ZEND_LONG_FMT_SPEC, (zend_long) (t->f * 1000000)); break; + case 'f': length = slprintf(buffer, 32, ZEND_LONG_FMT, (zend_long) (t->f * 1000000)); break; + case 'a': { if ((int) t->days != -99999) { length = slprintf(buffer, 32, "%d", (int) t->days); |