【问题标题】:Formatting DateTime object, respecting Locale::getDefault()格式化 DateTime 对象,尊重 Locale::getDefault()
【发布时间】:2012-01-05 15:23:08
【问题描述】:

我有一个 DateTime 对象,我目前正在通过它格式化

$mytime->format("D d.m.Y")

这正是我需要的格式:

2012 年 3 月 5 日星期二

唯一缺少的一点是正确的语言。我需要Tue (Tuesday) 的德语翻译,即Die (Dienstag)。

这给了我正确的语言环境设置

Locale::getDefault()

但我不知道如何告诉DateTime::format 使用它。

有没有办法做类似的事情:

$mytime->format("D d.m.Y", \Locale::getDefault());

【问题讨论】:

  • 小心: strftime("%a %e.%l.%Y", \Locale::getDefault()) 不起作用(至少在我的设置中),因为 getDefault()返回“de”而不是“de_DE”...
  • strftime的第二个参数应该是时间戳,不是locale。
  • 哦,对不起。完全清楚这是行不通的。我真正想告诉的是 setlocale(LC_TIME, \Locale::getDefault()) 不起作用(在我的 symfony2 应用程序中)

标签: php datetime-format


【解决方案1】:

您可以使用Intl 扩展名来格式化日期。它将根据所选的语言环境格式化日期/时间,或者您可以使用 IntlDateFormatter::setPattern() 覆盖它。

对于您想要的输出格式,使用自定义模式的快速示例可能如下所示。

$dt = new DateTime;

$formatter = new IntlDateFormatter('de_DE', IntlDateFormatter::SHORT, IntlDateFormatter::SHORT);
$formatter->setPattern('E d.M.yyyy');

echo $formatter->format($dt);

输出以下内容(至少在今天)。

迪。 2013 年 4 月 6 日

【讨论】:

  • 很高兴你回答了一个古老的问题,因为这个问题会在谷歌搜索结果的顶部弹出,并且过去只提供过时的信息。
  • 另外,当您(成功)回复旧问题时,您会获得“死灵法师”徽章。
  • 您可以按如下方式轻松安装扩展:yum install php-intlapachectl reload
  • 你应该知道 PHP 的 IntlDateFormatter 类使用 ISO 日期格式代码,而不是 PHP 的 date() 格式代码。 I 查找 ISO 代码的好列表位于 framework.zend.com/manual/1.12/en/…
【解决方案2】:

那是因为format 不关注语言环境。你应该改用strftime

例如:

setlocale(LC_TIME, "de_DE"); //only necessary if the locale isn't already set
$formatted_time = strftime("%a %e.%l.%Y", $mytime->getTimestamp())

【讨论】:

  • DateTime::format 上的 php 文档中指出了此行为:This method does not use locales. All output is in English.
  • strftime() 不适用于 1970 年之前的日期,Date_time::format() 不适用于语言环境...有什么可以同时适用的吗?
  • @Jay K:总是可以扩展 PHP 的原生 DateTime 类来为其添加本地化。
  • 实际上,我们发现 strftime() 确实适用于 1970 年之前的日期,如果你传递一个(负的)unix 时间戳(至少在我们的服务器上)......所以我们这样做了二:$datetime = new DateTime('1920-01-01'); setLocale(LC_TIME|LC_CTYPE, $locale_based_on_user_profile); return strftime($format, $datetime->format('U'));
  • @Jonathan 格式修饰符应该是 %m 而不是 %l 来显示月份数
【解决方案3】:

虽然setlocale() 是正确答案并且仍然有效,但现在已经过时了。

strftime 自 PHP 8.1.0 起已弃用。强烈建议不要依赖此函数。

并提到Intl 扩展工作完美,但并不总是很方便。

处理日期和时间的最简单方法之一是使用Carbon2CakePHP Chronos 或类似库。它为所有日期的操作、格式化和计算提供了一个单一的界面。如果您经常使用日期,我建议您使用 Carbon,然后执行类似的操作

$date = Carbon::now()->locale('fr_FR');
echo $date->isoFormat('dd DD.MM.YYYY');  

请注意,格式与date() 不同。完整列表见in Carbon docs,但提到D d.m.Y 可能类似于dd DD.MM.YYYY

如果您的项目接受 3rd 方库,那确实是不错的选择。另外,如果您使用的是框架,请检查一下,也许 Carbon(或其包装器)已经包含在内。

【讨论】:

    【解决方案4】:

    这就是我结合 DateTimestrftime() 的功能解决的方法。

    第一个允许我们管理具有奇怪日期格式的字符串,例如“Ymd”(从日期选择器存储在 db 中)。 第二个允许我们将日期字符串翻译成某种语言。

    例如,我们从一个值“20201129”开始,我们希望以一个可读的意大利日期结束,日期和月份的名称,也是第一个大写字母:“Domenica 29 novembre 2020”。

    // for example we start from a variable like this
    $yyyymmdd = '20201129';
    
    // set the local time to italian
    date_default_timezone_set('Europe/Rome');
    setlocale(LC_ALL, 'it_IT.utf8');
    
    // convert the variable $yyyymmdd to a real date with DateTime
    $truedate = DateTime::createFromFormat('Ymd', $yyyymmdd);
    
    // check if the result is a date (true) else do nothing
    if($truedate){
    
      // output the date using strftime
      // note the value passed using format->('U'), it is a conversion to timestamp
      echo ucfirst(strftime('%A %d %B %Y', $truedate->format('U')));
    
    }
    
    // final result: Domenica 29 novembre 2020
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-12-02
      • 2014-07-27
      • 2017-01-20
      • 1970-01-01
      • 2012-01-15
      • 2016-05-08
      • 1970-01-01
      相关资源
      最近更新 更多