Save and Display Date/Time Fields in different formats in Yii2

You are viewing revision #10 of this wiki article.
This is the latest version of this article.
You may want to see the changes made in this revision.

« previous (#9)

  1. Tip 1: Use a prebuilt extension
  2. Tip 2: Use TimeStamp Behavior for auto-saving date/time records
  3. Tip 3: Controlling global formats
  4. Tip 4: Easily convert any attribute format before saving to db

You would find having such a need 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

The yii2-datecontrol 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 INPUTS and WIDGETS.

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 other than INSERT or UPDATE

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 the following:

$model->timestamp->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');