【问题标题】:PHP DateTime::createFromFormat and multi languagesPHP DateTime::createFromFormat 和多语言
【发布时间】:2016-04-08 11:12:57
【问题描述】:

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

只要我使用英语文化,它就可以完美地工作。

2016 年 4 月 15 日 -> 好的

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

看起来DateTime::createFromFormat() 不支持英语以外的其他语言,所以“2016 年 4 月 15 日”最终会是:

“致命错误:在布尔值上调用成员函数 format()”

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

谢谢

【问题讨论】:

  • 您能否详细说明“我无法控制给我日期的组件”?如果您描述插件,也许我们可以找到更好的解决方案。我认为实际上您可以获得有关您的日期的非本地化信息。
  • 您好,我从amsul.ca/pickadate.js 的 POST 值中获取信息,并且文化由 WP 管理员设置。
  • 如果你看一下pickadate.js docs,你可以看到它有一个formatSubmit选项:使用这个选项,你的问题就解决了。
  • 谢谢,但我无法控制组件和 CMS,我只是在界面的另一边。我只是像“钩子”/“触发器”一样从第 3 方捕获价值如何使用它。所以问题是“有人知道我们如何将月份日期作为多种语言的文本处理吗?”谢谢
  • 你必须花一些时间来描述详细你的插件和上下文(编辑问题,不在cmets中),否则它是只是浪费时间。基本上,在 php 中,您可以使用 strptimesetlocale 来解决这个问题,但在您的具体情况下,有很多未定义的变量:wordpress 语言环境(您可以检索它吗?)、本地化字符串(在 wp 中不是与 php 相同),日期格式(在 pickadate.js 中这种格式是基于 wp 配置的?它是由用户自定义的?它是出厂设置?)。这只是您的问题调用的子问题的简短列表。

标签: php wordpress datetime internationalization


【解决方案1】:

有两种方法可以做到这一点,但都取决于输入的生成方式...

  1. 维护月份名称翻译数组

这是简单/幼稚和最明显的方式,我认为不需要解释。

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

  1. IntlDateFormatter

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

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

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

// 见 http://userguide.icu-project.org/formatparse/datetime $inputFormat = 'MMMM dd, yyyy'; $inputDate = '2016 年 4 月 15 日'; $locale = 'fr_FR'; // 魔法来了... $dateFormatter = 新的 IntlDateFormatter( $语言环境, IntlDateFormatter::LONG, // 不是很重要,甚至可能是 NONE IntlDateFormatter::NONE, // Time ... 我们没有使用它 NULL, // 将使用 date_default_timezone_get() NULL, // 日历;我们不需要它 $输入格式 ); // 失败时返回 bool(false),使用 getErrorMessage() 进行调试 $unixTimestamp = $dateFormatter->parse($inputDate);

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

还有一个警告 - 我们需要一个时区
您可以通过(最好)$dateFormatter->getTimeZone() 或在本例中为 date_default_timezone_get() 获得它,但您确实需要时区,原因有两个:

  1. 您的输入中没有 时间 值,因此 IntlDateFormatter::parse() 假定为“00:00:00”。
  2. UNIX 时间戳始终采用 UTC,因此IntlDateFormatter::parse() 会考虑到这一点,DateTime::createFromFormat('U', $unixTimestamp) 会将对象的时区设置为 UTC!

如果您在另一个时区,更具体地说是在世界东部的一个时区,则会发生这种情况:

$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')); // 字符串(10)“2016-04-15”

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

【讨论】:

    猜你喜欢
    • 2017-11-01
    • 2012-04-24
    • 1970-01-01
    • 2011-07-20
    • 1970-01-01
    • 1970-01-01
    • 2013-06-09
    • 2014-08-07
    • 1970-01-01
    相关资源
    最近更新 更多