时间和日期
CodeIgniter 提供了一个完全本地化的、不可变的日期/时间类,它基于 PHP 的 DateTimeImmutable 对象,但使用 Intl 扩展的功能在时区之间转换时间,并为不同的语言环境正确显示输出。此类是 Time
类,位于 CodeIgniter\I18n
命名空间中。
注意
由于 Time 类扩展了 DateTimeImmutable
,如果您需要此类未提供的功能,您可以在 DateTimeImmutable 类本身中找到它们。
注意
在 v4.3.0 之前,Time 类扩展了 DateTime
,一些继承的方法改变了当前对象的状态。该错误已在 v4.3.0 中修复。如果您需要旧的 Time 类以保持向后兼容性,您可以暂时使用已弃用的 TimeLegacy
类。
实例化
有几种方法可以创建新的 Time 实例。第一种方法是像其他任何类一样创建一个新实例。
使用这种方法时,您可以传入一个表示所需时间的字符串。这可以是 PHP 的 strtotime() 函数可以解析的任何字符串。
<?php
use CodeIgniter\I18n\Time;
$myTime = new Time('+3 week');
$myTime = new Time('now');
您可以在第二个和参数中分别传入表示时区和区域设置的字符串。时区可以是 PHP 的 DateTimeZone 类支持的任何时区。区域设置可以是 PHP 的 Locale 类支持的任何区域设置。如果未提供区域设置或时区,将使用应用程序默认值。
<?php
use CodeIgniter\I18n\Time;
$myTime = new Time('now', 'America/Chicago', 'en_US');
now()
Time 类有几个帮助方法来实例化该类。第一个是 now()
方法,该方法返回一个设置为当前时间的新的实例。您可以在第二个和参数中分别传入表示时区和区域设置的字符串。如果未提供区域设置或时区,将使用应用程序默认值。
<?php
use CodeIgniter\I18n\Time;
$myTime = Time::now('America/Chicago', 'en_US');
parse()
此帮助方法是默认构造函数的静态版本。它将 DateTimeImmutable 的构造函数可接受的字符串作为第一个参数,时区作为第二个参数,区域设置作为第三个参数。
<?php
use CodeIgniter\I18n\Time;
$myTime = Time::parse('next Tuesday', 'America/Chicago', 'en_US');
today()
返回一个新的实例,其日期设置为当前日期,时间设置为午夜。它接受第一个和第二个参数中的时区和区域设置字符串。
<?php
use CodeIgniter\I18n\Time;
$myTime = Time::today('America/Chicago', 'en_US');
yesterday()
返回一个新的实例,其日期设置为昨天的日期,时间设置为午夜。它接受第一个和第二个参数中的时区和区域设置字符串。
<?php
use CodeIgniter\I18n\Time;
$myTime = Time::yesterday('America/Chicago', 'en_US');
tomorrow()
返回一个新的实例,日期设置为明天的日期,时间设置为午夜。它接受第一个和第二个参数中的时区和区域设置字符串
<?php
use CodeIgniter\I18n\Time;
$myTime = Time::tomorrow('America/Chicago', 'en_US');
createFromDate()
给定**年**、**月**和**日**的单独输入,将返回一个新的实例。如果这些参数中的任何一个未提供,它将使用当前值来填充它。接受第四和第五参数中的时区和区域设置字符串
<?php
use CodeIgniter\I18n\Time;
$today = Time::createFromDate(); // Uses current year, month, and day
$anniversary = Time::createFromDate(2018); // Uses current month and day
$date = Time::createFromDate(2018, 3, 15, 'America/Chicago', 'en_US');
createFromTime()
与createFromDate()
类似,只是它只关心**小时**、**分钟**和**秒**。使用当前日期作为 Time 实例的日期部分。接受第四和第五参数中的时区和区域设置字符串
<?php
use CodeIgniter\I18n\Time;
$lunch = Time::createFromTime(11, 30); // 11:30 am today
$dinner = Time::createFromTime(18, 00, 00); // 6:00 pm today
$time = Time::createFromTime($hour, $minutes, $seconds, $timezone, $locale);
create()
结合了前两种方法,分别接受**年**、**月**、**日**、**小时**、**分钟**和**秒**作为参数。任何未提供的将使用当前日期和时间来确定。接受第四和第五参数中的时区和区域设置字符串
<?php
use CodeIgniter\I18n\Time;
$time = Time::create($year, $month, $day, $hour, $minutes, $seconds, $timezone, $locale);
createFromFormat()
这是对 DateTimeImmutable 同名方法的替代。这允许同时设置时区,并返回一个Time
实例,而不是 DateTimeImmutable
<?php
use CodeIgniter\I18n\Time;
$time = Time::createFromFormat('j-M-Y', '15-Feb-2009', 'America/Chicago');
createFromTimestamp()
此方法接受一个 UNIX 时间戳,以及可选的时区和区域设置,以创建一个新的 Time 实例
<?php
use CodeIgniter\I18n\Time;
$time = Time::createFromTimestamp(1501821586, 'America/Chicago', 'en_US');
createFromInstance()
在使用提供 DateTime 实例的其他库时,可以使用此方法将其转换为 Time 实例,并可以选择设置区域设置。时区将从传入的 DateTime 实例中自动确定
<?php
use CodeIgniter\I18n\Time;
$dt = new \DateTime('now');
$time = Time::createFromInstance($dt, 'en_US');
toDateTime()
虽然不是一个实例化器,但此方法与**instance**方法相反,允许您将 Time 实例转换为 DateTime 实例。这保留了时区设置,但丢失了区域设置,因为 DateTime 不了解区域设置
<?php
use CodeIgniter\I18n\Time;
$datetime = Time::toDateTime();
显示值
由于 Time 类继承自 DateTimeImmutable,因此您获得了它提供的所有输出方法,包括 format()
方法。但是,DateTimeImmutable 方法不提供本地化的结果。不过,Time 类确实提供了一些辅助方法来显示值的本地化版本。
toLocalizedString()
这是 DateTimeImmutable 的 format()
方法的本地化版本。但是,您不必使用您可能熟悉的那些值,而是必须使用 IntlDateFormatter 类可接受的值。可以在 此处 找到值的完整列表。
<?php
use CodeIgniter\I18n\Time;
// Locale: en
$time = Time::parse('March 9, 2016 12:00:00', 'America/Chicago');
echo $time->toLocalizedString('MMM d, yyyy'); // March 9, 2016
// Locale: fa
$time = Time::parse('March 9, 2016 12:00:00', 'America/Chicago');
echo $time->toLocalizedString('MMM d, yyyy'); // مارس ۹, ۲۰۱۶
toDateTimeString()
这是三个辅助方法中的第一个,用于与 IntlDateFormatter 一起使用,而无需记住它们的值。这将返回格式化为 (Y-m-d H:i:s
) 的字符串的本地化版本。
<?php
use CodeIgniter\I18n\Time;
// Locale: en
$time = Time::parse('March 9, 2016 12:00:00', 'America/Chicago');
echo $time->toDateTimeString(); // 2016-03-09 12:00:00
// Locale: fa
$time = Time::parse('March 9, 2016 12:00:00', 'America/Chicago');
echo $time->toDateTimeString(); // ۲۰۱۶-۰۳-۰۹ ۱۲:۰۰:۰۰
toDateString()
仅显示 Time 的日期部分的本地化版本。
<?php
use CodeIgniter\I18n\Time;
// Locale: en
$time = Time::parse('March 9, 2016 12:00:00', 'America/Chicago');
echo $time->toDateString(); // 2016-03-09
// Locale: fa
$time = Time::parse('March 9, 2016 12:00:00', 'America/Chicago');
echo $time->toDateString(); // ۲۰۱۶-۰۳-۰۹
toTimeString()
仅显示值的时分秒部分的本地化版本。
<?php
use CodeIgniter\I18n\Time;
// Locale: en
$time = Time::parse('March 9, 2016 12:00:00', 'America/Chicago');
echo $time->toTimeString(); // 12:00:00
// Locale: fa
$time = Time::parse('March 9, 2016 12:00:00', 'America/Chicago');
echo $time->toTimeString(); // ۱۲:۰۰:۰۰
humanize()
此方法返回一个字符串,该字符串以易于理解的人类可读格式显示当前日期/时间与实例之间的差异。它可以创建诸如“3 小时前”、“1 个月后”之类的字符串。
<?php
use CodeIgniter\I18n\Time;
// Assume current time is: March 10, 2017 (America/Chicago)
$time = Time::parse('March 9, 2016 12:00:00', 'America/Chicago');
echo $time->humanize(); // 1 year ago
显示的确切时间按以下方式确定。
时间差 |
结果 |
---|---|
$time > 1 年 && < 2 年 |
1 年内 / 1 年前 |
$time > 1 个月 && < 1 年 |
6 个月内 / 6 个月前 |
$time > 7 天 && < 1 个月 |
3 周内 / 3 周前 |
$time > 今天 && < 7 天 |
4 天内 / 4 天前 |
$time == 明天 / 昨天 |
明天 / 昨天 |
$time > 59 分钟 && < 1 天 |
2 小时内 / 2 小时前 |
$time > 现在 && < 1 小时 |
35 分钟内 / 35 分钟前 |
$time == 现在 |
现在 |
使用的确切语言由语言文件 Time.php 控制。
处理单个值
Time 对象提供了一些方法,允许获取和设置现有实例的单个项目,例如年、月、小时等。通过以下方法检索的所有值都将完全本地化,并尊重创建 Time 实例时使用的区域设置。
以下所有 getX()
和 setX()
方法也可以像类属性一样使用。因此,对 getYear()
等方法的任何调用也可以通过 $time->year
访问,依此类推。
获取器
存在以下基本获取器
<?php
use CodeIgniter\I18n\Time;
$time = Time::parse('August 12, 2016 4:15:23pm');
// The output may vary based on locale.
echo $time->getYear(); // '2016'
echo $time->getMonth(); // '8'
echo $time->getDay(); // '12'
echo $time->getHour(); // '16'
echo $time->getMinute(); // '15'
echo $time->getSecond(); // '23'
echo $time->year; // '2016'
echo $time->month; // '8'
echo $time->day; // '12'
echo $time->hour; // '16'
echo $time->minute; // '15'
echo $time->second; // '23'
除了这些之外,还有一些方法可以提供有关日期的更多信息
<?php
use CodeIgniter\I18n\Time;
$time = Time::parse('August 12, 2016 4:15:23pm');
// The output may vary based on locale.
echo $time->getDayOfWeek(); // '6'
echo $time->getDayOfYear(); // '225'
echo $time->getWeekOfMonth(); // '2'
echo $time->getWeekOfYear(); // '33'
echo $time->getTimestamp(); // 1471018523 - UNIX timestamp (locale independent)
echo $time->getQuarter(); // '3'
echo $time->dayOfWeek; // '6'
echo $time->dayOfYear; // '225'
echo $time->weekOfMonth; // '2'
echo $time->weekOfYear; // '33'
echo $time->timestamp; // 1471018523
echo $time->quarter; // '3'
getAge()
返回 Time 实例与当前时间之间的时间差(以年为单位)。非常适合根据生日检查某人的年龄
<?php
use CodeIgniter\I18n\Time;
$time = Time::parse('5 years ago');
echo $time->getAge(); // 5
echo $time->age; // 5
getDST()
根据 Time 实例当前是否处于夏令时返回布尔值 true/false
<?php
use CodeIgniter\I18n\Time;
echo Time::createFromDate(2012, 1, 1)->getDst(); // false
echo Time::createFromDate(2012, 9, 1)->dst; // true
getLocal()
如果 Time 实例与应用程序当前运行的时区相同,则返回布尔值 true
<?php
use CodeIgniter\I18n\Time;
echo Time::now()->getLocal(); // true
echo Time::now('Europe/London')->local; // false
getUtc()
如果 Time 实例处于 UTC 时间,则返回布尔值 true
<?php
use CodeIgniter\I18n\Time;
echo Time::now('America/Chicago')->getUtc(); // false
echo Time::now('UTC')->utc; // true
getTimezone()
返回一个新的 DateTimeZone 对象,该对象设置了 Time 实例的时区
<?php
use CodeIgniter\I18n\Time;
$tz = Time::now()->getTimezone();
$tz = Time::now()->timezone;
echo $tz->getName();
echo $tz->getOffset();
getTimezoneName()
返回 Time 实例的完整 时区字符串
<?php
use CodeIgniter\I18n\Time;
echo Time::now('America/Chicago')->getTimezoneName(); // America/Chicago
echo Time::now('Europe/London')->timezoneName; // Europe/London
设置器
存在以下基本设置器。如果设置的任何值超出范围,则会抛出 InvalidArgumentExeption
。
注意
所有设置器都将返回一个新的 Time 实例,而不会修改原始实例。
注意
如果值超出范围,所有设置器都将抛出 InvalidArgumentException。
<?php
$time = $time->setYear(2017);
$time = $time->setMonth(4); // April
$time = $time->setMonth('April');
$time = $time->setMonth('Feb'); // February
$time = $time->setDay(25);
$time = $time->setHour(14); // 2:00 pm
$time = $time->setMinute(30);
$time = $time->setSecond(54);
setTimezone()
将时间从其当前时区转换为新的时区
<?php
use CodeIgniter\I18n\Time;
$time = Time::parse('13 May 2020 10:00', 'America/Chicago');
$time2 = $time->setTimezone('Europe/London'); // Returns new instance converted to new timezone
echo $time->getTimezoneName(); // American/Chicago
echo $time2->getTimezoneName(); // Europe/London
echo $time->toDateTimeString(); // 2020-05-13 10:00:00
echo $time2->toDateTimeString(); // 2020-05-13 18:00:00
setTimestamp()
返回一个新的实例,其日期设置为新的时间戳
<?php
use CodeIgniter\I18n\Time;
$time = Time::parse('May 10, 2017', 'America/Chicago');
$time2 = $time->setTimestamp(strtotime('April 1, 2017'));
echo $time->toDateTimeString(); // 2017-05-10 00:00:00
echo $time2->toDateTimeString(); // 2017-04-01 00:00:00
修改值
以下方法允许您通过对当前 Time 添加或减去值来修改日期。这不会修改现有的 Time 实例,而是会返回一个新的实例。
<?php
$time = $time->addSeconds(23);
$time = $time->addMinutes(15);
$time = $time->addHours(12);
$time = $time->addDays(21);
$time = $time->addMonths(14);
$time = $time->addYears(5);
$time = $time->subSeconds(23);
$time = $time->subMinutes(15);
$time = $time->subHours(12);
$time = $time->subDays(21);
$time = $time->subMonths(14);
$time = $time->subYears(5);
比较两个时间
以下方法允许您将一个 Time 实例与另一个 Time 实例进行比较。所有比较都先转换为 UTC,然后再进行比较,以确保不同的时区能够正确响应。
equals()
确定传入的日期时间是否等于当前实例。在这种情况下,相等意味着它们代表时间上的同一时刻,并且不需要处于相同的时区,因为两个时间都转换为 UTC 并以这种方式进行比较
<?php
use CodeIgniter\I18n\Time;
$time1 = Time::parse('January 10, 2017 21:50:00', 'America/Chicago');
$time2 = Time::parse('January 11, 2017 03:50:00', 'Europe/London');
$time1->equals($time2); // true
要测试的值可以是 Time 实例、DateTime 实例或以新 DateTime 实例可以理解的方式表示完整日期时间的字符串。当将字符串作为第一个参数传递时,您可以将时区字符串作为第二个参数传递。如果没有给出时区,将使用系统默认值
<?php
$time1->equals('January 11, 2017 03:50:00', 'Europe/London'); // true
sameAs()
这与 equals()
方法相同,只是它仅在日期、时间和时区都完全相同的情况下才返回 true
<?php
use CodeIgniter\I18n\Time;
$time1 = Time::parse('January 10, 2017 21:50:00', 'America/Chicago');
$time2 = Time::parse('January 11, 2017 03:50:00', 'Europe/London');
$time1->sameAs($time2); // false
$time2->sameAs('January 10, 2017 21:50:00', 'America/Chicago'); // true
isBefore()
检查传入的时间是否早于当前实例。比较是针对两个时间的 UTC 版本进行的
<?php
use CodeIgniter\I18n\Time;
$time1 = Time::parse('January 10, 2017 21:50:00', 'America/Chicago');
$time2 = Time::parse('January 11, 2017 03:50:00', 'America/Chicago');
$time1->isBefore($time2); // true
$time2->isBefore($time1); // false
要测试的值可以是 Time 实例、DateTime 实例或以新 DateTime 实例可以理解的方式表示完整日期时间的字符串。当将字符串作为第一个参数传递时,您可以将时区字符串作为第二个参数传递。如果没有给出时区,将使用系统默认值
<?php
$time1->isBefore('March 15, 2013', 'America/Chicago'); // false
isAfter()
与 isBefore()
的工作方式完全相同,只是检查时间是否晚于传入的时间
<?php
use CodeIgniter\I18n\Time;
$time1 = Time::parse('January 10, 2017 21:50:00', 'America/Chicago');
$time2 = Time::parse('January 11, 2017 03:50:00', 'America/Chicago');
$time1->isAfter($time2); // false
$time2->isAfter($time1); // true
查看差异
要直接比较两个时间,可以使用 difference()
方法,该方法返回一个 CodeIgniter\I18n\TimeDifference
实例。第一个参数可以是时间实例、日期时间实例或包含日期/时间的字符串。如果第一个参数传入字符串,则第二个参数可以是时区字符串
<?php
use CodeIgniter\I18n\Time;
$time = Time::parse('March 10, 2017', 'America/Chicago');
$diff = $time->difference(Time::now());
$diff = $time->difference(new \DateTime('July 4, 1975', 'America/Chicago'));
$diff = $time->difference('July 4, 1975 13:32:05', 'America/Chicago');
获得 TimeDifference 实例后,您可以使用多种方法来查找有关两个时间之间差异的信息。如果时间是过去,则返回的值为负数;如果时间是未来,则返回的值为正数
<?php
use CodeIgniter\I18n\Time;
$current = Time::parse('March 10, 2017', 'America/Chicago');
$test = Time::parse('March 10, 2010', 'America/Chicago');
$diff = $current->difference($test);
echo $diff->getYears(); // -7
echo $diff->getMonths(); // -84
echo $diff->getWeeks(); // -365
echo $diff->getDays(); // -2557
echo $diff->getHours(); // -61368
echo $diff->getMinutes(); // -3682080
echo $diff->getSeconds(); // -220924800
您可以使用 getX()
方法,也可以像访问属性一样访问计算值
<?php
echo $diff->years; // -7
echo $diff->months; // -84
echo $diff->weeks; // -365
echo $diff->days; // -2557
echo $diff->hours; // -61368
echo $diff->minutes; // -3682080
echo $diff->seconds; // -220924800
humanize()
与 Time 的 humanize()
方法类似,这将返回一个字符串,该字符串以易于理解的人类可读格式显示时间之间的差异。它可以创建诸如“3 小时前”、“1 个月后”之类的字符串。最大的区别在于处理非常近期的日期的方式
<?php
use CodeIgniter\I18n\Time;
$current = Time::parse('March 10, 2017', 'America/Chicago');
$test = Time::parse('March 9, 2016 12:00:00', 'America/Chicago');
$diff = $current->difference($test);
echo $diff->humanize(); // 1 year ago
显示的确切时间按以下方式确定。
时间差 |
结果 |
---|---|
$time > 1 年 && < 2 年 |
1 年内 / 1 年前 |
$time > 1 个月 && < 1 年 |
6 个月内 / 6 个月前 |
$time > 7 天 && < 1 个月 |
3 周内 / 3 周前 |
$time > 今天 && < 7 天 |
4 天内 / 4 天前 |
$time > 1 小时 && < 1 天 |
8 小时后 / 8 小时前 |
$time > 1 分钟 && < 1 小时 |
35 分钟内 / 35 分钟前 |
$time < 1 分钟 |
现在 |
使用的确切语言由语言文件 Time.php 控制。