I want to show the date format like: 10月09日, 周三
(which means 10/9, Wed.)
and my data is UNIX time like [message.time]: 1380813820000
so this is what I do in twig:
{{ (message.time/1000)|date("m月d日, 周w") }}
But it show me: 10月09日,周3
, Because date "w" are numbers, not Chinese text.
so can I do anything by Twig to converse the text format?
thanks
The underlying problem is, that Twig uses the DateTime::format
method, which does not support locales or (as far as I know) any other type of functionality to translate the names of the weekdays.
There are three solutions:
- Use
strftime
, which supports locales (and thus localized weekday-names).
- If you can use the
intl
extension of PHP, then you can use the Twig-extensions which comes with a intl
extension for Twig.
- You translate the weekdays by yourself.
Plus to use your preferred solution in a Twig-template, you have to extend the functionality of Twig.
Using strftime and setlocale
The following (rather large) code implements the strftime
solution:
<?php
// inspired by phpdude:
// https://github.com/fabpot/twig/issues/378#issuecomment-4698225
class DateTimeHelper_Twig extends Twig_Extension
{
public function getFilters()
{
return array(
'datetime' => new Twig_Filter_Method($this, 'datetime',
array('needs_environment' => true)),
);
}
// This uses `strftime` which makes use of the locale. The format is not
// compatible with the one of date() or DateTime::format().
public function datetime(Twig_Environment $env, $date,
$format = "%B %e, %Y %H:%M", $timezone = null)
{
$date = twig_date_converter($env, $date, $timezone);
return strftime($format, $date->getTimestamp());
}
public function getName()
{
return 'DateTimeHelper';
}
}
$loader = new Twig_Loader_String();
$twig = new Twig_Environment($loader);
// Call the setlocale before you use the `datetime` in your templates.
// This only needs to be done once per request.
// If you already have a locale configured in your environment,
// you can replace this with setlocale(LC_TIME, ""); - that way the
// locale of your environment is used.
setlocale(LC_TIME, "zh_CN.UTF-8");
// Add the extension to Twig like that:
$twig->addExtension(new DateTimeHelper_Twig());
$message = array('time' => time() * 1000);
// use the `datetime` filter with %a which gets replaced by the short weekday name of
// the current locale.
echo $twig->render('{{ (message.time/1000)|datetime("%m月%d日, 周%a") }}',
array('message' => $message)), PHP_EOL;
This code shows 10月09日, 周三
on my system (after I installed the debian package locales-all
;-) ).
Of course, locales come with a list of restrictions you probably need to be aware of:
- You have to use the correct locale (probably with UTF-8) and the locale you need has to be installed on all the systems which use your code.
- Also this solution is not fully platform-independent (on windows
setlocale
works different/gives different results). Check out the PHP-manual of setlocale
- It's easy to screw things up.
Using intl and the Twig-extensions
If you can use the intl
extensions and the "Twig-extensions"-package, you have to use localizeddate
instead of date
:
// add the extension like that
$twig->addExtension(new Twig_Extensions_Extension_Intl());
$message = array('time' => time() * 1000);
echo $twig->render('{{ (message.time/1000)|localizeddate("none", "none", "zh", null, "MM月dd日, eee") }}', array('message' => $message)), PHP_EOL;
That code also shows 10月09日, 周三
- it even adds the 周-thingie automatically.
Of course, the date-format here is also different - check out the ICU user guide.
You can try this code if the setlocale function cannot working on you system.
<?php
require_once dirname(__FILE__).'/vendor/autoload.php';
$loader = new Twig_Loader_String();
$twig = new Twig_Environment($loader);
$twig->addFilter(new Twig_SimpleFilter('format_date', function($value) {
$weekdays = array('日','一','二','三','四','五','六');
return sprintf("%s, 周%s", date("m月d日"), $weekdays[date("w")]);
}));
echo $twig->render('{{ time_at | format_date }}', array(
'time_at' => 1380813820000/1000
));
I found a quick filter replace
, here is the code snippet:
<div class="date"><span>{{ (create_time/1000)|date("m月d日,周D")|replace({'Mon':'一','Tue':'二','Wed':'三','Thu':'四','Fri':'五','Sat':'六','Sun':'日'}) }}</span></div>