nedarta/yii2-datetime-behavior 问题修复 & 功能扩展

解决BUG、新增功能、兼容多环境部署,快速响应你的开发需求

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

nedarta/yii2-datetime-behavior

Composer 安装命令:

composer require nedarta/yii2-datetime-behavior

包简介

Timezone-aware datetime behavior for Yii2

README 文档

README

Timezone-aware DateTime behavior for Yii2 ActiveRecord models.

This extension provides a clean, future-proof way to automatically convert datetime values between database format and user-facing format, while keeping your database consistent (UTC / UNIX) and your UI localized.

Features

  • Automatic timezone conversion (UI ↔ DB)
  • Works on afterFind and beforeSave
  • Supports UNIX timestamps and DATETIME columns
  • Timezone offset inclusion for robust Formatter integration
  • Includes toTimestamp() helper for UTC-normalized timestamps
  • Multiple attributes per model
  • Ready for multi-timezone users
  • Easy to test, no UI or widget coupling
  • Compatible with Yii2 Formatter (asDateTime())

Installation

composer require nedarta/yii2-datetime-behavior

Basic Usage

Model configuration

use nedarta\behaviors\DateTimeBehavior;

class Post extends \yii\db\ActiveRecord
{
    public function behaviors(): array
    {
        return [
            [
                'class' => DateTimeBehavior::class,
                'attributes' => ['created_at', 'scheduled_at'],
                'inputFormat' => 'Y-m-d H:i',
                // Optional:
                // 'dbFormat' => 'unix',          // default: 'unix'
                // 'serverTimeZone' => 'UTC',     // default: 'UTC'
                // 'displayTimeZone' => null,     // default: null (falls back to Yii::$app->timeZone)
            ],
        ];
    }
}

What Happens Automatically

Step Value Description
Database value 1704031200 UTC Unix Timestamp
After find() 2023-12-31 16:00 +02:00 Local time with offset
User edits 2024-01-01 10:00 UI Form input (no offset)
Before save() 1704103200 Converted back to UTC

The database always stays in UTC / UNIX format.
The model attribute always contains a user-facing value.

Configuration Options

Option Type Default Description
attributes array [] Attributes to convert
dbFormat string unix unix, datetime, date, time, or custom PHP format string (e.g. Y-m-d)
inputFormat string Y-m-d H:i User / UI format
serverTimeZone string UTC Database timezone (usually UTC)
displayTimeZone `string null` null

How It Works

DB → UI (afterFind)

  1. Reads value from database
  2. Interprets it using serverTimeZone
  3. Converts to displayTimeZone
  4. Formats as inputFormat + P (timezone offset)

UI → DB (beforeSave)

  1. Parses user input using inputFormat (tries both with and without offset)
  2. Interprets it in displayTimeZone (unless offset provided)
  3. Converts to serverTimeZone
  4. Stores as UNIX timestamp or DATETIME string

Automatic Timezone Fallback

If you don't explicitly set displayTimeZone in the behavior, it will automatically pick up your application's timezone from Yii::$app->formatter->timeZone or Yii::$app->timeZone. This ensures consistency across your application without extra configuration.

// In common/config/main.php
'timeZone' => 'Asia/Tokyo',

// In your Model - no displayTimeZone needed!
[
    'class' => DateTimeBehavior::class,
    'attributes' => ['created_at'],
],

Helper Methods

toTimestamp($attribute)

Returns a UTC-normalized UNIX timestamp for a given attribute, regardless of whether the attribute currently holds a raw database value or a localized UI string.

$timestamp = $model->getBehavior('dt')->toTimestamp('created_at');

Querying

When querying the database (e.g., filtering for "today's events"), you must compare against UTC time. You can use the toDbValue() helper to correctly format your filter values.

Option 1: Static Helper (Simplest)

You don't need a model instance, just the class name:

use nedarta\behaviors\DateTimeBehavior;

$now = DateTimeBehavior::now(Event::class);
$query->andWhere(['>=', 'datetime', $now]);

Option 2: Direct Model Call

If you have a model instance, you can call the behavior methods directly on it:

$model = new Event();
$query->andWhere(['>=', 'datetime', $model->toDbValue('now')]);

Alternatively, if you are using unix timestamps, you can simply use the PHP time() function:

// Only for dbFormat => 'unix'
$query->andWhere(['>=', 'datetime', time()]);

Batch Operations

Since ActiveRecord::updateAll() and insertAll() do not trigger model behaviors, you can use the normalize() method to convert your data array before passing it to the database:

$model = new Post();
$dt = $model->getBehavior('dt');

// Normalize UI-formatted data for batch update
$data = $dt->normalize([
    'status' => Post::STATUS_PUBLISHED,
    'published_at' => '2024-01-01 12:00', // Will be converted to UTC/Unix
]);

Post::updateAll($data, ['author_id' => 1]);

What This Extension Does NOT Do

  • Render form inputs or widgets
  • Depend on Tempus Dominus or any UI library
  • Store business logic
  • Guess or auto-detect timezones

This extension operates strictly at the model layer.

Recommended Architecture

[ UI / Widget ]
       ↓
[ ActiveRecord Attribute ]
       ↓
[ DateTimeBehavior ]
       ↓
[ Database (UTC / UNIX) ]

Requirements

  • PHP 8.1+
  • Yii2 ^2.0

Testing

Run the test suite via Composer:

composer test

License

MIT

Roadmap

  • PHPUnit test suite
  • Support for additional database formats (date, time, custom)
  • Support for batch operations (e.g. updateAll())
  • Query helper toDbValue() for correct filtering
  • Read-only / write-only modes
  • Integration with popular date/time widgets

统计信息

  • 总下载量: 17
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 1
  • 点击次数: 0
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

  • Stars: 1
  • Watchers: 0
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2026-01-01

承接程序开发

PHP开发

VUE

Vue开发

前端开发

小程序开发

公众号开发

系统定制

数据库设计

云部署

网站建设

安全加固