关于 bitrix-datetime
面向 PHP 开发者的 Bitrix 日期时间参考技能,涵盖解析、格式化、运算、时区与 ORM 用法,并说明文化格式掩码和用户时区转换中的注意事项。
主要功能
- 01Date 与 DateTime 类型说明
- 02解析与严格输入校验
- 03文化格式掩码转换
- 04日期运算与差值计算
- 05时区及用户时间处理
- 06ORM 日期筛选
适用场景
- 01校验用户输入的日期
- 02按站点文化格式化日期
- 03计算日期间隔与偏移
- 04按日期筛选 ORM 记录
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ bxmaximum/ bitrix-framework-skills --skill bitrix-datetime安装后在 Claude Code 中输入/bitrix-datetime确认已加载。
详细介绍
日期和时间
基线:main 23.0+ · 已验证:main 26.800.0
Bitrix\Main\Type\Date— 仅日期(时间为00:00:00)。不是\DateTime子类:它封装了一个\DateTime对象,因此没有modify()、sub()、setTimestamp()方法。Bitrix\Main\Type\DateTime extends Date— 增加时间、时区和用户时间转换功能。
可用方法:format()、add()、setDate()、getTimestamp()、getDiff()、toString();DateTime 还增加了 setTime()、setTimeZone()、setDefaultTimeZone()、toUserTime()、disableUserTime()。
use Bitrix\Main\Type\Date;
use Bitrix\Main\Type\DateTime;
$d = new Date('25.11.2025', 'd.m.Y'); // 2nd arg is a PHP format
$dt = new DateTime('2025-11-25 14:30:00', 'Y-m-d H:i:s', new \DateTimeZone('UTC'));
$now = new DateTime();
$fromSite = new DateTime($request->get('DATE')); // no format = site culture format; bad input throws ObjectException
解析用户输入
$dt = DateTime::tryParse($input, 'd.m.Y H:i'); // null on error
$isValid = $dt !== null && $dt->format('d.m.Y H:i') === $input; // strict
Date::isCorrect('31.02.2025', 'd.m.Y') 返回 true:解析器会将日期滚动为 03.03.2025。请使用上面的严格往返校验或 checkdate()。
其他来源:DateTime::createFromTimestamp($ts)、DateTime::createFromPhp(\DateTime $php)(\DateTimeImmutable 需要先调用 \DateTime::createFromImmutable())、Date::createFromText('tomorrow')(返回 DateTime|null)。
文化格式和掩码
文化设置(Context::getCurrent()->getCulture())存储的是站点掩码(DD.MM.YYYY HH:MI:SS),而不是 PHP 格式。切勿将其传递给 format():
$culture = \Bitrix\Main\Context::getCurrent()->getCulture();
echo $dt->toString($culture); // culture format, user TZ
echo $dt->format(DateTime::getFormat($culture)); // culture format, no TZ shift
echo $d->format(Date::convertFormatToPhp($culture->getDateFormat()));
Date::convertFormatToPhp():
| 掩码 | PHP | 说明 |
|---|---|---|
YYYY、MMMM、MM、DD | Y、F、m、d | |
MI、SS | i、s | |
HH / H | H / h | 单独的 H(没有 HH)表示 12 小时制 |
GG / G | G / g | 规则相同,不补前导零 |
TT / T | A / a | AM/PM |
日期运算
add() 会修改对象并返回该对象。它接受 ISO 间隔(P10D、-P1M、PT30M)和相对文本(+2 weeks、-3 days):
$tomorrow = (clone $now)->add('P1D');
$dayStart = (clone $now)->setTime(0, 0);
$monday = (clone $dayStart)->add('-' . ((int)$now->format('N') - 1) . ' days');
$days = $d1->getDiff($d2)->days; // \DateInterval from $d1 to $d2
时区
值以服务器时间保存;在主模块中启用时区后,用户会看到自己所在时区的时间。
| 调用 | 结果 |
|---|---|
(string)$dt、$dt->toString() | 文化格式的用户时区时间(如果已启用,且对象上未禁用) |
$dt->format(...) | 对象自身时区的时间(除非设置了时区,例如上面的 UTC 示例,否则为服务器时区),不会转换为用户时区 |
$dt->disableUserTime() | toString() 保持服务器时间:用于日志、电子邮件以及面向服务器时区用户的文本 |
DateTime::createFromUserTime($str) | 将用户时区的字符串解析为服务器时间 |
$dt->toUserTime() | 直接转换对象本身;请在克隆对象上调用,切勿保存转换后的对象 |
旧版写入器(CAgent::AddAgent、$DB->Add()/PrepareUpdate())会通过 CDatabase::CharToDateFunction() 处理日期字符串,并减去用户时差。请传递用户时间字符串——使用普通的 toString(),而不是 disableUserTime():
\CAgent::AddAgent(
MyAgent::class . '::run();',
'vendor.module',
'N',
60,
'',
'Y',
(new DateTime())->add('+5 minutes')->toString(), // user time; the kernel shifts it back
);
ORM
DateField 返回 Date,DatetimeField 返回 DateTime;筛选时请使用对象,而不是字符串:
PostTable::query()->setSelect(['ID'])->where('CREATED_AT', '>', (new DateTime())->add('-P7D'))->fetchAll();
在 SQL 层,DateTime 会以服务器时区写入(bitrix-database)。需要使用 \DateTimeInterface 的第三方代码可调用:\DateTime::createFromFormat('U', (string)$dt->getTimestamp())。