fix timestamp support
authorMichael Wallner <mike@php.net>
Thu, 16 Dec 2021 08:48:54 +0000 (09:48 +0100)
committerMichael Wallner <mike@php.net>
Thu, 16 Dec 2021 08:48:54 +0000 (09:48 +0100)
ion.c
ion.stub.php
ion_arginfo.h
ion_private.h
tests/Timestamp.phpt

diff --git a/ion.c b/ion.c
index 5a691fd3a37a4ce68efe9e4968c7bbeaa4dd2adc..6bf02f5b6178ebc84511c727a525e8f0780fa254 100644 (file)
--- a/ion.c
+++ b/ion.c
@@ -1506,6 +1506,9 @@ PHP_MINIT_FUNCTION(ion)
        // Annotation
        ce_Annotation = register_class_ion_Annotation();
 
+       // Catalog
+       php_ion_register(catalog, Catalog);
+
        // Collection
        ce_Collection = register_class_ion_Collection();
 
@@ -1539,9 +1542,8 @@ PHP_MINIT_FUNCTION(ion)
        ce_Symbol_System_SID = register_class_ion_Symbol_System_SID();
 
        // Timestamp
-       php_ion_register(timestamp, Timestamp, php_date_get_date_ce());
+       ce_Timestamp = register_class_ion_Timestamp(php_date_get_date_ce());
        ce_Timestamp_Precision = register_class_ion_Timestamp_Precision();
-       php_ion_register(catalog, Catalog);
 
        // Type
        php_ion_register(type, Type);
@@ -1582,6 +1584,7 @@ PHP_GSHUTDOWN_FUNCTION(ion)
 }
 
 static zend_module_dep ion_module_deps[] = {
+       ZEND_MOD_REQUIRED("date")
        ZEND_MOD_REQUIRED("spl")
        ZEND_MOD_END
 };
index e874b927018ee1fe210d0371f9ff80ba377cac0b..ef6bbef557dde54347c345df4bba220ec3c5951b 100644 (file)
@@ -162,6 +162,9 @@ enum Precision : int {
     case Min            = 0x1|0x2|0x4|0x10;
     case Sec            = 0x1|0x2|0x4|0x10|0x20;
     case Frac           = 0x1|0x2|0x4|0x10|0x20|0x40;
+    case MinTZ          = 0x1|0x2|0x4|0x10|0x80;
+    case SecTZ          = 0x1|0x2|0x4|0x10|0x20|0x80;
+    case FracTZ         = 0x1|0x2|0x4|0x10|0x20|0x40|0x80;
 }
 namespace ion;
 class Timestamp extends \DateTime {
index 187891b9e062f2b3b7b8de809c286e98a33250de..5d48e0316e953506816bd885a864be9a7134e7ff 100644 (file)
@@ -1,5 +1,5 @@
 /* This is a generated file, edit the .stub.php file instead.
- * Stub hash: 3639336622da610f8866722b870d87563646465f */
+ * Stub hash: 31c610f8d923117a4e69635ba3eb9387087f66fd */
 
 ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_ion_serialize, 0, 1, IS_STRING, 0)
        ZEND_ARG_TYPE_INFO(0, data, IS_MIXED, 0)
@@ -1344,6 +1344,18 @@ static zend_class_entry *register_class_ion_Timestamp_Precision(void)
        ZVAL_LONG(&enum_case_Frac_value, 119);
        zend_enum_add_case_cstr(class_entry, "Frac", &enum_case_Frac_value);
 
+       zval enum_case_MinTZ_value;
+       ZVAL_LONG(&enum_case_MinTZ_value, 151);
+       zend_enum_add_case_cstr(class_entry, "MinTZ", &enum_case_MinTZ_value);
+
+       zval enum_case_SecTZ_value;
+       ZVAL_LONG(&enum_case_SecTZ_value, 183);
+       zend_enum_add_case_cstr(class_entry, "SecTZ", &enum_case_SecTZ_value);
+
+       zval enum_case_FracTZ_value;
+       ZVAL_LONG(&enum_case_FracTZ_value, 247);
+       zend_enum_add_case_cstr(class_entry, "FracTZ", &enum_case_FracTZ_value);
+
        return class_entry;
 }
 
