php 函数五 日期时间相关扩展 一

一 DateTime

与DateTimeImmutable类行为类似,但是可以修改对象本身。

1.1 静态常量

静态常量
ATOM"Y-m-d\\TH:i:sP"
COOKIE"l, d-M-Y H:i:s T"
ISO8601"Y-m-d\\TH:i:sO"
ISO8601_EXPANDED"X-m-d\\TH:i:sP"
RFC822"D, d M y H:i:s O"
RFC850"l, d-M-y H:i:s T"
RFC1036"D, d M y H:i:s O"
RFC1123"D, d M Y H:i:s O"
RFC7231"D, d M Y H:i:s \\G\\M\\T"
RFC2822"D, d M Y H:i:s O"
RFC3339"Y-m-d\\TH:i:sP"
RFC3339_EXTENDED"Y-m-d\\TH:i:s.vP"
RSS"D, d M Y H:i:s O"
W3C"Y-m-d\\TH:i:sP"

1.2 __construct(string $datetime = "now", ?DateTimeZone $timezone = null)

与DateTimeImmutable::__construct()类似,新的 DateTime 对象。继承DateTimeInterface

参数 :

  1. $datetime 日期/时间字符串,"now" 表示获取当前时间。
  2. $timezone 时区,为空则会使用当前时区,即系统时区。

1.2.1 日期或时间正确格式

通用规则:

  1. 解析器允许每个单位(年、月、日、小时、分、秒)的完整范围的值。年份只有4个数字,月份为0-12,日为0-31,小时为0-24,分钟为0-59。
  2. 60表示秒,因为有时带有闰秒的日期字符串确实会出现。但是PHP实现了Unix时间,其中“60”不是一个有效的第二个数字,因此它会溢出。
  3. 如果任何数字超出范围,strtotime()将返回false,而DateTimeImmutable::__construct()将抛出异常。
  4. 如果字符串包含日期,则所有时间元素都重置为0。
  5. 如果给定字符串中存在时间的任何部分,则将所有不太重要的时间元素重置为0。
  6. 解析器不做任何检查以使其更快(和更通用)。
  7. 除了单个时间元素的规则外,解析器还理解更具体的复合格式,例如解析Unix时间戳(@1690388256)和ISO Weekdates (2008-W28-3)。
  8. 如果提供的日期无效,则会进行额外的检查。使用date_parse()函数。
  9. DateTimeImmutable::createFromFormat()可以处理超越世间边界的错误日期,但是提供的日期格式必须正确。

日期格式 详见:PHP: Supported Date and Time Formats - Manual

1.2.2  时区

详见DateTimeZone类。使用DateTimeZone类静态成员变量。

1.3 add(DateInterval $interval)

修改 DateTime 对象,增加天、月、年、小时、分钟以及秒的数量。 返回修改后的 DateTime 对象。

1.4 sub(DateInterval $interval)

对 DateTime 对象减去一定量的日、月、年、小时、分钟和秒。 返回修改后的 DateTime 对象。

1.5 static createFromFormat(string $format, string $datetime, ?DateTimeZone $timezone = null)

$foramt识别字符如下

格式字符表述示例可解析值
日期------
d / j月的日期,2位数字,带或不带前导零

01 ~ 31或1 ~ 31。

接受比一个月的天数大的2位数,在这种情况下,它们会使这个月溢出。

例如,使用33和1月,表示2月2日。

D / l一天的文字表示

周一至周日或周日至周六。

如果给定的日名不同,则属于已解析(或默认)日期的日名也不同,则溢出给定日名的下一个日期。

S表示月份的日期,2个字符。它在处理过程中被忽略。st, nd, rd or th.
z一年中的星期几(从0开始),必须在Y或Y之前。

0到365。

接受比年份数字大3位数的数字,这种情况会使年份溢出。

例如,用366加2022表示2023年1月2日。

------
F / M月份的文本表示形式,如January或SeptJanuary 至 December 或者 Jan 至 Dec
m / n月份的数字表示形式,带或不带前导零

01到12或者1到12。

接受大于12的2位数,在这种情况下,它们会使年份溢出。例如,使用13表示下一年的1月。

