PHP日期格式,带有可识别intl的日期后缀


PHP date format with intl-aware day suffix?

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

注意,我来自.Net,是一个PHP新手,所以可能存在noob-scale错误。

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

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

IntlDateFormatter::FULL很接近-但"1月1日星期三"或"1月31日mercredi"不是很好的英语(或法语)-但它似乎是我能得到的最接近的?如果必须的话,我可以不用"on"、"the"answers"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');
?>

如果没有为世界上每种语言编写一个格式字符串,或者找到一个包含此类字符串的库,这个问题的全部内容(包括完整的语法易读性)将非常困难。MomentJs似乎提供了很好的intl支持,但经过粗略的搜索,除了intl扩展之外,我还找不到与之等效的PHP。

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

$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

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