Upgrading from 4.5.8 to 4.6.0

Please refer to the upgrade instructions corresponding to your installation method.

Breaking Changes

Exception Changes

Some classes have changed the exception classes that are thrown. Some exception classes have changed parent classes. See ChangeLog for details.

If you have code that catches these exceptions, change the exception classes.

Time::createFromTimestamp() Timezone Change

When you do not explicitly pass a timezone, now Time::createFromTimestamp() returns a Time instance with UTC. In v4.4.6 to prior to v4.6.0, a Time instance with the currently set default timezone was returned.

This behavior change normalizes behavior with changes in PHP 8.4 which adds a new DateTimeInterface::createFromTimestamp() method.

If you want to keep the default timezone, you need to pass the timezone as the second parameter:

use CodeIgniter\I18n\Time;

$time = Time::createFromTimestamp(1501821586, date_default_timezone_get());

Time keeps Microseconds

In previous versions, Time lost microseconds in some cases. But the bugs have been fixed.

The results of the Time comparison may differ due to these fixes:

use CodeIgniter\I18n\Time;

$time1 = new Time('2024-01-01 12:00:00.654321');
$time2 = new Time('2024-01-01 12:00:00');

$time1->equals($time2);
// Before: true
//  After: false

In a such case, you need to remove the microseconds:

use CodeIgniter\I18n\Time;

$time1 = new Time('2024-01-01 12:00:00.654321');
$time2 = new Time('2024-01-01 12:00:00');

// Removes the microseconds.
$time1 = Time::createFromFormat(
    'Y-m-d H:i:s',
    $time1->format('Y-m-d H:i:s'),
    $time1->getTimezone(),
);

$time1->equals($time2);
// Before: true
//  After: true

The following cases now keeps microseconds:

use CodeIgniter\I18n\Time;

$time = Time::createFromFormat('Y-m-d H:i:s.u', '2024-07-09 09:13:34.654321');
echo $time->format('Y-m-d H:i:s.u');
// Before: 2024-07-09 09:13:34.000000
//  After: 2024-07-09 09:13:34.654321
use CodeIgniter\I18n\Time;

$time = new Time('1 hour ago');
echo $time->format('Y-m-d H:i:s.u');
// Before: 2024-07-26 21:05:57.000000
//  After: 2024-07-26 21:05:57.857235

Note that Time with the current time has been holding microseconds since before.

use CodeIgniter\I18n\Time;

$time = Time::now();
echo $time->format('Y-m-d H:i:s.u');
// Before: 2024-07-26 21:39:32.249072
//  After: 2024-07-26 21:39:32.249072

Also, methods that returns an int still lose the microseconds.

use CodeIgniter\I18n\Time;

$time1 = new Time('2024-01-01 12:00:00');
echo $time1->getTimestamp(); // 1704110400

$time2 = new Time('2024-01-01 12:00:00.654321');
echo $time2->getTimestamp(); // 1704110400

Time::setTimestamp() Behavior Fix

In previous versions, if you call Time::setTimestamp() on a Time instance with a timezone other than the default timezone might return a Time instance with the wrong date/time.

This bug has been fixed, and it now behaves in the same way as DateTimeImmutable:

use CodeIgniter\I18n\Time;

// The Application Timezone is "UTC".

// Set $time1 timezone to "America/Chicago".
$time1 = Time::parse('2024-08-20', 'America/Chicago');

// The timestamp is "2024-08-20 00:00" in "UTC".
$stamp = strtotime('2024-08-20'); // 1724112000

// But $time2 timezone is "America/Chicago".
$time2 = $time1->setTimestamp($stamp);

echo $time2->format('Y-m-d H:i:s P');
// Before: 2024-08-20 00:00:00 -05:00
//  After: 2024-08-19 19:00:00 -05:00

Note that if you use the default timezone, the behavior is not changed:

use CodeIgniter\I18n\Time;

// The Application Timezone is "America/Chicago".

// $time1 timezone is "America/Chicago".
$time1 = Time::parse('2024-08-20');

// The timestamp is "2024-08-20 00:00" in "America/Chicago".
$stamp = strtotime('2024-08-20'); // 1724130000

// $time2 timezone is also "America/Chicago".
$time2 = $time1->setTimestamp($stamp);

echo $time2->format('Y-m-d H:i:s P');
// Before: 2024-08-20 00:00:00 -05:00
//  After: 2024-08-20 00:00:00 -05:00