Skip to content

Commit 665fc2b

Browse files
LamentXU123NickSdot
andcommitted
ext/intl: Implement IntlRelativeDateTimeFormatter
Add locale-aware formatting of relative offsets, enum-based style, capitalization and unit options, and custom NumberFormatter support. Observe subsequent NumberFormatter configuration changes and cover formatting, error handling, and object lifetime in tests. RFC: https://wiki.php.net/rfc/reldateformatter Co-authored-by: NickSdot <32384907+NickSdot@users.noreply.github.com>
1 parent 8db886e commit 665fc2b

34 files changed

Lines changed: 2505 additions & 2 deletions

‎NEWS‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ PHP NEWS
1515
throwing a ValueError. (Marc Bennewitz)
1616

1717
- Intl:
18+
. Added IntlRelativeDateTimeFormatter for locale-aware relative date and time
19+
formatting, with enums for styles, capitalization contexts, and units.
20+
(Weilin Du)
1821
. Fixed Collator attribute and strength methods not rejecting an
1922
unconstructed Collator. (Ilia Alshanetsky)
2023
. Added optional $availableLocales argument to Locale::acceptFromHttp()

‎UPGRADING‎

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,18 @@ PHP 8.7 UPGRADE NOTES
3737
========================================
3838

3939
- Intl:
40+
. Added IntlRelativeDateTimeFormatter to format relative date and time offsets
41+
using locale-specific text, such as "yesterday" or "in 3 days". Its format()
42+
method uses a textual form when available and a numeric form otherwise,
43+
while formatNumeric() always uses a numeric form. combineDateAndTime()
44+
combines already formatted date and time strings according to the locale.
45+
The constructor accepts an optional NumberFormatter to customize numeric
46+
output; subsequent configuration changes to that object are reflected in
47+
formatting results. Styles, capitalization contexts, and units are selected
48+
using the IntlRelativeDateTimeFormatterStyle,
49+
IntlRelativeDateTimeFormatterCapitalization, and
50+
IntlRelativeDateTimeFormatterUnit enums, respectively.
51+
RFC: https://wiki.php.net/rfc/reldateformatter
4052
. Locale::acceptFromHttp() and locale_accept_from_http() now accept an
4153
optional $availableLocales array argument. When given, the
4254
Accept-Language header is matched against these locales instead of all
@@ -68,6 +80,13 @@ PHP 8.7 UPGRADE NOTES
6880
7. New Classes and Interfaces
6981
========================================
7082

83+
- Intl:
84+
. IntlRelativeDateTimeFormatter
85+
. enum IntlRelativeDateTimeFormatterStyle
86+
. enum IntlRelativeDateTimeFormatterCapitalization
87+
. enum IntlRelativeDateTimeFormatterUnit
88+
RFC: https://wiki.php.net/rfc/reldateformatter
89+
7190
========================================
7291
8. Removed Extensions and SAPIs
7392
========================================

‎ext/intl/CREDITS‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
Internationalization
2-
Ed Batutis, Vladimir Iordanov, Dmitry Lakhtyuk, Stanislav Malyshev, Vadim Savchuk, Kirti Velankar
2+
Ed Batutis, Vladimir Iordanov, Dmitry Lakhtyuk, Stanislav Malyshev, Vadim Savchuk, Kirti Velankar, Weilin Du

‎ext/intl/config.m4‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ if test "$PHP_INTL" != "no"; then
7474
breakiterator/codepointiterator_internal.cpp \
7575
breakiterator/codepointiterator_methods.cpp \
7676
listformatter/listformatter_class.cpp \
77+
reldateformatter/reldateformatter_class.cpp \
7778
transliterator/transliterator_class.cpp \
7879
transliterator/transliterator_methods.cpp \
7980
idn/idn.cpp \
@@ -124,6 +125,7 @@ if test "$PHP_INTL" != "no"; then
124125
$ext_builddir/idn
125126
$ext_builddir/locale
126127
$ext_builddir/listformatter
128+
$ext_builddir/reldateformatter
127129
$ext_builddir/msgformat
128130
$ext_builddir/normalizer
129131
$ext_builddir/rangeformatter

‎ext/intl/config.w32‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@ if (PHP_INTL != "no") {
4242
ADD_SOURCES(configure_module_dirname + "/listformatter", "\
4343
listformatter_class.cpp \
4444
", "intl");
45+
ADD_SOURCES(configure_module_dirname + "/reldateformatter", "\
46+
reldateformatter_class.cpp \
47+
", "intl");
4548
ADD_SOURCES(configure_module_dirname + "/locale", "\
4649
locale.cpp \
4750
locale_class.cpp \

‎ext/intl/formatter/formatter_attr.cpp‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,7 @@ U_CFUNC PHP_FUNCTION( numfmt_set_attribute )
181181

182182
INTL_METHOD_CHECK_STATUS( nfo, "Error setting attribute value" );
183183

184+
nfo->configuration_version++;
184185
RETURN_TRUE;
185186
}
186187
/* }}} */
@@ -212,6 +213,7 @@ U_CFUNC PHP_FUNCTION( numfmt_set_text_attribute )
212213
unum_setTextAttribute(FORMATTER_UNUM(nfo), static_cast<UNumberFormatTextAttribute>(attribute), svalue.getBuffer(), svalue.length(), &INTL_DATA_ERROR_CODE(nfo));
213214
INTL_METHOD_CHECK_STATUS( nfo, "Error setting text attribute" );
214215

216+
nfo->configuration_version++;
215217
RETURN_TRUE;
216218
}
217219
/* }}} */
@@ -293,6 +295,7 @@ U_CFUNC PHP_FUNCTION( numfmt_set_symbol )
293295
unum_setSymbol(FORMATTER_UNUM(nfo), symbol, svalue.getBuffer(), svalue.length(), &INTL_DATA_ERROR_CODE(nfo));
294296
INTL_METHOD_CHECK_STATUS( nfo, "Error setting symbol value" );
295297

298+
nfo->configuration_version++;
296299
RETURN_TRUE;
297300
}
298301
/* }}} */
@@ -363,6 +366,7 @@ U_CFUNC PHP_FUNCTION( numfmt_set_pattern )
363366
RETURN_FALSE;
364367
}
365368

