Save and Display Date Time Fields in different formats in Yii2

You would find having a very common need to control your date inputs in most Yii Projects. Your database needs a specific format to store date fields, while you may want to display it in different formats to the users on forms and other views.

How do you manage this situation easily of controlling global formats for date to save and display across your Yii application?

Here are a few pointers:

Tip 1: Use a prebuilt extension

One of the direct and easiest ways is to use yii2-datecontrol extension by Krajee. This extension allows you to setup global formats for DATE FIELDS separately for save and view on the form. You can use this for most of the FORM based interfaces, as it allows you to use various INPUTS and WIDGETS. The extension includes out of the box support for the enhanced DatePicker, DateTimePicker, and TimePicker widgets from yii2-widgets. Refer a complete demo.

Tip 2: Use TimeStamp Behavior for auto-saving date/time records

For cases, where you want to auto-save the date time field like created_on and updated_on, you can use the \yii\behaviors\TimeStampBehavior. You can configure the behavior to automatically save timestamp fields on INSERT AND UPDATE events by default – or you can add additional events.

Some additional tips when using this behavior:

Tip 2.1: Format for saving

You can choose to save a specific timestamp value using a predefined format. So let’s take you have defined your datetime field in the backend as an INTEGER and you want to save it as a integer. You can set the behavior like this:

public function behaviors()
{
    return [
        'timestamp' => [
            'class' => TimestampBehavior::className(),
            'attributes' => [
                ActiveRecord::EVENT_BEFORE_INSERT => 'creation_time',
                ActiveRecord::EVENT_BEFORE_UPDATE => 'update_time',
            ],
            'value' => function() { return date('U'); // unix timestamp },
        ],
    ];
}

Tip 2.2: Save Timestamp beyond INSERT or UPDATE events

You may want to save the timestamp for custom scenarios. Let’s say you want to update creation_time for a specific controller action. In that situation you can trigger the timestamp update for your specific attribute by using the following approach:

$model->touch('creation_time');

Tip 3: Controlling global formats

You can configure yii\i18n\formatter to control your global date formats for display for your locale. You can set something like this in your config file that you can access across

'formatter' => [
    'class' => 'yii\i18n\Formatter',
    'dateFormat' => 'php:d-M-Y',
    'datetimeFormat' => 'php:d-M-Y H:i:s',
    'timeFormat' => 'php:H:i:s',
]

Then you can display your date times anywhere using the formatter specified formats:

echo Yii::t('app', 'Today is {0, date}', $yourTimeStampAttr);

Tip 4: Easily convert any attribute format before saving to db

In case you do not wish to use the extension as mentioned in Tip # 1, you can create your own global formats for save. Just create a helper class like this:

class Setup {
    const DATE_FORMAT = 'php:Y-m-d';
    const DATETIME_FORMAT = 'php:Y-m-d H:i:s';
    const TIME_FORMAT = 'php:H:i:s';

    public static function convert($dateStr, $type='date', $format = null) {
        if ($type === 'datetime') {
              $fmt = ($format == null) ? self::DATETIME_FORMAT : $format;
        }
        elseif ($type === 'time') {
              $fmt = ($format == null) ? self::TIME_FORMAT : $format;
        }
        else {
              $fmt = ($format == null) ? self::DATE_FORMAT : $format;
        }
        return Yii::$app->formatter->asDate($dateStr, $fmt);
    }
}

Then anywhere else (like controller/model) you can access this function to convert any input date/time string for saving to database.

$model->dateAttr = Setup::convert($model->dateAttr);
$model->datetimeAttr = Setup::convert($model->datetimeAttr, 'datetime');

One thought on “Save and Display Date Time Fields in different formats in Yii2

  1. Just a little note about Tip 2.2 :
    $model->timestamp->touch(‘creation_time’);
    doesn’t work, the correct syntax should be :
    $model->touch(‘creation_time’);

Comments are closed.