PHP DateTime :: createFromFormat和多语言

时间:2016-04-08 11:12:57

标签: php wordpress datetime internationalization

我在使用“2016年4月15日”等文字的日期使用DateTime::createFromFormat()

只要我使用英国文化,它就能完美运作。

  

2016年4月15日 - >确定

我的代码设置为WordPress插件。请理解我无法控制给出日期(作为文本)和WordPress设置的组件。如果用户使用其他语言设置WordPress安装,则日期将从“2016年4月15日”更改为(如果是法语)“Avril 15,2016”。

看起来DateTime::createFromFormat()不支持除英语以外的其他语言,因此“2016年4月15日”将最终得到:

  

“致命错误:在布尔”

上调用成员函数format()

有人知道我们如何用多种语言处理月份日期作为文本?在php中使用DateTime::createFromFormat()或其他方法?

由于

1 个答案:

答案 0 :(得分:2)

有两种方法可以做到这一点,但两者都取决于输入的准确程度......

  1. 维护一系列月份名称翻译
  2. 这是简单/天真和最明显的方式,我认为这样做的方式不需要解释。

    但是,根据WordPress(和/或您使用的插件)的工作原理,它也可能是您唯一的选择。

    1. IntlDateFormatter
    2. 这是纯粹的编程方式,因此被认为是“正确”的方式,但不幸的是,这个类是PECL扩展的一部分 - intl - 并且没有与PHP捆绑在一起。

      它还要求您在解析日期之前了解所使用的语言,但这应该不是问题,因为这就是所有本地化解决方案应该首先起作用的方式,因此我假设您可以使用此信息。 WordPress的。
      pickdate.js也seems to work with standard locales by default

      话虽如此,这是它的工作原理:

      // See http://userguide.icu-project.org/formatparse/datetime
      $inputFormat = 'MMMM dd, yyyy';
      $inputDate   = 'Avril 15, 2016';
      $locale      = 'fr_FR';
      
      // Here comes the magic ...
      $dateFormatter = new IntlDateFormatter(
          $locale,
          IntlDateFormatter::LONG, // Not really important, may even be NONE
          IntlDateFormatter::NONE, // Time ... we're not using it
          NULL, // Will use date_default_timezone_get()
          NULL, // Calendar; we don't need it
          $inputFormat
      );
      
      // Will return bool(false) on failure, use getErrorMessage() for debugging
      $unixTimestamp = $dateFormatter->parse($inputDate);
      

      值得注意的是IntlDateFormatter主要用于创建本地化的输出(这是正确的 - 您不应该首先解析翻译的月份名称,或者在所有这一切;数字FTW),所以我们确实在这里写了很多无关紧要的东西。 对于您的使用案例,只有$locale$inputFormat参数很重要。

      还有一点需要注意 - 我们需要一个时区
      您可以通过(最好)$dateFormatter->getTimeZone()或在这种情况下date_default_timezone_get()获取它,但您确实需要时区有两个原因:

      1. 您的输入中没有时间值,因此IntlDateFormatter::parse()假定为“00:00:00”。
      2. UNIX中的时间戳总是,因此IntlDateFormatter::parse()会考虑到这一点,DateTime::createFromFormat('U', $unixTimestamp)会将对象的时区设置为UTC!
      3. 如果你在另一个时区,更具体地说是在世界东边的一个时区,这将会发生:

        $dateTime = DateTime::createFromFormat('U', $unixTimestamp);
        var_dump($dateTime->format('Y-m-d')); // string(10) "2016-04-14" !!!
        
        $dateTime->setTimeZone(new DateTimeZone($timezone));
        var_dump($dateTime->format('Y-m-d')); // string(10) "2016-04-15"
        

        可能告诉IntlDateFormatter您首先是UTC,但这在技术上是作弊(眨眼)并取决于您使用$dateTime的内容之后,它可能会引起副作用。