369+
nfo->configuration_version++;
366370
RETURN_TRUE;
367371
}
368372
/* }}} */

‎ext/intl/formatter/formatter_class.cpp‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ U_CFUNC zend_object *NumberFormatter_object_create(zend_class_entry *ce)
5252

5353
intern = reinterpret_cast<NumberFormatter_object *>(zend_object_alloc(sizeof(NumberFormatter_object), ce));
5454
formatter_data_init( &intern->nf_data );
55+
intern->configuration_version = 0;
5556
zend_object_std_init( &intern->zo, ce );
5657
object_properties_init(&intern->zo, ce);
5758

@@ -68,6 +69,7 @@ U_CFUNC zend_object *NumberFormatter_object_clone(zend_object *object)
6869

6970
/* clone standard parts */
7071
zend_objects_clone_members(&new_nfo->zo, &nfo->zo);
72+
new_nfo->configuration_version = nfo->configuration_version;
7173

7274
/* clone formatter object. It may fail, the destruction code must handle this case */
7375
if (FORMATTER_OBJECT(nfo) != nullptr) {

‎ext/intl/formatter/formatter_class.h‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ extern "C" {
2929

3030
typedef struct {
3131
formatter_data nf_data;
32+
uint64_t configuration_version;
3233
zend_object zo;
3334
} NumberFormatter_object;
3435

‎ext/intl/php_intl.c‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
#include "locale/locale_class.h"
4343

4444
#include "listformatter/listformatter_class.h"
45+
#include "reldateformatter/reldateformatter_class.h"
4546
#include "rangeformatter/rangeformatter_class.h"
4647

4748
#include "dateformat/dateformat.h"
@@ -189,6 +190,9 @@ PHP_MINIT_FUNCTION( intl )
189190
/* Register 'ListFormatter' PHP class */
190191
listformatter_register_class( );
191192

193+
/* Register 'IntlRelativeDateTimeFormatter' PHP class */
194+
reldateformatter_register_class( );
195+
192196
#if U_ICU_VERSION_MAJOR_NUM >= 63
193197
/* Register 'NumberRangeFormatter' PHP class */
194198
rangeformatter_register_class( );
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
<?php
2+
3+
/**
4+
* @generate-class-entries
5+
* @generate-c-enums
6+
*/
7+
8+
enum IntlRelativeDateTimeFormatterStyle
9+
{
10+
case Long;
11+
case Short;
12+
case Narrow;
13+
}
14+
15+
enum IntlRelativeDateTimeFormatterCapitalization
16+
{
17+
case None;
18+
case MiddleOfSentence;
19+
case BeginningOfSentence;
20+
case UiListAndMenu;
21+
case Standalone;
22+
}
23+
24+
enum IntlRelativeDateTimeFormatterUnit
25+
{
26+
case Year;
27+
case Quarter;
28+
case Month;
29+
case Week;
30+
case Day;
31+
case Hour;
32+
case Minute;
33+
case Second;
34+
case Sunday;
35+
case Monday;
36+
case Tuesday;
37+
case Wednesday;
38+
case Thursday;
39+
case Friday;
40+
case Saturday;
41+
}
42+
43+
/**
44+
* @not-serializable
45+
* @strict-properties
46+
*/
47+
final class IntlRelativeDateTimeFormatter
48+
{
49+
public function __construct(
50+
?string $locale = null,
51+
IntlRelativeDateTimeFormatterStyle $style = IntlRelativeDateTimeFormatterStyle::Long,
52+
IntlRelativeDateTimeFormatterCapitalization $capitalizationContext = IntlRelativeDateTimeFormatterCapitalization::None,
53+
?NumberFormatter $numberFormatter = null,
54+
) {}
55+
56+
public function format(int|float $offset, IntlRelativeDateTimeFormatterUnit $unit): string|false {}
57+
58+
public function formatNumeric(int|float $offset, IntlRelativeDateTimeFormatterUnit $unit): string|false {}
59+
60+
public function combineDateAndTime(string $relativeDate, string $time): string|false {}
61+
62+
public function getErrorCode(): int {}
63+
64+
public function getErrorMessage(): string {}
65+
}

0 commit comments

Comments
 (0)