------
X / x年份的完整数字表示形式,最多19位数字,可选以+或-作为前缀例如: 0055, 787, 1999, -2003, +10191
Y一年的完整数字表示形式,最多4位数字例如: 0055, 787, 1999, 2003
yA年份的两位数表示(假定在1970-2069(含)的范围内)

例如: 99 或者 03

被解释为1999年和2003年。

时间------
a / A

正午之前(Ante meridiem)

正午之后(Post meridiem)

am 或者 pm
g / h12-hour format of an hour with or without leading zero1 through 12 or 01 through 12 (2 digit numbers higher than 12 are accepted, in which case they will make the day overflow. For example using 14 means 02 in the next AM/PM period)
G / H24-hour format of an hour with or without leading zeros0 through 23 or 00 through 23 (2 digit numbers higher than 24 are accepted, in which case they will make the day overflow. For example using 26 means 02:00 the next day)
iMinutes with leading zeros00 to 59. (2 digit numbers higher than 59 are accepted, in which case they will make the hour overflow. For example using 66 means :06 the next hour)
sSeconds, with leading zeros00 through 59 (2 digit numbers higher than 59 are accepted, in which case they will make the minute overflow. For example using 90 means :30 the next minute)
vFraction in milliseconds (up to three digits)Example: 12 (0.12 seconds), 345 (0.345 seconds)
uFraction in microseconds (up to six digits)Example: 45 (0.45 seconds), 654321 (0.654321 seconds)
时区------
e, O, P / TTimezone identifier, or difference to UTC in hours, or difference to UTC with colon between hours and minutes, or timezone abbreviationExamples: UTC, GMT, Atlantic/Azores or +0200 or +02:00 or EST, MDT
完整的日期/时间------
USeconds since the Unix Epoch (January 1 1970 00:00:00 GMT)Example: 1292177455
空格和分隔符------
(space)Zero or more spaces, tabs, NBSP (U+A0), or NNBSP (U+202F) charactersExample: "\t", " "
#One of the following separation symbol: ;, :, /, ., ,, -, ( or )Example: /
;, :, /, ., ,, -, ( or )The specified character.Example: -
?A random byteExample: ^ (Be aware that for UTF-8 characters you might need more than one ?. In this case, using * is probably what you want instead)
*Random bytes until the next separator or digitExample: * in Y-*-d with the string 2009-aWord-08 will match aWord
!Resets all fields (year, month, day, hour, minute, second, fraction and timezone information) to zero-like values ( 0 for hour, minute, second and fraction, 1 for month and day, 1970 for year and UTC for timezone information)Without !, all fields will be set to the current date and time.
|Resets all fields (year, month, day, hour, minute, second, fraction and timezone information) to zero-like values if they have not been parsed yetY-m-d| will set the year, month and day to the information found in the string to parse, and sets the hour, minute and second to 0.
+If this format specifier is present, trailing data in the string will not cause an error, but a warning insteadUse DateTimeImmutable::getLastErrors() to find out whether trailing data was present.

1.6 static createFromImmutable(DateTimeImmutable $object)

返回封装给定DateTimeImmutable对象的新DateTime实例。适用于PHP7.3.0以上及 PHP 8