index 809f8532618933d371cdeab49e131cf9f52c280c..c2333332f21ac27c03473549d69ba84a1c7a6f54 100644 (file)
@@ -544,6 +544,9 @@ typedef php_date_obj php_ion_timestamp;
 
 static inline zend_long php_usec_from_ion(const decQuad *frac, decContext *ctx)
 {
+       if (!ctx) {
+               ctx = &g_dec_ctx;
+       }
        decQuad microsecs, result;
        decQuadMultiply(&result, decQuadFromInt32(&microsecs, 1000000), frac, ctx);
        return (zend_long) decQuadToUInt32(&result, ctx, DEC_ROUND_HALF_EVEN);
@@ -551,13 +554,16 @@ static inline zend_long php_usec_from_ion(const decQuad *frac, decContext *ctx)
 
 static inline decQuad *ion_ts_frac_from_usec(decQuad *frac, zend_long usec, decContext *ctx)
 {
+       if (!ctx) {
+               ctx = &g_dec_ctx;
+       }
        decQuad microsecs, us;
        return decQuadDivide(frac, decQuadFromInt32(&us, usec), decQuadFromInt32(&microsecs, 1000000), ctx);
 }
 
-static inline zend_string *php_dt_format_from_precision(uint8_t precision)
+static inline zend_string *php_dt_format_from_precision(int precision)
 {
-       switch (precision) {
+       switch (precision & 0x7f) {
        case ION_TS_FRAC:
                return zend_string_init(ZEND_STRL("c"), 0);
        case ION_TS_SEC:
@@ -579,7 +585,9 @@ static inline timelib_time* php_time_from_ion(const ION_TIMESTAMP *ts, decContex
 {
        timelib_time *time = timelib_time_ctor();
 
-       switch (ts->precision) {
+       int precision = ION_TS_FRAC;
+       ion_timestamp_get_precision(ts,  &precision);
+       switch (precision) {
        case ION_TS_FRAC:
                time->us = php_usec_from_ion(&ts->fraction, ctx);
                /* fallthrough */
@@ -601,10 +609,16 @@ static inline timelib_time* php_time_from_ion(const ION_TIMESTAMP *ts, decContex
                /* fallthrough */
        default:
                time->z = ts->tz_offset * 60;
+               if (time->z) {
+                       time->zone_type = TIMELIB_ZONETYPE_OFFSET;
+               } else {
+                       time->zone_type = TIMELIB_ZONETYPE_ID;
+                       time->tz_info = get_timezone_info();
+               }
        }
 
        if (fmt) {
-               *fmt = php_dt_format_from_precision(ts->precision);
+               *fmt = php_dt_format_from_precision(precision);
        }
        return time;
 }
@@ -614,11 +628,11 @@ static inline ION_TIMESTAMP *ion_timestamp_from_php(ION_TIMESTAMP *buf, php_ion_
        memset(buf, 0, sizeof(*buf));
 
        zval tmp;
-       uint8_t precision = Z_LVAL_P(zend_read_property(ts->std.ce, &ts->std, ZEND_STRL("precision"), 0, &tmp));
+       int precision = Z_LVAL_P(zend_read_property(ts->std.ce, &ts->std, ZEND_STRL("precision"), 0, &tmp));
 
        if (!precision || precision > ION_TS_FRAC) {
                zend_throw_exception_ex(spl_ce_InvalidArgumentException, IERR_INVALID_ARG,
-                               "Invalid precision (%u) of ion\\Timestamp", (unsigned) precision);
+                               "Invalid precision (%d) of ion\\Timestamp", precision);
        } else switch ((buf->precision = precision)) {
        case ION_TS_FRAC:
                ion_ts_frac_from_usec(&buf->fraction, ts->time->us, ctx);
@@ -641,6 +655,9 @@ static inline ION_TIMESTAMP *ion_timestamp_from_php(ION_TIMESTAMP *buf, php_ion_
                /* fallthrough */
        default:
                buf->tz_offset = ts->time->z / 60;
+               if (buf->tz_offset) {
+                       buf->precision |= 0x80;
+               }
        }
 
        return buf;
@@ -658,15 +675,6 @@ static inline void php_ion_timestamp_ctor(php_ion_timestamp *obj, zend_long prec
        zend_string_release(fmt);
 }
 
-static inline void php_ion_timestamp_dtor(php_ion_timestamp *obj)
-{
-       if (obj->time) {
-               timelib_time_dtor(obj->time);
-       }
-}
-
-php_ion_decl(timestamp, Timestamp, php_ion_timestamp_dtor(obj));
-
 typedef struct php_ion_catalog {
        ION_CATALOG *cat;
        zend_object std;
index cb50cf05d0a7b74f82961a308fef2cf0690b552d..6b263ecbb522716a0ca2fb6a40092e69c4b9e556 100644 (file)
@@ -2,6 +2,8 @@
 ion\Timestamp
 --EXTENSIONS--
 ion
+--INI--
+date.timezone=CET
 --FILE--
 TEST
 <?php
@@ -22,32 +24,56 @@ DONE
 --EXPECTF--
 TEST
 caught empty
-object(ion\Timestamp)#%d (2) {
+object(ion\Timestamp)#%d (5) {
   ["precision"]=>
   int(7)
   ["format"]=>
   string(7) "Y-m-d\T"
+  ["date"]=>
+  string(26) "2021-12-07 14:08:51.000000"
+  ["timezone_type"]=>
+  int(1)
+  ["timezone"]=>
+  string(6) "+00:00"
 }
 string(11) "2021-12-07T"
-object(ion\Timestamp)#%d (2) {
+object(ion\Timestamp)#%d (5) {
   ["precision"]=>
   int(7)
   ["format"]=>
   string(7) "Y-m-d\T"
+  ["date"]=>
+  string(26) "2021-12-07 14:08:51.000000"
+  ["timezone_type"]=>
+  int(1)
+  ["timezone"]=>
+  string(6) "+00:00"
 }
 string(11) "2021-12-07T"
-object(ion\Timestamp)#%d (2) {
+object(ion\Timestamp)#%d (5) {
   ["precision"]=>
   int(23)
   ["format"]=>
   string(11) "Y-m-d\TH:iP"
+  ["date"]=>
+  string(26) "2020-10-01 00:00:00.000000"
+  ["timezone_type"]=>
+  int(3)
+  ["timezone"]=>
+  string(3) "CET"
 }
-string(22) "2020-10-01T00:00+00:00"
-object(ion\Timestamp)#%d (2) {
+string(22) "2020-10-01T00:00+02:00"
+object(ion\Timestamp)#%d (5) {
   ["precision"]=>
   int(7)
   ["format"]=>
   string(7) "Y-m-d\T"
+  ["date"]=>
+  string(26) "2000-10-01 00:00:00.000000"
+  ["timezone_type"]=>
+  int(3)
+  ["timezone"]=>
+  string(3) "CET"
 }
 string(11) "2000-10-01T"
 DONE