首先:我知道我可以为每个语言环境手动创建一堆具有相应模式的配置文件;实际上我尝试找到仅使用 IntlDateFormatter 的解决方法。
我会尝试用例子来解释。
<?php
$tz = new DateTimeZone('Europe/Moscow');
$now = time();
foreach (['en_US', 'ja_JA', 'ru_RU'] as $locale) {
printf("%s:\n", $locale);
foreach ([IntlDateFormatter::MEDIUM, IntlDateFormatter::LONG] as $datetype) {
$formatter = new IntlDateFormatter($locale, $datetype, IntlDateFormatter::NONE);
printf("- %s\n", $formatter->format($now));
}
}
这会产生
en_US:
- Feb 1, 2016
- February 1, 2016
ja_JA:
- 2016/02/01
- 2016年2月1日
ru_RU:
- 1 февр. 2016 г.
- 1 февраля 2016 г.
我需要
en_US:
- Feb 1
- February 1
ja_JA:
- 02/01
- 2月1日
ru_RU:
- 1 февр.
- 1 февраля
第一个想法是提取给定区域设置的模式并删除任何“y”和“Y”字母。但正如您所看到的,不仅仅是 4 位数的年份:所有逗号、斜杠、标签(如“г.”和“年”)。
PS:
实际上,我想要的理想
IntlDateFormatter
实现是一种智能模式,其中所有组件都就位,但我可以配置每个组件使用的模式。例如: 'd MMMM y г.'
格式化程序具有 ru_RU
模式,而不是 'dmy'
模式,而对于 d
组件,它具有 d
模式、m
- MMMM
和 y
- y г.
。所以我可以说 y
组件是一个 '' (空字符串),瞧。
此外,如果您知道任何图书馆已经这样做了,请告诉我。
所以,目前这是不可能的。我发现
intl
PHP 扩展只是缺少 DateTimePatternGenerator
(http://userguide.icu-project.org/formatparse/datetime),这正是我所需要的。
DateTimePatternGenerator 类提供了一种将对一组日期/时间字段及其宽度的请求映射到适合区域设置的格式模式的方法。该请求采用“骨架”的形式,其中仅包含使用所需宽度表示的所需字段的模式字母。在骨架中,除了模式字母之外的任何内容都会被忽略,字段顺序无关紧要,并且可以使用两个特殊的附加模式字母:“j”请求区域设置的首选小时周期类型(它被映射到一个‘H’、‘h’、‘k’或‘K’); 'J' 类似,但不要求 AM/PM 标记,即使区域设置的首选小时周期类型是 'h' 或 'K'。
例如,“MMMMdjmm”的骨架可能会针对不同区域设置产生以下格式模式:
语言环境 |骨架“MMMMdjmm”的格式模式 |例子 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~ en_US "MMMM d 'at' h:mm a" 4 月 2 日下午 5:00 es_ES "d 'de' MMMM, H:mm" 4 月 2 日,17:00 ja_JP "月日 H:mm" 4月2日 17:00
此外,我发现 HHVM 已经实现了它 - https://github.com/facebook/hhvm/commit/bc84daf7816e4cd268da59d535dcadfc6cf01085。我希望有一天它能被移植到 PHP。
UPD:我已经就这个问题写了一篇大文章 - https://blog.ksimka.com/a-long-journey-to-formatting-a-date-without-a-year-internationally-with -php/
这有点难看,但如果您愿意为有限数量的语言环境定义模式并为其他语言环境设置合理的默认值,我们可以做这样的事情。
$formatter = match ($lang) {
'en' => new \IntlDateFormatter($lang, pattern: "MMMM d 'at' h:mm a"),
'es' => new \IntlDateFormatter($lang, pattern: "d 'de' MMMM, H:mm"),
'ja' => new \IntlDateFormatter($lang, pattern: "M月d日 H:mm"),
default => new \IntlDateFormatter($lang, \IntlDateFormatter::LONG, \IntlDateFormatter::NONE),
};
$date = $formatter->format($datetime);
自 PHP 8.0 起,IntlDatePatternGenerator 可用(官方 Unicode 文档),它允许您定义基本格式模式并自动将其转换为“最佳”本地化版本。
使用它,解决方案是:
$now = new \DateTime('2016-02-01');
foreach (['en_US', 'ja_JA', 'ru_RU'] as $locale) {
printf("%s:\n", $locale);
$patternGenerator = new \IntlDatePatternGenerator($locale);
foreach (['MMMd', 'MMMMd'] as $datetype) {
$pattern = $patternGenerator->getBestPattern($datetype);
printf("- %s\n",
\IntlDateFormatter::formatObject(
$now,
$pattern,
$locale
)
);
}
}
返回:
en_US:
- Feb 1
- February 1
ja_JA:
- 2月1日
- 2月1日
ru_RU:
- 1 февр.
- 1 февраля
不幸的是,它没有返回
02/01
作为日语简短版本。当使用正常格式时,这可以通过 IntlDateFormatter::MEDIUM
神奇地完成,但无法使用 IntlDatePatternGenerator::getBestPattern()
完成。不过,如果 DateTimePatternGenerator::replaceFieldTypes() 也被添加到 PHP 中,也许有一天可以实现这一目标。
但无论如何,它非常,所以我希望它可以帮助其他人。