在Twig模板中使用4位数年份的本地化日期

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在Twig模板中使用4位数年份的本地化日期相关的知识,希望对你有一定的参考价值。

我在Symfony 2.4项目中使用Twig Intl Extension来本地化日期:

{{ post.published_at|localizeddate('short', 'none', locale) }}

这很好用,但不会以yyyy格式显示整年,而是使用yy格式。

这样,2013年12月31日将显示为2013年12月31日或12/31/2013,具体取决于区域设置,而不是2013年12月31日或2013年12月31日。

有没有办法使用4位数年份的本地化日期?

答案

我终于成功了!

我以这种方式扩展了默认的Twig Intl扩展:

<?php
namespace AcmeDemoBundleTwig;

class AcmeIntlExtension extends Twig_Extensions_Extension_Intl
{
    public function getFilters()
    {
        return array(
            new Twig_SimpleFilter('localizeddate', array($this, 'twigLocalizedDateFilter'), array('needs_environment' => true)),
        );
    }

    public function twigLocalizedDateFilter($env, $date, $dateFormat = 'medium', $timeFormat = 'medium', $locale = null, $timezone = null, $format = null)
    {
        $date = twig_date_converter($env, $date, $timezone);

        $formatValues = array(
            'none'   => IntlDateFormatter::NONE,
            'short'  => IntlDateFormatter::SHORT,
            'medium' => IntlDateFormatter::MEDIUM,
            'long'   => IntlDateFormatter::LONG,
            'full'   => IntlDateFormatter::FULL,
        );

        $formatter = IntlDateFormatter::create(
            $locale,
            $formatValues[$dateFormat],
            $formatValues[$timeFormat],
            $date->getTimezone()->getName(),
            IntlDateFormatter::GREGORIAN,
            $format
        );

        if ($format === null) {
            // Replace yy to y (but yyy should be kept yyy, and yyyy kept as yyyy)
            // This way, years are NEVER shown as "yy" (eg. 14), but always like "yyyy" (eg. 2014)
            $pattern = preg_replace(':(^|[^y])y{2,2}([^y]|$):', '$1y$2', $formatter->getPattern());

            $formatter->setPattern($pattern);
        }

        return $formatter->format($date->getTimestamp());
    }
}

它在我的Symfony的app/config.yml文件中声明:

services:
    acme.twig.extension.intl:
        class: AcmeDemoBundleTwigAcmeIntlExtension
        tags:
            - { name: twig.extension }

我更改了默认模式,将“yy”替换为“y”(这是4位数年份的格式,如下所述:http://userguide.icu-project.org/formatparse/datetime)。

这样,它适用于所有格式和所有语言环境。

另一答案

扩展intl扩展的解决方案很好,但您可以更轻松地完成。如果您仔细查看文档,您会看到扩展名有format参数。所以你可以这样做:

{{ post.published_at|localizeddate('short', 'none', locale, null, 'd/m/y HH:mm') }}

格式遵循ICU格式指南。对于4位数年份,您可以使用yor yyyy。完整文档:http://userguide.icu-project.org/formatparse/datetime

希望能帮助到你。

另一答案

改变MichaëlPerrin的答案,通过将_year添加到日期格式,能够使用新旧方式。

使用以下命令创建文件app / src / Myproject / MyBundle / Twig / Extension / IntlExtension.php:

<?php
namespace MyprojectMyBundleTwigExtension;

/**
 * Extension of Twig Intl Extension to add support fo showing 4-digit year. Add
 * '_year' to the date format for it to work, i.e. short_year instead of short.
 */
class IntlExtension extends Twig_Extensions_Extension_Intl
{

    /**
     * A new filter must be added for this extension to work. Since this extension
     * extends an existing one, the filter should be loaded after the original one.
     *
     * @return array
     */
    public function getFilters()
    {
        $filters = [];

        // Add all filters but the localizeddate created by the parent.
        foreach (parent::getFilters() as $filter) {
            if ('localizeddate' !== $filter->getName()) {
                $filters[] = $filter;
            }
        }

        // Add custom version of 'localizeddate' which adds support showing 4-digit years.
        $filters[] = new Twig_SimpleFilter('localizeddate', array($this, 'twigLocalizedDateFilter'), array('needs_environment' => true));

        return $filters;
    }

    /**
     * If the date format has _year in it, the format returned by Intl, will be
     * changed to show a 4-digit year.
     *
     * @param Twig_Environment $env
     * @param DateTime $date
     * @param string $dateFormat
     * @param string $timeFormat
     * @param string $locale
     * @param string $timezone
     * @param string $format
     * @return string
     */
    public function twigLocalizedDateFilter(Twig_Environment $env, $date, $dateFormat = 'medium', $timeFormat = 'medium', $locale = null, $timezone = null, $format = null, $calendar = 'gregorian')
    {
        $date = twig_date_converter($env, $date, $timezone);

        $formatValues = array(
            'none' => IntlDateFormatter::NONE,
            'short' => IntlDateFormatter::SHORT,
            'medium' => IntlDateFormatter::MEDIUM,
            'long' => IntlDateFormatter::LONG,
            'full' => IntlDateFormatter::FULL,
        );

        $formatter = IntlDateFormatter::create(
            $locale,
            $formatValues[$this->getDateFormat($dateFormat)],
            $formatValues[$timeFormat],
            PHP_VERSION_ID >= 50500 ? $date->getTimezone() : $date->getTimezone()->getName(),
            'gregorian' === $calendar ? IntlDateFormatter::GREGORIAN : IntlDateFormatter::TRADITIONAL,
            $format
        );

        if ($format === null && $this->showFullYear($dateFormat)) {
            // Replace yy to y (but yyy should be kept yyy, and yyyy kept as yyyy)
            // This way, years are NEVER shown as "yy" (eg. 14), but always like "yyyy" (eg. 2014)
            $pattern = preg_replace(':(^|[^y])y{2,2}([^y]|$):', '$1y$2', $formatter->getPattern());

            $formatter->setPattern($pattern);
        }

        return $formatter->format($date->getTimestamp());
    }

    /**
     * If the given date format has _year in it, true is returned, otherwise false.
     *
     * @param string $dateFormat
     * @return boolean
     */
    protected function showFullYear($dateFormat)
    {
        return (strpos($dateFormat, '_year') !== false);
    }

    /**
     * The date format will be returned without the part '_year' if it contains it.
     * @param string $dateFormat
     * @return string
     */
    protected function getDateFormat($dateFormat)
    {
        return str_replace('_year', '', $dateFormat);
    }
}

而且,当然还有app / config / config.yml中的添加

services:
    myproject.twig.extension.intl:
        class: MyprojectMyBundleTwigExtensionIntlExtension
        tags:
            - { name: twig.extension }
另一答案

试试这个:

{{ post.published_at|localizeddate('d/m/Y', 'none', locale) }}

您可以使用自己的格式使用特殊的pkaceholder,例如Y表示YYYY日期格式,检查有关localizeddate过滤器的文档。

以上是关于在Twig模板中使用4位数年份的本地化日期的主要内容,如果未能解决你的问题,请参考以下文章

处理 Y2K 日期转换的首选方法?

信用卡到期日自动填充 - 如何使用 4 位数年份?

如何用2位数年份解析字符串日期?

用德鲁伊摄取 2 位数的年份?

Twig - 格式化日期

Laravel 4 中的 Twig 模板