如果您需要 TimeHelper
功能在 View
之外使用,请使用 DateTime
类
use Cake\I18n\DateTime;
class UsersController extends AppController
{
public function initialize(): void
{
parent::initialize();
$this->loadComponent('Authentication.Authentication');
}
public function afterLogin()
{
$identity = $this->Authentication->getIdentity();
$time = new DateTime($identity->date_of_birth);
if ($time->isToday()) {
// Greet user with a happy birthday message
$this->Flash->success(__('Happy birthday to you...'));
}
}
}
CakePHP 在幕后使用 Chronos 为其 DateTime
实用程序提供支持。任何您可以使用 Chronos
和 PHP 的 DateTimeImmutable
做的事情,您都可以使用 DateTime
做。
有关 Chronos 的更多详细信息,请参阅 API 文档.
DateTime
是不可变对象,因为不可变性可以防止意外更改数据,并避免基于顺序的依赖项问题。
有几种方法可以创建 DateTime
实例
use Cake\I18n\DateTime;
// Create from a string datetime.
$time = DateTime::createFromFormat(
'Y-m-d H:i:s',
'2021-01-31 22:11:30',
'America/New_York'
);
// Create from a timestamp and set timezone
$time = DateTime::createFromTimestamp(1612149090, 'America/New_York');
// Get the current time.
$time = DateTime::now();
// Or just use 'new'
$time = new DateTime('2021-01-31 22:11:30', 'America/New_York');
$time = new DateTime('2 hours ago');
DateTime
类构造函数可以接受内部 DateTimeImmutable
PHP 类可以接受的任何参数。传递数字或数字字符串时,它将被解释为 UNIX 时间戳。
在测试用例中,您可以使用 setTestNow()
模拟 now()
// Fixate time.
$time = new DateTime('2021-01-31 22:11:30');
DateTime::setTestNow($time);
// Outputs '2021-01-31 22:11:30'
$now = DateTime::now();
echo $now->i18nFormat('yyyy-MM-dd HH:mm:ss');
// Outputs '2021-01-31 22:11:30'
$now = DateTime::parse('now');
echo $now->i18nFormat('yyyy-MM-dd HH:mm:ss');
请记住,DateTime
实例始终从 setter 返回一个新实例,而不是修改自身
$time = DateTime::now();
// Create and reassign a new instance
$newTime = $time->year(2013)
->month(10)
->day(31);
// Outputs '2013-10-31 22:11:30'
echo $newTime->i18nFormat('yyyy-MM-dd HH:mm:ss');
您还可以使用 PHP 内置 DateTime
类提供的方法
$time = $time->setDate(2013, 10, 31);
未能重新分配新的 DateTime
实例将导致使用原始的未修改实例
$time->year(2013)
->month(10)
->day(31);
// Outputs '2021-01-31 22:11:30'
echo $time->i18nFormat('yyyy-MM-dd HH:mm:ss');
您可以通过减去和添加其组件来创建另一个具有修改日期的实例
$time = DateTime::create(2021, 1, 31, 22, 11, 30);
$newTime = $time->subDays(5)
->addHours(-2)
->addMonth(1);
// Outputs '2/26/21, 8:11 PM'
echo $newTime;
// Using strtotime strings.
$newTime = $time->modify('+1 month -5 days -2 hours');
// Outputs '2/26/21, 8:11 PM'
echo $newTime;
您可以通过访问日期的属性来获取其内部组件
$time = DateTime::create(2021, 1, 31, 22, 11, 30);
echo $time->year; // 2021
echo $time->month; // 1
echo $time->day; // 31
echo $time->timezoneName; // America/New_York
此方法设置将对象转换为 JSON 时使用的默认格式
DateTime::setJsonEncodeFormat('yyyy-MM-dd HH:mm:ss'); // For any immutable DateTime
Date::setJsonEncodeFormat('yyyy-MM-dd HH:mm:ss'); // For any mutable Date
$time = DateTime::parse('2021-01-31 22:11:30');
echo json_encode($time); // Outputs '2021-01-31 22:11:30'
Date::setJsonEncodeFormat(static function($time) {
return $time->format(DATE_ATOM);
});
注意
此方法必须以静态方式调用。
注意
请注意,这不是 PHP Datetime 字符串格式!您需要使用 ICU 日期格式字符串,如以下资源中所指定:https://unicode-org.github.io/icu/userguide/format_parse/datetime/#datetime-format-syntax.
Changed in version 4.1.0: 添加了 callable
参数类型。
使用 Time
实例最常见的事情之一是打印出格式化的日期。CakePHP 使这变得轻而易举
$time = DateTime::parse('2021-01-31 22:11:30');
// Prints a localized datetime stamp. Outputs '1/31/21, 10:11 PM'
echo $time;
// Outputs '1/31/21, 10:11 PM' for the en-US locale
echo $time->i18nFormat();
// Use the full date and time format. Outputs 'Sunday, January 31, 2021 at 10:11:30 PM Eastern Standard Time'
echo $time->i18nFormat(\IntlDateFormatter::FULL);
// Use full date but short time format. Outputs 'Sunday, January 31, 2021 at 10:11 PM'
echo $time->i18nFormat([\IntlDateFormatter::FULL, \IntlDateFormatter::SHORT]);
// Outputs '2021-Jan-31 22:11:30'
echo $time->i18nFormat('yyyy-MMM-dd HH:mm:ss');
可以指定要显示的字符串的所需格式。您可以将 IntlDateFormatter 常量 作为此函数的第一个参数传递,或者传递完整的 ICU 日期格式字符串,如以下资源中所指定:https://unicode-org.github.io/icu/userguide/format_parse/datetime/#datetime-format-syntax.
您也可以使用非格里高利历格式化日期
// On ICU version 66.1
$time = DateTime::create(2021, 1, 31, 22, 11, 30);
// Outputs 'Sunday, Bahman 12, 1399 AP at 10:11:30 PM Eastern Standard Time'
echo $time->i18nFormat(\IntlDateFormatter::FULL, null, 'en-IR@calendar=persian');
// Outputs 'Sunday, January 31, 3 Reiwa at 10:11:30 PM Eastern Standard Time'
echo $time->i18nFormat(\IntlDateFormatter::FULL, null, 'en-JP@calendar=japanese');
// Outputs 'Sunday, Twelfth Month 19, 2020(geng-zi) at 10:11:30 PM Eastern Standard Time'
echo $time->i18nFormat(\IntlDateFormatter::FULL, null, 'en-CN@calendar=chinese');
// Outputs 'Sunday, Jumada II 18, 1442 AH at 10:11:30 PM Eastern Standard Time'
echo $time->i18nFormat(\IntlDateFormatter::FULL, null, 'en-SA@calendar=islamic');
支持以下日历类型
japanese
buddhist
chinese
persian
indian
islamic
hebrew
coptic
ethiopic
注意
对于常量字符串,例如 IntlDateFormatter::FULL,Intl 使用 ICU 库,该库从 CLDR(https://cldr.unicode.org/)获取其数据,CLDR 的版本可能因 PHP 安装而异,并产生不同的结果。
打印出预定义的“好”格式
$time = DateTime::parse('2021-01-31 22:11:30', new \DateTimeZone('America/New_York'));
// Outputs 'Jan 31, 2021, 10:11 PM' in en-US
echo $time->nice();
您可以更改显示日期的时区,而无需更改 DateTime
对象本身。当您将日期存储在一个时区中,但希望以用户的时区显示时,这很有用
// Outputs 'Monday, February 1, 2021 at 4:11:30 AM Central European Standard Time'
echo $time->i18nFormat(\IntlDateFormatter::FULL, 'Europe/Paris');
// Outputs 'Monday, February 1, 2021 at 12:11:30 PM Japan Standard Time'
echo $time->i18nFormat(\IntlDateFormatter::FULL, 'Asia/Tokyo');
// Timezone is unchanged. Outputs 'America/New_York'
echo $time->timezoneName;
将第一个参数保留为 null
将使用默认格式字符串
// Outputs '2/1/21, 4:11 AM'
echo $time->i18nFormat(null, 'Europe/Paris');
最后,可以使用不同的区域设置来显示日期
// Outputs 'lundi 1 février 2021 à 04:11:30 heure normale d’Europe centrale'
echo $time->i18nFormat(\IntlDateFormatter::FULL, 'Europe/Paris', 'fr-FR');
// Outputs '1 févr. 2021 à 04:11'
echo $time->nice('Europe/Paris', 'fr-FR');
使用 nice
i18nFormat
时显示日期的默认区域设置取自指令 intl.default_locale。但是,您可以在运行时修改此默认值
DateTime::setDefaultLocale('es-ES');
Date::setDefaultLocale('es-ES');
// Outputs '31 ene. 2021 22:11'
echo $time->nice();
从现在开始,日期时间将以西班牙语首选格式显示,除非在格式化方法中直接指定了不同的区域设置。
同样,可以更改用于 i18nFormat
的默认格式字符串
DateTime::setToStringFormat(\IntlDateFormatter::SHORT); // For any DateTime
Date::setToStringFormat(\IntlDateFormatter::SHORT); // For any Date
// The same method exists on Date, and DateTime
DateTime::setToStringFormat([
\IntlDateFormatter::FULL,
\IntlDateFormatter::SHORT
]);
// Outputs 'Sunday, January 31, 2021 at 10:11 PM'
echo $time;
// The same method exists on Date and DateTime
DateTime::setToStringFormat("EEEE, MMMM dd, yyyy 'at' KK:mm:ss a");
// Outputs 'Sunday, January 31, 2021 at 10:11:30 PM'
echo $time;
建议始终使用常量,而不是直接传递日期格式字符串。
注意
请注意,这不是 PHP Datetime 字符串格式!您需要使用 ICU 日期格式字符串,如以下资源中所指定:https://unicode-org.github.io/icu/userguide/format_parse/datetime/#datetime-format-syntax.
通常,打印相对于现在的时期非常有用
$time = new DateTime('Jan 31, 2021');
// On June 12, 2021, this would output '4 months, 1 week, 6 days ago'
echo $time->timeAgoInWords(
['format' => 'MMM d, YYY', 'end' => '+1 year']
);
end
选项允许您定义在哪个时间点之后,相对时间应使用 format
选项进行格式化。 accuracy
选项允许我们控制每个间隔范围应使用什么级别的细节
// Outputs '4 months ago'
echo $time->timeAgoInWords([
'accuracy' => ['month' => 'month'],
'end' => '1 year'
]);
通过将accuracy
设置为字符串,您可以指定所需的输出详细程度。
$time = new DateTime('+23 hours');
// Outputs 'in about a day'
echo $time->timeAgoInWords([
'accuracy' => 'day'
]);
创建后,您可以将DateTime
实例转换为时间戳或季度值。
$time = new DateTime('2021-01-31');
echo $time->toQuarter(); // Outputs '1'
echo $time->toUnixString(); // Outputs '1612069200'
您可以通过多种方式将DateTime
实例与当前时间进行比较。
$time = new DateTime('+3 days');
debug($time->isYesterday());
debug($time->isThisWeek());
debug($time->isThisMonth());
debug($time->isThisYear());
上述每个方法将根据DateTime
实例是否与当前时间匹配返回true
/false
。
您可以使用wasWithinLast()
和isWithinNext()
查看DateTime
实例是否落在给定范围内。
$time = new DateTime('+3 days');
// Within 2 days. Outputs 'false'
debug($time->isWithinNext('2 days'));
// Within 2 next weeks. Outputs 'true'
debug($time->isWithinNext('2 weeks'));
您还可以比较过去范围内DateTime
实例。
$time = new DateTime('-72 hours');
// Within past 2 days. Outputs 'false'
debug($time->wasWithinLast('2 days'));
// Within past 3 days. Outputs 'true'
debug($time->wasWithinLast('3 days'));
// Within past 2 weeks. Outputs 'true'
debug($time->wasWithinLast('2 weeks'));
CakePHP 中的不可变Date
类表示不受时间和时区影响的日历日期。Date
类封装了Cake\\Chronos\\ChronosDate
类。
注意
与DateTime
类不同,Date
不扩展DateTimeInterface
。因此您无法直接比较Date
实例与DateTime
实例。但您可以进行如下比较:$dateTime->toNative() > $date->toNative()
。
Time
类表示独立于日期或时区的时钟时间。类似于DateTime
和`Date
类,Time
类也是不可变的。它封装了Cake\\Chronos\\ChronosTime
类。
在创建操作日期的文本输入时,您可能希望接受和解析本地化日期时间字符串。请参阅解析本地化日期时间数据。
CakePHP 支持所有有效的 PHP 时区。有关支持的时区列表,请参阅此页面。