In my DB I store all datetime fields in UTC format. Also, I have the ability to change default time zone by users. Each user can have own time zone, different from UTC.
How shall I display all model datetime fields in this case?
I have an idea. To do this action for each ActiveRecord model:
public function init()
{
parent::init();
$this->on(ActiveRecord::EVENT_AFTER_FIND, function($event) {
$this->created_date = (new \DateTime('now', new \DateTimeZone("Europe/Kiev")))->format("Y-m-d H:i:s");
});
}
But I'm not sure it's the best way for big amount of models...
if the dates are stored in UTC why not append the string UTC along the time and display it
$time = strtotime($this->created_at.' UTC');
date("Y-m-d H:i:s", $time);
Your code will look like this
public function init()
{
parent::init();
$this->on(ActiveRecord::EVENT_AFTER_FIND, function($event) {
$time = strtotime($model->create_at.' UTC');
$this->created_date = date("Y-m-d H:i:s", $time);
});
}
if I would do it I would just create a separate Helper and use it to display the date in the local format rather than EVENT_AFTER_FIND
Another alternative is to use this Extension
Search for frontend/config/main.php
Try putting in
return [
...
'components' => [
...
a FORMATTER part like
'formatter' => [
'dateFormat' => 'dd/MM/yyyy',
'datetimeFormat' => 'dd/MM/yyyy H:i:s',
'timeFormat' => 'H:i:s',
'locale' => 'it-IT',
'decimalSeparator' => ',',
'thousandSeparator' => '.',
'currencyCode' => 'EUR',
'numberFormatterSymbols' => [
NumberFormatter::CURRENCY_SYMBOL => '€',
],
'timeZone' => 'Europe/Rome',
],
Set your parameters like TimeZone, Currency, etc...
NB: I dont remember but maybe the NumberFormatter part need some other setup so delete the numberFormatterSymbols part if it give to you an error
Related
I am currently trying to format a datetime object that I access like this:
Blade:
{{ $event->start }} and {{ $event->end}}
this outputs something like this on the frontend blades:
2021-12-02 22:30:00 ($event->start) 2021-2021-12-02 23:00:00 ($event->end)
the formatting above is also how it is stored as a DATETIME object in the database.
Because I use other elements, like a fullcalendar, I dont want to change the way the database stores the dates, just formatting the dates on the frontend/controller directly.
Controller:
if ($course == 'course') {
$view = 'pages.course.current_course';
$id = '8';
}
// get the course data from the database
$events = DB::table('eventaries')
// map the current view $id to the database query
->where('category', $id)
// check if event is expired
->where('start', '>', now())
->get();
// pass through the data to the correct views
return view($view, [
"events" => $events
]);
But I need the following formatting: Sunday. 12th December 2021, 22:30 ($event->start) and 23:00 ($event->end)
I already got the formatting in the BackPack Backend right by adding 'format' => to the CrudController, like this:
CrudController:
CRUD::addColumn([
'name' => 'start',
'label' => 'Start',
'type' => 'datetime',
'format' => 'DD.MM.Y - H:mm',
]);
CRUD::addColumn([
'name' => 'end',
'label' => 'End',
'type' => 'datetime',
'format' => 'DD.MM.Y - H:mm',
]);
If you have Model defined for that particular table. you can define accessor for those two column, like
public function getStartAttribute($value)
{
return Carbon::parse($value)->toDayDateTimeString();
}
It will return output something like Mon, Nov 29, 2021 05:45 PM
Define these type of function for end column.
Refer this Carbon Document for other format and date operation
If you don't have Model you can use Carbon class in blade or controller directly
We will use createFromFormat() and format(), createFromFormat() will take two argument first give format of date and second one date and format() take one argument give formate as you want. you can see bellow examples:
Example 1:
$post->created_at->format('d-m-Y');
Example 2:
\Carbon\Carbon::createFromFormat('Y-m-d H:i:s', $date)->format('d-m-Y')
I have a factory for generating the event
public function definition()
{
return [
'event_type' => $this->faker->randomElement(['class','event']),
'event_name' => $this->faker->sentence(1,2),
'date' => $this->faker->dateTimeBetween($startDate = '+1 days', $endDate = '+5 days'),
'start_time' => $this->faker->dateTimeBetween('+0 hours', '+2 hours'),
'end_time' => $this->faker->dateTimeBetween('+3 hours', '+10 hours'),
];
}
Here I need start_time and date to have the same value generated in date
For example if date='2003-03-15 02:00:49'. I wanted the start_time to be 02:00:49 but I get some other value because it is generated randomly.
Note: date is a timestamp and start_time is in time format in database
You can re-use faker data by putting it into a variable first and get the timestamp of a DateTime object by calling its getTimestamp() method:
public function definition()
{
$date = $this->faker->dateTimeBetween($startDate = '+1 days', $endDate = '+5 days');
return [
'event_type' => $this->faker->randomElement(['class','event']),
'event_name' => $this->faker->sentence(1,2),
'date' => $date->getTimestamp(),
'start_time' => $date,
'end_time' => $this->faker->dateTimeBetween('+3 hours', '+10 hours'),
];
}
. Good day! Please tell me a technical question, in GridView Yii2, code:
['attribute' => 'request_date_create',
'value' => function ($model) {
return Yii::$app->formatter->asDateTime($model->request_date_create, 'php: d.m.Y H:i:s');
},
],
Does it display the date 3 hours later than the one taken from the database? And this code displays normal :
['attribute' => 'request_date_create',
'value' => function ($model) {
return Yii::$app->formatter->asDateTime(strtotime($model->request_date_create), 'php: d.m.Y H:i:s');
},
],
And this code generally displays nonsense :
[
'attribute' => 'request_date_create',
'format' => ['date', 'php: d.m.Y H:i:s']
],
Why? There is some nuance, but I cannot understand what
[
'attribute' => 'request_date_create',
'format' => ['datetime', 'php:d.m.Y H:i:s']
],
Try to use datetime format and remove whitespace after php:
Looks like PHP time zone is different. See docs https://www.yiiframework.com/doc/api/2.0/yii-i18n-formatter#$defaultTimeZone-detail and example https://www.yiiframework.com/wiki/684/save-and-display-datetime-fields-in-different-formats-in-yii2#tip-3-controlling-global-formats how to set formater time zone, date and time formats
I would like to ask for a better approach. I am using Yii2 with PostgreSQL, and set all timestamp fields for all table to timestamp with timezone data type.
timestamp with time zone NOT NULL DEFAULT now()
I have created setting which will be called for every response,
Yii::$app->setTimezone(MallSettings::getSetting('timezone', Yii::$app->session['mall_id']));
which will return something like Asia/Makassar or Asia/Jakarta (it depends on user's setting).
I extend the \yii\18n\Formatter, using a class named ZeedFormatter below, and make a new function to display the datetime value in user's preferred timezone.
class ZeedFormatter extends \yii\i18n\Formatter
{
/**
* Format timestamp with timezone value to user's preferred timezone.
* (extends the asDatetime() functionality)
*
* #param [type] $value [description]
* #param [type] $format [description]
* #return [type] [description]
*/
public function asLocaldatetime($value, $format = null)
{
$originalDateTime = \DateTime::createFromFormat('Y-m-d H:i:s.uO', $value);
$originalDateTime->setTimezone(new \DateTimeZone(date_default_timezone_get()));
if ($format === null)
$format = 'Y-m-d H:i:s.uO';
$localDateTime = $originalDateTime->format($format);
return $localDateTime;
}
}
The idea is that whenever I need a 'local' datetime format, I can call it like so:
Yii::$app->formatter->asLocaldatetime('2019-08-29 19:52:21.02886+07');
// will return 2019-08-29 20:52:21.02886+08 for Asia/Makassar timezone
Or, if used inside a GridView,
'position',
'created_at:localdatetime',
['class' => 'backend\widgets\ActionColumn'],
Can I get this functionality only using Yii2's feature? Or (another option) is calling created_at AT TIME ZONE 'Asia/Makassar' from the Psql query? I hope I can get an enlightment. Thank you.
My (another) approach is to keep using the asDatetime() function.
I just realized that I need to remove / comment the timezone from config file. If the value is set there, no matter how I set the timezone at other place, Yii always gets the value from the config file (common/config/main.php) if we are using the asDatetime formatter.
'components' => [
'formatter' => [
// 'class' => '\common\modules\ZeedFormatter',
'locale' => 'id-ID',
// 'timeZone' => 'Asia/Jakarta',
'defaultTimeZone' => 'Asia/Jakarta',
'dateFormat' => 'php:j M Y',
'decimalSeparator' => ',',
'thousandSeparator' => '.',
'currencyCode' => 'Rp ',
'nullDisplay' => '<em style="color:#d8d8d8">null</em>',
'numberFormatterOptions' => [
NumberFormatter::MIN_FRACTION_DIGITS => 0,
NumberFormatter::MAX_FRACTION_DIGITS => 0,
],
],
]
If we need another (or customized) format, we can still use the ZeedFormatter as above and add some desired functions. For example :
public function asMyformat($value)
{
$timestamp = strtotime($value);
$fmt = new \IntlDateFormatter('id-ID', \IntlDateFormatter::NONE, \IntlDateFormatter::LONG);
$fmt->setPattern('hh:mm z');// will return something like '09:47 WITA'
return $fmt->format($timestamp);
}
If I have function like this
protected function getAreaValues($model)
{
return
[
[
$model->getAttributeLabel('EXPDATE'),TbArea::findOne($model->KODE)->EXPDATE
],
];
}
where EXPDATE IS date data
How to format it in d-M-Y ?
I add formatter in web.php in config like this
'formatter' => [
'class' => 'yii\i18n\Formatter',
'nullDisplay' => '-',
'dateFormat' => 'd-M-Y',
'datetimeFormat' => 'd-M-Y H:i:s',
'timeFormat' => 'H:i:s',
],
But still not working
You can format date like below.
echo Yii::$app->formatter->asDate('2017-03-30', 'd-M-Y'); // 30-Mar-2017
try this.
and you can check Yii2 doc
Yii2 Formatters
I think this will work
$DateTime = DateTime::createFromFormat('Y-m-d', $yourOldDateString);
$newDateString = $DateTime->format('d/M/Y');