5

对不起,如果这是一个骗局 - 很多类似的问题,但显然如果我能找到一个确切的答案,我就不会问了:)

请注意,我来自 .Net,并且是 PHP 新手,因此可能存在 noob-scale 错误。

我希望能够输出例如 new DateTime('2014-01-01 13:15:00') 为:'2014 年 1 月 1 日星期三下午 1:15'(可能 - 非本地化)或 'Mercredi 1er Janvier 2014 à 13h15'(不可能?)。

基本上,似乎没有与 PHP 的“S”日期格式说明符等效的 ISO 格式,也没有用于 strftime 的 ISO 格式?

IntlDateFormatter::FULL 接近了 - 但 'Wednesday, 1 January' 或 'mercredi 1 janvier' 不是很好的英语(或法语) - 但它似乎是我能得到的最接近的?如果必须的话,我可以不用“on”、“the”和“at”,但序数后缀会很好。(“一月的星期三”——那是什么,一首诗的开头?)

我确实在 PHP.net 上的 strftime 部分评论中看到了一个示例,解决了这个问题(这似乎表明这是一个问题) - 但是它似乎只添加了英文后缀,这似乎没有多大用处?我想要一个简单的方法,它采用 UTC 日期时间、语言环境和时区并输出本地化字符串 - 最好采用英语中可能的“正确”人类可读格式(如上)。我想在不为世界上每种语言编写格式字符串的情况下实现这一目标。如果它可以在我的 Windows 开发盒和 *nix 生产盒上工作,那也很好。

<?php
$utcdate = new DateTime('2014-01-01 13:15:00', new DateTimeZone('UTC'));
echo $utcdate->format('l \t\h\e jS \o\f F Y \a\t g:ia') . "<br>";
function dumpDates($date, $locale, $tz){
    $date->setTimeZone(new DateTimeZone($tz));
    $fmt = new IntlDateFormatter( $locale, IntlDateFormatter::FULL, IntlDateFormatter::FULL,
         $tz, IntlDateFormatter::GREGORIAN  );
    echo $fmt->format($date) . "<br>";
    // doesn't work under windows?
    setLocale(LC_TIME, $locale);
    echo strftime('%A, %#d %B %Y %I:%M:%S %p', $date->getTimeStamp()) . "<br>";

}
dumpDates($utcdate, 'en_GB', 'Europe/London');
dumpDates($utcdate, 'de_DE', 'Europe/Berlin');
dumpDates($utcdate, 'fr_FR', 'Europe/Paris');
?>
4

1 回答 1

1

如您所说,如果没有为世界上每种语言编写格式字符串或找到包含此类字符串的库,则该问题的全部部分(包括完整的语法易读性)都很难做到。MomentJs似乎提供了很好的 intl 支持,但经过粗略搜索后,除了 intl 扩展之外,我还没有找到 PHP 等价物。

您可以通过使用 IntlDateFormatter 和NumberFormatter的组合来提供包括基于序数的国际化表格的阶段,首先使用 NumberFormatter 获取日期序数后缀/前缀的模式:

$numFmt = new NumberFormatter('fr_FR', NumberFormatter::ORDINAL);
$ordinalDay = $numFmt->format($date->format('j'));

然后,您可以创建一个 IntlDateFormatter,它允许您检索目标语言的完整日期格式的模式:

$dateFormat = new IntlDateFormatter('fr_FR', IntlDateFormatter::FULL, IntlDateFormatter::FULL, $tz, IntlDateFormatter::GREGORIAN);
$datePattern = $dateFormat->getPattern();

最后,您需要用转义的序数日模式替换 $datePattern 中表示日期的部分:

$datePattern = preg_replace('/d+', "'"+$ordinalDay+"'", $datePattern);
$dateFormat->setPattern($datePattern);
$outputDate = $dateFormat->format($date);   

请注意,IntlDateFormatter 使用的模式与通常的 PHP 日期格式化格式代码不同,这里是识别代码的文档。

一个警告; 在相当严格标准化的国际化格式中,序数看起来不合适。例如中文,格式为:

y年M月d日EEEE

并且在日值之前插入存在于书面中文的序数前缀对于中文读者来说可能看起来很奇怪。

于 2015-08-04T10:00:53.290 回答