summaryrefslogtreecommitdiff
path: root/ext/date/php_date.c
diff options
context:
space:
mode:
Diffstat (limited to 'ext/date/php_date.c')
-rw-r--r--ext/date/php_date.c73
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);