-
Notifications
You must be signed in to change notification settings - Fork 7.9k
MessageFormatter
uses default timezone to format dates
#10956
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
The main problem I see is that ICU's MessageFormatter doesn't seem to support this sort of behavior: internally, the date being passed for formatting is actually just a numeric timestamp. Which means there's a big question of what to do if you try to format a message with multiple DateTimes in different timezones... I'm changing this to a feature request of having a way to specify the timezone on the MessageFormatter directly, instead of relying on PHP's default timezone with no way (that I saw) to change that. |
Okay I guess this won’t be simple to implement 😅 As a workaround I’ll pass datetimes as strings returned by |
I'd suggest to set the default timezone to |
In my case the timezone is dynamic so I cannot act on the server's. |
It is actually possible to fix this by including the timezone offset in the milliseconds. So this would already work if the default timezone is set to UTC: diff --git a/ext/intl/common/common_date.cpp b/ext/intl/common/common_date.cpp
index e4f442a8195..1cf3e7da56c 100644
--- a/ext/intl/common/common_date.cpp
+++ b/ext/intl/common/common_date.cpp
@@ -113,9 +113,13 @@ U_CFUNC zend_result intl_datetime_decompose(zend_object *obj, double *millis, Ti
if (millis) {
auto getTimestampMethod = static_cast<zend_function *>(zend_hash_str_find_ptr(&obj->ce->function_table, ZEND_STRL("gettimestamp")));
+ auto getOffsetMethod = static_cast<zend_function *>(zend_hash_str_find_ptr(&obj->ce->function_table, ZEND_STRL("getoffset")));
zval retval;
+ double timestamp;
ZEND_ASSERT(getTimestampMethod && "DateTimeInterface is sealed and thus must have this method");
+ ZEND_ASSERT(getOffsetMethod && "DateTimeInterface is sealed and thus must have this method");
+
zend_call_known_function(getTimestampMethod, obj, obj->ce, &retval, 0, nullptr, nullptr);
/* An exception has occurred */
@@ -130,7 +134,25 @@ U_CFUNC zend_result intl_datetime_decompose(zend_object *obj, double *millis, Ti
return FAILURE;
}
- *millis = U_MILLIS_PER_SECOND * (double)Z_LVAL(retval) + (datetime->time->us / 1000);
+ timestamp = (double) Z_LVAL(retval);
+
+ zend_call_known_function(getOffsetMethod, obj, obj->ce, &retval, 0, nullptr, nullptr);
+
+ /* An exception has occurred */
+ if (Z_TYPE(retval) == IS_UNDEF) {
+ return FAILURE;
+ }
+ // TODO: Remove this when DateTimeInterface::getoffset() no longer has a tentative return type
+ if (Z_TYPE(retval) != IS_LONG) {
+ spprintf(&message, 0, "%s: %s::getoffset() did not return an int", func, ZSTR_VAL(obj->ce->name));
+ intl_errors_set(err, U_INTERNAL_PROGRAM_ERROR, message, 1);
+ efree(message);
+ return FAILURE;
+ }
+
+ timestamp += (double) Z_LVAL(retval);
+
+ *millis = U_MILLIS_PER_SECOND * timestamp + (datetime->time->us / 1000);
}
if (tz) {
It's incomplete though because we need to not let the default timezone influence the output or the timezone offset will be added twice. Also needs a review of all other cases that this influences but jfc the intl code is a mess. |
Description
The following code:
Resulted in this output:
But I expected this output instead:
PHP Version
all
Operating System
No response
The text was updated successfully, but these errors were encountered: