Date 对细枝模板中的本地化日期使用4位数的年份

Date 对细枝模板中的本地化日期使用4位数的年份,date,symfony,twig,locale,Date,Symfony,Twig,Locale,我在Symfony 2.4项目中使用Twig Intl扩展来本地化日期: {post.published_在| localizeddate('short','none',locale)} 这很有效,但不会以yyy格式显示全年,而是使用yy格式 这样,2013年12月31日将根据区域设置显示为2013年12月31日或2013年12月31日,而不是2013年12月31日或2013年12月31日 有没有一种方法可以使用带有本地化日期的4位数年份?试试以下方法: {{ post.published_

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


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

这很有效,但不会以
yyy
格式显示全年,而是使用
yy
格式

这样,2013年12月31日将根据区域设置显示为2013年12月31日或2013年12月31日,而不是2013年12月31日或2013年12月31日

有没有一种方法可以使用带有本地化日期的4位数年份?

试试以下方法:

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

您可以使用自己的格式与特殊的pkaceholder一起执行此操作,例如
Y
meanYYYY日期格式,检查有关筛选器的文档。

我终于做到了

我通过以下方式扩展了默认的Twig Intl扩展:

<?php
namespace Acme\DemoBundle\Twig;

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());
    }
}
我将默认模式更改为将“yy”替换为“y”(这是4位数年份的格式,如下所述:)


通过这种方式,它适用于所有格式和所有地区。

对Michaël Perrin的答案进行了更改,可以通过在日期格式中添加“u year”来使用新旧方法

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

<?php
namespace Myproject\MyBundle\Twig\Extension;

/**
 * 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);
    }
}

您的扩展intl扩展的解决方案很好,但是您可以更轻松地完成它。如果深入查看文档,您将看到扩展名有一个
格式
参数。因此,您可以:

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

格式遵循ICU格式指南。对于4位数年份,您可以使用
y
yyyy
。完整文档:


希望能有所帮助。

问题是它将不再使用区域设置。日期将始终显示为2013年12月31日,而不是2013年12月31日。例如,对于en_US地区…我理解,我认为您需要为您的案例手动实现本地化我认为您是对的。。。那真是太糟糕了!不管怎样,谢谢你的帮助。我做了一个改变,这样你就可以使用旧的和新的方式,只需加上年份:在我的机器配置中,我有四位数字,但在其他配置中,我只有两位数字。你不知道他们之间有什么区别。但我认为有一种方法可以做到这一点,而不需要延长树枝
<?php
namespace Myproject\MyBundle\Twig\Extension;

/**
 * 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);
    }
}
services:
    myproject.twig.extension.intl:
        class: Myproject\MyBundle\Twig\Extension\IntlExtension
        tags:
            - { name: twig.extension }