1.7 static createFromInterface((DateTimeInterface $object)

返回封装给定DateTimeInterface对象的新的DateTime对象。适用于PHP 8。

1.8 getLastErrors()

返回包含有关警告和错误信息的数组,如果既没有警告也没有错误,则返回false。

1.9 modify(string $modifier)

$modifier 日期/时间字符串。详见__construct()参数$datetime。

1.10 __set_state(array $array)

$array 数组初始化。返回 DateTime 对象实例。

1.11 setDate(int $year, int $month, int $day)

返回方法链修改后的 DateTime 对象。

1.12 setISODate(int $year, int $week, int $dayOfWeek = 1)

设置 ISO 日期。根据 ISO 8601 规范设置日期,使用周和日的偏移量,而不是使用指定日期。

$dayOfWeek从周的第一天计算,日在一周内的偏移量。

返回方法链修改后的 DateTime 对象。

1.13 setTime(int $hour,int $minute,int $second = 0,int $microsecond = 0)

设置时间。返回方法链修改后的 DateTime 对象。

1.14 setTimestamp(int $timestamp)

以 Unix 时间戳的方式设置日期和时间.返回方法链修改后的 DateTime 对象。

1.15 setTimezone(DateTimeZone $timezone)

设置 DateTime 对象的时区。返回链式调用的 DateTime 对象。调用此方法时,底层的时间点不会更改。

1.16 diff(DateTimeInterface $targetObject, bool $absolute = false)

因为参数$targetObject是DateTimeInterface类,所以其子类都可传入。

$targetObject 要比较的日期。

$absolute 间隔是否强制为正的。

DateTimeImmutableDateTime 对象可以使用比较运算符进行比较。

返回DateInterval类。

1.17 format(string $format)

$format 输出的日期 string 的格式。详见createFromFormat()参数$format。

1.18 getOffset()

返回时差。成功时返回与 UTC 之间的时差(以秒为单位)。

1.19 getTimestamp()

获取 Unix 时间戳。

如果时间戳不能表示为 int,将抛出 DateRangeError。在 PHP 8.3.0 之前,将抛出 ValueError。并且在 PHP 8.0.0 之前,在这种情况下返回 false。不过,可以使用 U 格式和 DateTimeInterface::format() 作为 string 检索时间戳。

1.20 getTimezone()

返回相对于指定 DateTime 的时区。

成功时返回 DateTimeZone 对象 或者在失败时返回 false

1.21 测试

1.21.1 测试1

    $dt1 = new DateTime();
    $dt2 = new DateTime();
    var_dump($dt1);
    $di = new DateInterval('P1D'); //一年一月一天一小时一四一秒
    $dt1 = $dt1->add($di);
    $date = $dt1->format('Y-m-d H:i:s');
    var_dump($date);
    $dt2 = $dt2->sub($di);
    $date = $dt2->format('Y-m-d H:i:s');
    var_dump($date);
    $di = $dt1->diff($dt2, true);
    $r = $di->format('%d days');
    var_dump($r);
    $r1 = $dt1 < $dt2;
    $r2 = $dt1 > $dt2;
    var_dump($r1, $r2);

 测试结果

object(DateTime)#1 (3) {
  ["date"]=>
  string(26) "2024-03-21 15:35:07.627395"
  ["timezone_type"]=>
  int(3)
  ["timezone"]=>
  string(13) "Asia/Shanghai"
}
string(19) "2024-03-22 15:35:07"
string(19) "2024-03-20 15:35:07"
string(6) "1 days"
bool(false)
bool(true)

 1.21.2 测试2

根据 文档PHP: Supported Date and Time Formats - Manual

DateTime构造可以传入不同格式的字符串代码设置的日期,默认使用当前时间。

    $dt = new DateTime("2008W27");
    $dt1 = new DateTime('15810726');
    $dt2 = new DateTime('5/12');
    $dt3 = new DateTime('0713');
    $dt4 = new DateTime('071136');
    $dt5 = new DateTime('Thu, 02 Jun 2022 16:58:35 +0000');
    $r = $dt5->format('Y-m-d H:i:s');
    var_dump($dt, $dt1, $dt2, $dt3, $dt4, $dt5);
    var_dump($r);

 测试结果

根据测试传入的字符串不能是两个或三个数字,需要能解析出年日月时分秒。

