Chronos 提供了一个无依赖的 DateTimeImmutable
扩展,日期专用和时间专用类
Cake\Chronos\Chronos
扩展了 DateTimeImmutable
并提供许多辅助工具。
Cake\Chronos\ChronosDate
表示不受时间或时区影响的日历日期。
Cake\Chronos\ChronosTime
表示独立于日期或时区的时钟时间。
只有安全的,不可变的对象。
一个可插拔的翻译系统。库中只包含英文翻译。但是,可以使用 cakephp/i18n
来获得完整语言支持。
Chronos
类扩展了 DateTimeImmutable
并实现了 DateTimeInterface
,允许用户使用支持任一种类型的类型声明。
ChronosDate
和ChronosTime
不扩展DateTimeImmutable
并且不共享接口。但是,它们可以使用toDateTimeImmutable()
转换为DateTimeImmutable
实例。
要安装 Chronos,您应该使用 composer
。从您的应用程序的 ROOT 目录(composer.json 文件所在的目录)运行以下命令
php composer.phar require "cakephp/chronos:^3.0"
有许多方法可以获取 Chronos 或 Date 的实例。有很多工厂方法可以处理不同的参数集
use Cake\Chronos\Chronos;
$now = Chronos::now();
$today = Chronos::today();
$yesterday = Chronos::yesterday();
$tomorrow = Chronos::tomorrow();
// Parse relative expressions
$date = Chronos::parse('+2 days, +3 hours');
// Date and time integer values.
$date = Chronos::create(2015, 12, 25, 4, 32, 58);
// Date or time integer values.
$date = Chronos::createFromDate(2015, 12, 25);
$date = Chronos::createFromTime(11, 45, 10);
// Parse formatted values.
$date = Chronos::createFromFormat('m/d/Y', '06/15/2015');
Chronos 只提供不可变对象。
如果您使用过 PHP 的 DateTimeImmutable
和 DateTime
类,那么您理解可变和不可变对象之间的区别。
不可变对象每次更改时都会创建对象的副本。由于日期时间周围的修改方法并不总是很容易识别,因此数据可能会意外地修改或在开发人员不知情的情况下修改。不可变对象可以防止意外更改数据,并使代码免受基于顺序的依赖性问题。不可变性确实意味着您需要记住在使用修改器时替换变量
// This code doesn't work with immutable objects
$chronos->addDay(1);
doSomething($chronos);
return $chronos;
// This works like you'd expect
$chronos = $chronos->addDay(1);
$chronos = doSomething($chronos);
return $chronos;
通过捕获每次修改的返回值,您的代码将按预期工作。
PHP 只提供将日期和时间部分结合在一起的日期时间类。用 DateTimeImmutable
表示日历日期可能有点笨拙,因为它包含时间和时区,而这些时区不属于“日期”。Chronos 提供了 ChronosDate
,允许您表示日期。这些对象的这些对象的时间始终固定为 00:00:00
并且不受服务器时区或修改帮助程序的影响
use Cake\Chronos\ChronosDate;
$today = ChronosDate::today();
// Changes to the time/timezone are ignored.
$today->modify('+1 hours');
// Outputs '2015-12-20'
echo $today;
虽然 ChronosDate
在内部使用固定的时区,但您可以指定要用于当前时间的时区,例如 now()
或 today()
use Cake\Chronos\ChronosDate:
// Takes the current date from Asia/Tokyo time zone
$today = ChronosDate::today('Asia/Tokyo');
Chronos 对象提供了修改方法,让您以细粒度的方式修改值
// Set components of the datetime value.
$halloween = Chronos::create()
->year(2015)
->month(10)
->day(31)
->hour(20)
->minute(30);
您还可以相对地修改日期时间的各个部分
$future = Chronos::create()
->addYears(1)
->subMonths(2)
->addDays(15)
->addHours(20)
->subMinutes(2);
还可以跳到时间中的定义点
$time = Chronos::create();
$time->startOfDay();
$time->endOfDay();
$time->startOfMonth();
$time->endOfMonth();
$time->startOfYear();
$time->endOfYear();
$time->startOfWeek();
$time->endOfWeek();
或跳到一周中的特定日期
$time->next(Chronos::TUESDAY);
$time->previous(Chronos::MONDAY);
在跨越 DST 转换修改日期/时间时,您的操作可能会增加/减少一个小时,从而导致小时值加起来不正确。您可以通过先将时区更改为 UTC
,然后修改时间来避免这些问题
// Additional hour gained.
$time = new Chronos('2014-03-30 00:00:00', 'Europe/London');
debug($time->modify('+24 hours')); // 2014-03-31 01:00:00
// First switch to UTC, and modify
$time = $time->setTimezone('UTC')
->modify('+24 hours');
修改完时间后,您可以添加原始时区以获取本地化时间。
拥有 2 个 Chronos 日期/时间对象实例后,您可以通过多种方式比较它们
// Full suite of comparators exist
// equals, notEquals, greaterThan, greaterThanOrEquals, lessThan, lessThanOrEquals
$first->equals($second);
$first->greaterThanOrEquals($second);
// See if the current object is between two others.
$now->between($start, $end);
// Find which argument is closest or farthest.
$now->closest($june, $november);
$now->farthest($june, $november);
您也可以查询给定值在日历上的位置
$now->isToday();
$now->isYesterday();
$now->isFuture();
$now->isPast();
// Check the day of the week
$now->isWeekend();
// All other weekday methods exist too.
$now->isMonday();
您还可以了解一个值是否在一个相对的时间段内
$time->wasWithinLast('3 days');
$time->isWithinNext('3 hours');
除了比较日期时间之外,计算两个值之间的差异或增量也是一项常见任务
// Get a DateInterval representing the difference
$first->diff($second);
// Get difference as a count of specific units.
$first->diffInHours($second);
$first->diffInDays($second);
$first->diffInWeeks($second);
$first->diffInYears($second);
您可以生成适合在提要或时间轴中使用的可读差异
// Difference from now.
echo $date->diffForHumans();
// Difference from another point in time.
echo $date->diffForHumans($other); // 1 hour ago;
Chronos 提供了许多方法来显示或输出日期时间对象
// Uses the format controlled by setToStringFormat()
echo $date;
// Different standard formats
echo $time->toAtomString(); // 1975-12-25T14:15:16-05:00
echo $time->toCookieString(); // Thursday, 25-Dec-1975 14:15:16 EST
echo $time->toIso8601String(); // 1975-12-25T14:15:16-05:00
echo $time->toRfc822String(); // Thu, 25 Dec 75 14:15:16 -0500
echo $time->toRfc850String(); // Thursday, 25-Dec-75 14:15:16 EST
echo $time->toRfc1036String(); // Thu, 25 Dec 75 14:15:16 -0500
echo $time->toRfc1123String(); // Thu, 25 Dec 1975 14:15:16 -0500
echo $time->toRfc2822String(); // Thu, 25 Dec 1975 14:15:16 -0500
echo $time->toRfc3339String(); // 1975-12-25T14:15:16-05:00
echo $time->toRssString(); // Thu, 25 Dec 1975 14:15:16 -0500
echo $time->toW3cString(); // 1975-12-25T14:15:16-05:00
// Get the quarter/week
echo $time->toQuarter(); // 4
echo $time->toWeek(); // 52
// Generic formatting
echo $time->toTimeString(); // 14:15:16
echo $time->toDateString(); // 1975-12-25
echo $time->toDateTimeString(); // 1975-12-25 14:15:16
echo $time->toFormattedDateString(); // Dec 25, 1975
echo $time->toDayDateTimeString(); // Thu, Dec 25, 1975 2:15 PM
获取日期对象的各个部分可以通过直接访问属性来完成
$time = new Chronos('2015-12-31 23:59:58.123');
$time->year; // 2015
$time->month; // 12
$time->day; // 31
$time->hour // 23
$time->minute // 59
$time->second // 58
$time->micro // 123
其他可以访问的属性是
时区
时区名称
星期几
月份中的第几天
一年中的第几天
一个月的天数
时间戳
季度
半年
编写单元测试时,固定当前时间很有帮助。Chronos 允许您为每个类固定当前时间。作为测试套件引导过程的一部分,您可以包含以下内容
Chronos::setTestNow(Chronos::now());
ChronosDate::setTestNow(ChronosDate::parse(Chronos::now()));
这将把所有对象的当前时间固定为测试套件开始时的点。
例如,如果您将 Chronos
固定到过去的某个时间点,则使用 now
或相对时间字符串创建的任何新的 Chronos
实例,都将相对于固定时间返回
Chronos::setTestNow(new Chronos('1975-12-25 00:00:00'));
$time = new Chronos(); // 1975-12-25 00:00:00
$time = new Chronos('1 hour ago'); // 1975-12-24 23:00:00
要重置固定,只需再次调用 setTestNow()
,不带参数或使用 null
作为参数。