codeigniter4 / CodeIgniter4

Open Source PHP Framework (originally from EllisLab)
https://codeigniter.com/
MIT License
5.4k stars 1.9k forks source link

Bug: [Model] created_at takes timezone of server but updated_at takes timezone of app #7082

Closed vitorini closed 1 year ago

vitorini commented 1 year ago

PHP Version

8.2

CodeIgniter4 Version

4.2.10

CodeIgniter4 Installation Method

Composer (using codeigniter4/appstarter)

Which operating systems have you tested for this bug?

Linux

Which server did you use?

apache

Database

MariaDB 10.4.26

What happened?

A strange error is occurring when I save any record in the database using the SAVE() method. the created_at is taking the timezone of the server and the uptaded_at is the timezone configured for the application. the time difference is 3 hours (time zones of different countries USA(server) - BRAZIL(app)). I couldn't identify the problem.

Steps to Reproduce

create any table with created_at and updated_at save any record with SAVE() method server time zone need to be different from your app configuration

Expected Output

same timezone recorded

Anything else?

No response

ddevsr commented 1 year ago

https://github.com/codeigniter4/CodeIgniter4/blob/758889a19d53d155e62b7d1edb49498e395acf2e/system/BaseModel.php#L766-L774

https://github.com/codeigniter4/CodeIgniter4/blob/758889a19d53d155e62b7d1edb49498e395acf2e/system/BaseModel.php#L1263-L1268

https://github.com/codeigniter4/CodeIgniter4/blob/758889a19d53d155e62b7d1edb49498e395acf2e/system/BaseModel.php#L1287-L1302

In this line not yet using Time class. With date() will using php.ini configuration timezone.

ddevsr commented 1 year ago

I will send PR soon

kenjis commented 1 year ago

Why are the timezones of created_at and updated_at different?

kenjis commented 1 year ago

Cannot reproduce.

$appTimezone: UTC macOS timezone: JST +0900

<?php

namespace App\Database\Migrations;

use CodeIgniter\Database\Migration;

class CreateTableNews extends Migration
{
    public function up()
    {
        $this->forge->addField([
            'id'         => ['type' => 'INT', 'constraint' => 11, 'unsigned' => true, 'auto_increment' => true],
            'title'      => ['type' => 'VARCHAR', 'constraint' => '128', 'null' => false],
            'slug'       => ['type' => 'VARCHAR', 'constraint' => '128', 'null' => false],
            'body'       => ['type' => 'TEXT', 'null' => false],
            'created_at' => ['type' => 'datetime', 'null' => true],
            'updated_at' => ['type' => 'datetime', 'null' => true],
            'deleted_at' => ['type' => 'datetime', 'null' => true],
        ]);
        $this->forge->addPrimaryKey('id');
        $this->forge->addUniqueKey('slug');
        $this->forge->createTable('news');
    }

    public function down()
    {
        $this->forge->dropTable('news');
    }
}
<?php

namespace App\Models;

use CodeIgniter\Model;

class NewsModel extends Model
{
    protected $table            = 'news';
    protected $allowedFields    = [
        'title', 'slug', 'body',
    ];

    // Dates
    protected $useTimestamps = true;
    protected $dateFormat    = 'datetime';
    protected $createdField  = 'created_at';
    protected $updatedField  = 'updated_at';
    protected $deletedField  = 'deleted_at';
}
<?php

namespace App\Controllers;

class Home extends BaseController
{
    public function index()
    {
        $model = model('NewsModel');

        $model->save([
            'title' => 'test',
            'slug'  => 'test',
            'body'  => 'test',
        ]);
    }
}

created_at: 2023-01-11 02:56:38 updated_at: 2023-01-11 02:56:38

kenjis commented 1 year ago

In this line not yet using Time class. With date() will using php.ini configuration timezone.

appTimezone is set as the default timezone: https://github.com/codeigniter4/CodeIgniter4/blob/0438a1b1f8811f6ff6d5696c0027e1acadde1066/system/CodeIgniter.php#L197

kenjis commented 1 year ago

@vitorini I cannot reproduce the issue. Can you show minimum code to reproduce?

vitorini commented 1 year ago

thank you very much for the help, but I found the problem. My database is creating all fields "created_at" with this parameter ON UPDATE CURRENT_TIMESTAMP(). And of course the database NOW() is turning the date wrong.