object(DateTime)#1 (3) {
  ["date"]=>
  string(26) "2008-06-30 00:00:00.000000"
  ["timezone_type"]=>
  int(3)
  ["timezone"]=>
  string(13) "Asia/Shanghai"
}
object(DateTime)#2 (3) {
  ["date"]=>
  string(26) "1581-07-26 00:00:00.000000"
  ["timezone_type"]=>
  int(3)
  ["timezone"]=>
  string(13) "Asia/Shanghai"
}
object(DateTime)#3 (3) {
  ["date"]=>
  string(26) "2024-05-12 00:00:00.000000"
  ["timezone_type"]=>
  int(3)
  ["timezone"]=>
  string(13) "Asia/Shanghai"
}
object(DateTime)#4 (3) {
  ["date"]=>
  string(26) "2024-03-21 07:13:00.000000"
  ["timezone_type"]=>
  int(3)
  ["timezone"]=>
  string(13) "Asia/Shanghai"
}
object(DateTime)#5 (3) {
  ["date"]=>
  string(26) "2024-03-21 07:11:36.000000"
  ["timezone_type"]=>
  int(3)
  ["timezone"]=>
  string(13) "Asia/Shanghai"
}
object(DateTime)#6 (3) {
  ["date"]=>
  string(26) "2022-06-02 16:58:35.000000"
  ["timezone_type"]=>
  int(1)
  ["timezone"]=>
  string(6) "+00:00"
}
string(19) "2022-06-02 16:58:35"

 1.21.3 测试3

    $dtz_list = DateTimeZone::listIdentifiers();
    foreach ($dtz_list as $key => $value) {
        if (preg_match('/^(Europe\/M).*$/', $value)) {
            var_dump($value);
        }
    }
    #Europe/Madrid
    $dt1 = new DateTime();
    $dt2 = new DateTime();
    $timezone = $dt1->getTimezone();
    #$timezone
    var_dump($timezone);
    $offset1 = $dt1->getOffset();
    var_dump($offset1);
    $dtz = new DateTimeZone('Europe/Madrid');
    $dt2->setTimezone($dtz);
    $offset2 = $dt2->getOffset();
    var_dump($offset2);
    $di = $dt1->diff($dt2);
    $r = $di->format('%H h %I i %S s');
    var_dump($r);

    $date1 = $dt1->format('Y-m-d H:i:s');
    $date2 = $dt2->format('Y-m-d H:i:s');
    var_dump($date1, $date2);

    $dt3 = new DateTime($date2);
    $date3 = $dt3->format('Y-m-d H:i:s');
    var_dump($date3);

    $di = $dt1->diff($dt3);
    $r = $di->format('%H h %I i %S s');
    var_dump($r);

 测试结果

string(13) "Europe/Madrid"
string(12) "Europe/Malta"
string(16) "Europe/Mariehamn"
string(12) "Europe/Minsk"
string(13) "Europe/Monaco"
string(13) "Europe/Moscow"
object(DateTimeZone)#3 (2) {
  ["timezone_type"]=>
  int(3)
  ["timezone"]=>
  string(13) "Asia/Shanghai"
}
int(28800)
int(3600)
string(14) "00 h 00 i 00 s"
string(19) "2024-03-21 16:41:06"
string(19) "2024-03-21 09:41:06"
string(19) "2024-03-21 09:41:06"
string(14) "07 h 00 i 00 s"

测试时区的使用。

先将一个对象设置不同时区,之后调用diff(),但返回DateInterval对象都是0……之后将设置不同时区后的时间直接设置DataTime对象,则返回结果正确。

显然使用diff()时使用的都是一个时区,即使两个对象设置了不同的时区。

本地测试使用php8.0.2,也许以后会改呢~

二 DateTimeZone

时区类。

2.1 预定义常量

常量解释
AFRICA非洲时区
AMERICA美洲时区
ANTARCTICA南极洲时区
ARCTIC北极时区
ASIA亚洲时区
ATLANTIC大西洋时区
AUSTRALIA澳洲时区
EUROPE欧洲时区
INDIAN印度洋(Indian)时区
PACIFIC太平洋时区
UTCUTC 时区
ALL所有时区
ALL_WITH_BC所有时区,包含向后兼容
PER_COUNTRY每个国家的时区

 2.2 __construct(string $timezone)

$timezone 时区标识符之一。

时区标识符PHP: 所支持的时区列表 - Manual

2.3 getLocation()

返回时区的位置信息,包含国家代码,经纬度和注释。

2.4 static listIdentifiers(int $timezoneGroup = DateTimeZone::ALL, ?string $countryCode = null)

返回包含了所有时区标识符的数字索引数组。

参数

  1. $timezoneGroup 时区分组的标识。为DateTimeZone静态成员常量。
  2. $countryCode 国家代码。只有当 timezoneGroup 设置为 DateTimeZone::PER_COUNTRY 时,该选项才会被使用。

