时间和日期

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 控制。