DateInterval 类
(PHP 5 >= 5.3.0, PHP 7, PHP 8)
简介
表示时间间隔。
时间间隔表示固定量的时间(多少年,月,天,小时等),也可以表示一个字符串格式的相对时间,当表示相对时间的时候,字符串格式是 DateTimeImmutable 和 DateTime 类的构造函数所支持的格式。
更具体的说,DateInterval 类的对象中的信息是从一个日期/时间到另一个日期/时间的指令。这个过程并不始终可逆。
创建 DateInterval 对象的常用方法是通过 DateTimeInterface::diff() 计算两个日期/时间对象之间的差异。
由于没有明确定义的方法来比较日期间隔,因此 DateInterval 实例是无法比较的。
类摘要
属性
下列列出的有效属性依赖 PHP 版本,应视为 readonly。
- y
-
多少年。
- m
-
多少月。
- d
-
多少天。
- h
-
多少小时。
- i
-
多少分钟。
- s
-
多少秒。
- f
-
多少微秒。
- invert
-
如果是负的时间段,则为
1
,否则为0
。请参见 DateInterval::format()。 - days
-
如果 DateInterval 对象是由 DateTimeImmutable::diff() 或者 DateTime::diff() 函数创建的,那么它表示开始日期和结束日期之间的完整天数。否则,days 属性为
false
。 - from_string
-
如果 DateInterval 对象是通过 DateInterval::createFromDateString() 创建,则此属性值设为
true
并且 date_string 属性将填充数据。否则,此值设为false
且为从 y 到 f、invert 和 days 属性填充数据。 - date_string
-
字符串,用作 DateInterval::createFromDateString() 的参数。
更新日志
版本 | 说明 |
---|---|
8.2.0 | 为使用 DateInterval::createFromDateString() 方法创建的 DateInterval 实例添加了 from_string 和 date_string 属性。 |
8.2.0 |
仅从 y 到 f 、invert
和 days 将可见。
|
7.4.0 | 现在 DateInterval 无法比较;之前所有的 DateInterval 实例都认为相等。 |
7.1.0 | 增加 f 属性。 |
目录
- DateInterval::__construct — Creates a new DateInterval object
- DateInterval::createFromDateString — Sets up a DateInterval from the relative parts of the string
- DateInterval::format — Formats the interval
用户贡献的备注 4 notes
If you want to reverse a date interval use array_reverse and iterator_to_array. I've found using invert to be unreliable.
<?php
$start_date = date_create("2021-01-01");
$end_date = date_create("2021-01-05"); // If you want to include this date, add 1 day
$interval = DateInterval::createFromDateString('1 day');
$daterange = new DatePeriod($start_date, $interval ,$end_date);
function show_dates ($dr) {
foreach($dr as $date1){
echo $date1->format('Y-m-d').'<br>';
}
}
show_dates ($daterange);
echo '<br>';
// reverse the array
$daterange = array_reverse(iterator_to_array($daterange));
show_dates ($daterange);
?>
Gives
2021-01-01
2021-01-02
2021-01-03
2021-01-04
2021-01-04
2021-01-03
2021-01-02
2021-01-01
There is a handy way to compare intervals by adding them to 0 dates and comparing dates instead
<?php
function compare(DateInterval $first, DateInterval $second): int
{
$firstDate = (new DateTime())->setTimestamp(0)->add($first);
$secondDate = (new DateTime())->setTimestamp(0)->add($second);
return $firstDate <=> $secondDate;
}
echo compare(new DateInterval('P2D'), new DateInterval('PT48H')) . PHP_EOL;
echo compare(DateInterval::createFromDateString('2 days'), DateInterval::createFromDateString('48 hours')) . PHP_EOL;
echo compare(DateInterval::createFromDateString('2 days'), DateInterval::createFromDateString('49 hours')) . PHP_EOL;
echo compare(DateInterval::createFromDateString('2 days'), DateInterval::createFromDateString('47 hours')) . PHP_EOL;
?>
Outputs:
0
0
-1
1
More simple example i use to add or subtract.
<?php
$Datetime = new Datetime('NOW', new DateTimeZone('America/Bahia'));
$Datetime->add(DateInterval::createFromDateString('2 day'));
echo $Datetime->format("Y-m-d H:i:s");
?>
Subtracting months may not work as you might expect.
Code shows how subtracting 2 months from consecutive days produces potentially unexpected results.
<?php
$origin = date_create('2025-01-31T00:00:00');
$target = date_create('2024-11-26T00:00:00');
$interval = date_diff($origin, $target);
echo "interval total days: ".$interval->format('%a days');
echo "interval object years: ".$interval->format('%y years');
echo "interval object months: ".$interval->format('%m months');
echo "interval object days: ".$interval->format('%d days');
// create 3 dates that are consecutive, but in two months
$d1 = date_create('2025-01-31T00:00:00');
$d2 = date_create('2025-02-01T00:00:00');
$d3 = date_create('2025-02-02T00:00:00');
// add (negative) interval object to each date
$d1->add($interval);
$d2->add($interval);
$d3->add($interval);
echo "Add (negative) interval object to each date. Non-consecutive results: ";
echo($d1->format("Y-m-d\TH:i:s"));
echo($d2->format("Y-m-d\TH:i:s"));
echo($d3->format("Y-m-d\TH:i:s"));
// reset dates
$d1 = date_create('2025-01-31T00:00:00');
$d2 = date_create('2025-02-01T00:00:00');
$d3 = date_create('2025-02-02T00:00:00');
// Use same dates, but subtract total number of days instead of adding interval object: ";
$d1->sub(new DateInterval('P'.$interval->format('%a').'D'));
$d2->sub(new DateInterval('P'.$interval->format('%a').'D'));
$d3->sub(new DateInterval('P'.$interval->format('%a').'D'));
echo "Use same dates, but subtract total number of days instead of adding interval object. Results (consecutive): ";
echo($d1->format("Y-m-d\TH:i:s"));
echo($d2->format("Y-m-d\TH:i:s"));
echo($d3->format("Y-m-d\TH:i:s"));
$d1 = date_create('2025-01-31T00:00:00');
$d2 = date_create('2025-02-01T00:00:00');
$d3 = date_create('2025-02-02T00:00:00');
// do month separately for 2025-02-01T00:00:00
echo "Do month separately (interesting): ";
echo ('Subtract '. $interval->format('%m').' months (might not expect this):');
echo ('Jan 31 - 2 months (61 days = Dec, 31 days + Nov, 30 days) ==> Dec 1');
echo ('Feb 1 - 2 months (62 days = Dec, 31 days + Jan, 31 days) ==> Dec 1');
$d1->sub(new DateInterval('P'.$interval->format('%m').'M'));
echo $d1->format("Y-m-d\TH:i:s");
$d2->sub(new DateInterval('P'.$interval->format('%m').'M'));
echo $d2->format("Y-m-d\TH:i:s");
$d3->sub(new DateInterval('P'.$interval->format('%m').'M'));
echo $d3->format("Y-m-d\TH:i:s");
?>
Output:
interval total days: 66 days
interval object years: 0 years
interval object months: 2 months
interval object days: 5 days
create 3 dates that are consecutive, but in two months:
$d1 = 2025-01-31T00:00:00
$d2 = 2025-02-01T00:00:00
$d3 = 2025-02-02T00:00:00
Add (negative) interval object to each date. Non-consecutive results:
2024-11-26T00:00:00
2024-11-26T00:00:00
2024-11-27T00:00:00
Use same dates, but subtract total number of days instead of adding interval object. Results (consecutive):
2024-11-26T00:00:00
2024-11-27T00:00:00
2024-11-28T00:00:00
Do month separately (interesting):
Subtract 2 months (might not expect this):
Jan 31 - 2 months (61 days = Dec, 31 days + Nov, 30 days) ==> Dec 1
Feb 1 - 2 months (62 days = Dec, 31 days + Jan, 31 days) ==> Dec 1
2024-12-01T00:00:00
2024-12-01T00:00:00
2024-12-02T00:00:00