2.5 getName()

返回时区名称。根据区域类型、UTC 时差(类型 1)、时区缩写(类型 2)和 IANA 时区数据库发布的时区标识符(类型 3),描述符字符串使用相同时差和/或规则创建新的 DateTimeZone。例如:02:00CEST 或者 时区列表中的其中一个时区名称。

2.6 getOffset(DateTimeInterface $datetime)

返回相对于 GMT 的时差。成功时返回精确到秒的时差, 或者在失败时返回 false

$datetime 用来计算时差的 DateTime,其包含日期/时间。

2.7 getTransitions(int $timestampBegin = PHP_INT_MIN, int $timestampEnd = PHP_INT_MAX)

返回时区的所有转换。

参数

  1. $timestampBegin 开始时间戳。
  2. $timestampEnd 结束时间戳。

成功时返回转换数组的数字索引数组,或者在失败时返回false。

包装类型1 (UTC偏移量)和类型2(缩写)的DateTimeZone对象不包含任何转换,对它们调用此方法将返回false。

如果设置timestampBegin,则返回的数组中的第一个条目将包含timestampBegin时间的转换元素。

转换阵列结构

KeyTypeDescription
tsintUnix时间戳
timestringDateTimeInterface::ISO8601_EXPANDED (PHP 8.2及更高版本), 或者
DateTimeInterface::ISO8601 (PHP 8.1及以下版本) 时间的字符串
offsetint以秒为单位的UTC偏移量
isdstbool夏令时是否有效
abbrstring时区缩写

 2.8 static listAbbreviations()

返回一个包含 夏令时(dst),时差和时区信息的关联数组。

2.9 测试

    $dtz_list = DateTimeZone::listAbbreviations();
    var_dump(count($dtz_list), array_key_first($dtz_list), $dtz_list[array_key_first($dtz_list)]);
    $dtz = new DateTimeZone('Asia/Shanghai');
    $name = $dtz->getName();
    var_dump($name);
    $local = $dtz->getLocation();
    var_dump($local);
    $dtz = new DateTimeZone('Australia/South');
    $dt = new DateTime('now', $dtz);
    $r = $dtz->getOffset($dt);
    var_dump($r);
    $r1 = $dtz->getTransitions();
    var_dump($r1[0]);
    foreach ($r1 as $key => $value) {
        var_dump($value['abbr']); 
    }

 测试结果

int(144)
string(4) "acdt"
array(6) {
  [0]=>
  array(3) {
    ["dst"]=>
    bool(true)
    ["offset"]=>
    int(37800)
    ["timezone_id"]=>
    string(18) "Australia/Adelaide"
  }
  [1]=>
  array(3) {
    ["dst"]=>
    bool(true)
    ["offset"]=>
    int(37800)
    ["timezone_id"]=>
    string(21) "Australia/Broken_Hill"
  }
  [2]=>
  array(3) {
    ["dst"]=>
    bool(true)
    ["offset"]=>
    int(37800)
    ["timezone_id"]=>
    string(16) "Australia/Darwin"
  }
  [3]=>
  array(3) {
    ["dst"]=>
    bool(true)
    ["offset"]=>
    int(37800)
    ["timezone_id"]=>
    string(15) "Australia/North"
  }
  [4]=>
  array(3) {
    ["dst"]=>
    bool(true)
    ["offset"]=>
    int(37800)
    ["timezone_id"]=>
    string(15) "Australia/South"
  }
  [5]=>
  array(3) {
    ["dst"]=>
    bool(true)
    ["offset"]=>
    int(37800)
    ["timezone_id"]=>
    string(20) "Australia/Yancowinna"
  }
}
string(13) "Asia/Shanghai"
array(4) {
  ["country_code"]=>
  string(2) "CN"
  ["latitude"]=>
  float(31.233329999999995)
  ["longitude"]=>
  float(121.46665999999999)
  ["comments"]=>
  string(12) "Beijing Time"
}
int(37800)
array(5) {
  ["ts"]=>
  int(-9223372036854775808)
  ["time"]=>
  string(33) "-292277022657-01-27T08:29:52+0000"
  ["offset"]=>
  int(33260)
  ["isdst"]=>
  bool(false)
  ["abbr"]=>
  string(3) "LMT"
}
string(3) "LMT"
string(4) "ACST"
string(4) "ACST"
string(4) "ACDT"
string(4) "ACST"
string(4) "ACDT"
string(4) "ACST"
string(4) "ACDT"
string(4) "ACST"
string(4) "ACDT"
string(4) "ACST"
string(4) "ACDT"
string(4) "ACST"
string(4) "ACDT"
string(4) "ACST"
string(4) "ACDT"
string(4) "ACST"
string(4) "ACDT"
string(4) "ACST"
string(4) "ACDT"
string(4) "ACST"
string(4) "ACDT"
string(4) "ACST"
string(4) "ACDT"
string(4) "ACST"
string(4) "ACDT"
string(4) "ACST"
string(4) "ACDT"
string(4) "ACST"
string(4) "ACDT"
string(4) "ACST"
string(4) "ACDT"
string(4) "ACST"
string(4) "ACDT"
string(4) "ACST"
string(4) "ACDT"
string(4) "ACST"
string(4) "ACDT"
string(4) "ACST"
string(4) "ACDT"
string(4) "ACST"
string(4) "ACDT"
string(4) "ACST"
string(4) "ACDT"
string(4) "ACST"
string(4) "ACDT"
string(4) "ACST"
string(4) "ACDT"
string(4) "ACST"
string(4) "ACDT"
string(4) "ACST"
string(4) "ACDT"
string(4) "ACST"
string(4) "ACDT"
string(4) "ACST"
string(4) "ACDT"
string(4) "ACST"
string(4) "ACDT"
string(4) "ACST"
string(4) "ACDT"
string(4) "ACST"
string(4) "ACDT"
string(4) "ACST"
string(4) "ACDT"
string(4) "ACST"
string(4) "ACDT"
string(4) "ACST"
string(4) "ACDT"
string(4) "ACST"
string(4) "ACDT"
string(4) "ACST"
string(4) "ACDT"
string(4) "ACST"
string(4) "ACDT"
string(4) "ACST"
string(4) "ACDT"
string(4) "ACST"
string(4) "ACDT"
string(4) "ACST"
string(4) "ACDT"
string(4) "ACST"
string(4) "ACDT"
string(4) "ACST"
string(4) "ACDT"
string(4) "ACST"
string(4) "ACDT"
string(4) "ACST"
string(4) "ACDT"
string(4) "ACST"
string(4) "ACDT"
string(4) "ACST"
string(4) "ACDT"
string(4) "ACST"
string(4) "ACDT"
string(4) "ACST"
string(4) "ACDT"
string(4) "ACST"
string(4) "ACDT"
string(4) "ACST"
string(4) "ACDT"
string(4) "ACST"
string(4) "ACDT"
string(4) "ACST"
string(4) "ACDT"
string(4) "ACST"
string(4) "ACDT"
string(4) "ACST"
string(4) "ACDT"
string(4) "ACST"
string(4) "ACDT"
string(4) "ACST"
string(4) "ACDT"
string(4) "ACST"
string(4) "ACDT"
string(4) "ACST"
string(4) "ACDT"
string(4) "ACST"
string(4) "ACDT"
string(4) "ACST"
string(4) "ACDT"
string(4) "ACST"
string(4) "ACDT"
string(4) "ACST"
string(4) "ACDT"
string(4) "ACST"
string(4) "ACDT"
string(4) "ACST"
string(4) "ACDT"
string(4) "ACST"
string(4) "ACDT"
string(4) "ACST"
string(4) "ACDT"
string(4) "ACST"
string(4) "ACDT"
string(4) "ACST"
string(4) "ACDT"
string(4) "ACST"
string(4) "ACDT"
string(4) "ACST"
string(4) "ACDT"
string(4) "ACST"
string(4) "ACDT"
string(4) "ACST"
string(4) "ACDT"

  • 16
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lsswear

感谢大佬打赏 q(≧▽≦q)

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值