Skip to content

Commit bacd94e

Browse files
committed
ext/intl: IntlDateFormatter::parse adds new optional argument.
New option to update its internal calendar.
1 parent 79e4ca1 commit bacd94e

File tree

6 files changed

+49
-14
lines changed

6 files changed

+49
-14
lines changed

ext/intl/dateformat/dateformat.stub.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,10 +154,11 @@ public static function formatObject($datetime, $format = null, ?string $locale =
154154

155155
/**
156156
* @param int $offset
157+
* @param bool $updateCalendar
157158
* @tentative-return-type
158159
* @alias datefmt_parse
159160
*/
160-
public function parse(string $string, &$offset = null): int|float|false {}
161+
public function parse(string $string, &$offset = null, $updateCalendar = false): int|float|false {}
161162

162163
/**
163164
* @param int $offset

ext/intl/dateformat/dateformat_arginfo.h

Lines changed: 2 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

ext/intl/dateformat/dateformat_parse.c

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
* if set to 1 - store any error encountered in the parameter parse_error
3232
* if set to 0 - no need to store any error encountered in the parameter parse_error
3333
*/
34-
static void internal_parse_to_timestamp(IntlDateFormatter_object *dfo, char* text_to_parse, size_t text_len, int32_t *parse_pos, zval *return_value)
34+
static void internal_parse_to_timestamp(IntlDateFormatter_object *dfo, char* text_to_parse, size_t text_len, int32_t *parse_pos, bool update_calendar, zval *return_value)
3535
{
3636
double result = 0;
3737
UDate timestamp =0;
@@ -42,13 +42,22 @@ static void internal_parse_to_timestamp(IntlDateFormatter_object *dfo, char* tex
4242
intl_convert_utf8_to_utf16(&text_utf16, &text_utf16_len, text_to_parse, text_len, &INTL_DATA_ERROR_CODE(dfo));
4343
INTL_METHOD_CHECK_STATUS(dfo, "Error converting timezone to UTF-16" );
4444

45-
timestamp = udat_parse( DATE_FORMAT_OBJECT(dfo), text_utf16, text_utf16_len, parse_pos, &INTL_DATA_ERROR_CODE(dfo));
46-
if( text_utf16 ){
47-
efree(text_utf16);
45+
if (UNEXPECTED(update_calendar)) {
46+
UCalendar *parsed_calendar = (UCalendar *)udat_getCalendar(DATE_FORMAT_OBJECT(dfo));
47+
udat_parseCalendar( DATE_FORMAT_OBJECT(dfo), parsed_calendar, text_utf16, text_utf16_len, parse_pos, &INTL_DATA_ERROR_CODE(dfo));
48+
if( text_utf16 ){
49+
efree(text_utf16);
50+
}
51+
INTL_METHOD_CHECK_STATUS( dfo, "Calendar parsing failed" );
52+
timestamp = ucal_getMillis( parsed_calendar, &INTL_DATA_ERROR_CODE(dfo));
53+
} else {
54+
timestamp = udat_parse( DATE_FORMAT_OBJECT(dfo), text_utf16, text_utf16_len, parse_pos, &INTL_DATA_ERROR_CODE(dfo));
55+
if( text_utf16 ){
56+
efree(text_utf16);
57+
}
4858
}
4959

5060
INTL_METHOD_CHECK_STATUS( dfo, "Date parsing failed" );
51-
5261
/* Since return is in sec. */
5362
result = (double)timestamp / U_MILLIS_PER_SECOND;
5463
if (result > (double)LONG_MAX || result < (double)LONG_MIN) {
@@ -122,13 +131,14 @@ PHP_FUNCTION(datefmt_parse)
122131
char* text_to_parse = NULL;
123132
size_t text_len =0;
124133
zval* z_parse_pos = NULL;
125-
int32_t parse_pos = -1;
134+
int32_t parse_pos = -1;
135+
bool update_calendar = false;
126136

127137
DATE_FORMAT_METHOD_INIT_VARS;
128138

129139
/* Parse parameters. */
130-
if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "Os|z!",
131-
&object, IntlDateFormatter_ce_ptr, &text_to_parse, &text_len, &z_parse_pos ) == FAILURE ){
140+
if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "Os|z!b",
141+
&object, IntlDateFormatter_ce_ptr, &text_to_parse, &text_len, &z_parse_pos, &update_calendar ) == FAILURE ){
132142
RETURN_THROWS();
133143
}
134144

@@ -149,7 +159,7 @@ PHP_FUNCTION(datefmt_parse)
149159
RETURN_FALSE;
150160
}
151161
}
152-
internal_parse_to_timestamp( dfo, text_to_parse, text_len, z_parse_pos?&parse_pos:NULL, return_value);
162+
internal_parse_to_timestamp( dfo, text_to_parse, text_len, z_parse_pos?&parse_pos:NULL, update_calendar, return_value);
153163
if(z_parse_pos) {
154164
zval_ptr_dtor(z_parse_pos);
155165
ZVAL_LONG(z_parse_pos, parse_pos);

ext/intl/php_intl.stub.php

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -374,8 +374,11 @@ function datefmt_format(IntlDateFormatter $formatter, $datetime): string|false {
374374
*/
375375
function datefmt_format_object($datetime, $format = null, ?string $locale = null): string|false {}
376376

377-
/** @param int $offset */
378-
function datefmt_parse(IntlDateFormatter $formatter, string $string, &$offset = null): int|float|false {}
377+
/**
378+
* @param int $offset
379+
* @param bool $updateCalendar
380+
*/
381+
function datefmt_parse(IntlDateFormatter $formatter, string $string, &$offset = null, bool $updateCalendar = false): int|float|false {}
379382

380383
/**
381384
* @param int $offset

ext/intl/php_intl_arginfo.h

Lines changed: 2 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

ext/intl/tests/gh13766.phpt

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
--TEST--
2+
IntlDateFormatter::parse update its calendar
3+
--EXTENSIONS--
4+
intl
5+
--FILE--
6+
<?php
7+
$oIntlDateFormatter = new IntlDateFormatter("en_GB");
8+
$oIntlDateFormatter->setTimeZone('Europe/Berlin');
9+
$oIntlDateFormatter->setPattern('VV');
10+
11+
var_dump($oIntlDateFormatter->parse('America/Los_Angeles', $offset1));
12+
var_dump($oIntlDateFormatter->getTimeZone()->getID());
13+
var_dump($oIntlDateFormatter->parse('America/Los_Angeles', $offset2, true));
14+
var_dump($oIntlDateFormatter->getTimeZone()->getID());
15+
--EXPECTF--
16+
int(%d)
17+
string(13) "Europe/Berlin"
18+
int(%d)
19+
string(19) "America/Los_Angeles"

0 commit comments

Comments
 (0)