Skip to content

Fix: use extension Intl instead of strftime() for date format '(locale)' - #35

Open
peterschade wants to merge 1 commit into
Skrol29:masterfrom
peterschade:fix/date-locale-intl
Open

Fix: use extension Intl instead of strftime() for date format '(locale)'#35
peterschade wants to merge 1 commit into
Skrol29:masterfrom
peterschade:fix/date-locale-intl

Conversation

@peterschade

Copy link
Copy Markdown

Problem

The date format (locale) is merged with strftime(), which is deprecated since PHP 8.1 and deleted since PHP 9.0. So the format currently raises a deprecation notice, and it is going to raise a fatal error.

$x = strftime($Frm['str_loc'], $Value); // meth_Misc_DateFormat()

This is the only way to get localized month and day names with TBS, since mmm/mmmm are merged with date() which always gives English names.

Fix

The format is converted into the ICU syntax and merged with IntlDateFormatter (extension Intl, bundled with PHP and enabled by default since PHP 8.0):

  • the locale is the one set with setlocale() for category LC_TIME, like strftime() did, so existing applications do not have to be changed,
  • locales C and POSIX are mapped to en_US_POSIX in order to keep English names when no locale is set,
  • if extension Intl is not available, then the format falls back on date() which gives English names, like a non (locale) format.

The format parser is not changed: the ICU format is deduced from the PHP format (str_us) which is already prepared by f_Misc_CheckArgFormat().

Example with setlocale(LC_TIME, 'de_DE.UTF-8'):

[a;frm=(locale)dddd", "d". "mmmm yyyy]   =>  Freitag, 30. November 2001
[a;frm=dddd", "d". "mmmm yyyy]           =>  Friday, 30. November 2001   (unchanged)

Notes

  • Item xx (ordinal suffix) has no ICU equivalent, so it is ignored in a (locale) format. This is the same behavior as before since % had no equivalent for strftime() either.
  • Abbreviated names follow the ICU conventions of the locale (nov. for fr_FR instead of nov).

Unit tests

Unit tests are added in FrmTestCase (the commented locale test is replaced):

  • the conversion into the ICU syntax is tested directly, so it runs on any system,
  • the localized merges are skipped when the system locale (fr_FR) or extension Intl is missing.

Result on PHP 8.3: 398 passes, 0 failures (392 passes before the patch).

strftime() is deprecated since PHP 8.1 and deleted since PHP 9.0, so the
date format '(locale)' raises a deprecation notice and is going to stop
working.

The format is now converted into the ICU syntax and merged with
IntlDateFormatter, using the locale set with setlocale() for category
LC_TIME, like strftime() did. Locales 'C' and 'POSIX' are mapped to
'en_US_POSIX' so that the result stays in English when no locale is set.
If extension Intl is not available, then the format falls back on date()
which gives English names.

Unit tests are added in FrmTestCase. The localized ones are skipped when
the system locale or extension Intl is missing.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant