DateInterval::__construct

(PHP 5 >= 5.3.0, PHP 7, PHP 8)

DateInterval::__construct创建一个新的 DateInterval 对象

描述

public DateInterval::__construct(string $duration)

创建一个新的 DateInterval 对象。

参数

duration

一个时间间隔规范。

格式以字母 P 开头,代表 时期。每个时间段由一个整数和一个时期指示符表示。如果时间段包含时间元素,则该部分的规范以字母 T 开头。

duration 时期指示符
时期指示符 描述
Y
M
D
W 周。转换为天数。在 PHP 8.0.0 之前,不能与 D 结合使用。
H 小时
M 分钟
S

以下是一些简单的示例。两天是 P2D。两秒是 PT2S。六年零五分钟是 P6YT5M

注意:

单位类型必须从左侧的最大规模单位到右侧的最小规模单位输入。因此,年在月之前,月在日之前,日都在分钟之前,等等。因此,一年零四天必须表示为 P1Y4D,而不是 P4D1Y

该规范也可以表示为一个日期时间。一年零四天的示例为 P0001-00-04T00:00:00。但是,此格式的值不能超过给定时期的翻转点(例如,25 小时无效)。

这些格式基于 » ISO 8601 时间段规范

错误/异常

duration 无法解析为时间间隔时,将抛出 DateMalformedIntervalStringException。在 PHP 8.3 之前,这是 Exception

变更日志

版本 描述
8.3.0 现在抛出 DateMalformedIntervalStringException 而不是 Exception
8.2.0 只有 yfinvertdays 将可见,包括一个新的 from_string 布尔属性。
8.0.0 W 可以与 D 结合使用。

示例

示例 #1 构造和使用 DateInterval 对象

<?php
// 创建一个特定日期
$someDate = \DateTime::createFromFormat("Y-m-d H:i", "2022-08-25 14:18");

// 创建时间间隔
$interval = new \DateInterval("P7D");

// 添加时间间隔
$someDate->add($interval);

// 将时间间隔转换为字符串
echo $interval->format("%d");

以上示例将输出


7

示例 #2 DateInterval 示例

<?php

$interval
= new DateInterval('P1W2D');
var_dump($interval);

?>

PHP 8.2 中以上示例的输出

object(DateInterval)#1 (10) {
  ["y"]=>
  int(0)
  ["m"]=>
  int(0)
  ["d"]=>
  int(9)
  ["h"]=>
  int(0)
  ["i"]=>
  int(0)
  ["s"]=>
  int(0)
  ["f"]=>
  float(0)
  ["invert"]=>
  int(0)
  ["days"]=>
  bool(false)
  ["from_string"]=>
  bool(false)
}

PHP 8 中以上示例的输出

object(DateInterval)#1 (16) {
  ["y"]=>
  int(0)
  ["m"]=>
  int(0)
  ["d"]=>
  int(9)
  ["h"]=>
  int(0)
  ["i"]=>
  int(0)
  ["s"]=>
  int(0)
  ["f"]=>
  float(0)
  ["weekday"]=>
  int(0)
  ["weekday_behavior"]=>
  int(0)
  ["first_last_day_of"]=>
  int(0)
  ["invert"]=>
  int(0)
  ["days"]=>
  bool(false)
  ["special_type"]=>
  int(0)
  ["special_amount"]=>
  int(0)
  ["have_weekday_relative"]=>
  int(0)
  ["have_special_relative"]=>
  int(0)
}

PHP 7 中以上示例的输出

object(DateInterval)#1 (16) {
  ["y"]=>
  int(0)
  ["m"]=>
  int(0)
  ["d"]=>
  int(2)
  ["h"]=>
  int(0)
  ["i"]=>
  int(0)
  ["s"]=>
  int(0)
  ["f"]=>
  float(0)
  ["weekday"]=>
  int(0)
  ["weekday_behavior"]=>
  int(0)
  ["first_last_day_of"]=>
  int(0)
  ["invert"]=>
  int(0)
  ["days"]=>
  bool(false)
  ["special_type"]=>
  int(0)
  ["special_amount"]=>
  int(0)
  ["have_weekday_relative"]=>
  int(0)
  ["have_special_relative"]=>
  int(0)
}

参见

添加备注

用户贡献的备注 15 备注

owen at beliefs.com
11 年前
M 用于表示月和分钟。

如引用的 ISO 6801 维基百科页面 http://en.wikipedia.org/wiki/Iso8601#Durations 上所述

为了解决歧义,“P1M” 是一个月的时间段,“PT1M” 是一分钟的时间段(注意时间指示符 T,它位于时间值之前)。

使用:PHP 5.3.2-1ubuntu4.19

// 3 个月
$dateTime = new DateTime;echo $dateTime->format( DateTime::ISO8601 ), PHP_EOL;
$dateTime->add(new DateInterval("P3M"));
echo $dateTime->format( DateTime::ISO8601 ), PHP_EOL;
结果为
2013-07-11T11:12:26-0400
2013-10-11T11:12:26-0400

// 3 分钟
$dateTime = new DateTime;echo $dateTime->format( DateTime::ISO8601 ), PHP_EOL;
$dateTime->add(new DateInterval("PT3M"));
echo $dateTime->format( DateTime::ISO8601 ), PHP_EOL;
结果为
2013-07-11T11:12:42-0400
2013-07-11T11:15:42-0400

在时间间隔中的 P 之后插入一个 T 以添加 3 分钟而不是 3 个月。
Hernanibus
6 年前
虽然没有说明,但您无法直接创建一个负时间间隔,也就是说,您无法创建一个“负 2 天”的时间间隔,例如

<?
$interval = new DateInterval("P-2D");//或者
$interval = new DateInterval("-P2D");
?>

相反,您必须先创建时间间隔,然后将其 'invert' 属性设置为 1,即

<?
$interval = new DateInterval("P2D");
$interval->invert = 1;
?>

然后,您应该记住,此时间间隔充当负数,因此,要从给定日期减去时间间隔,您必须将其 '添加'

<?
$interval = new DateInterval("P2D");
$interval->invert = 1;
$date = new DateTime ("1978-01-23 17:46:00");
$date->add($interval)->format("Y-m-d H:i:s");//即 "1978-01-21 17:46:00"
?>
kuzb
13 年前
需要注意的是,此类不会计算给定单个时间计量单位的值(例如天数、小时数、分钟数、秒数等)。例如

<?php
$di
= new DateInterval('PT3600S');
echo
$di->format('%H:%i:%s');

?>

将产生 0:0:3600 而不是预期的 1:0:0
buvinghausen at gmail dot com
12 年前
我认为使用 DateTime 类上的 sub 方法最简单。

<?php
$date
= new DateTime();
$date->sub(new DateInterval("P89D"));
admin at torntech dot com
9 年前
警告 - 尽管 $interval_spec 接受 ISO 8601 规范格式,但它不接受规范中规定的带点或逗号的小数分数值。

https://bugs.php.net/bug.php?id=53831

<?php
/* 来自 ISO 8601 文档的示例 */
$interval = new DateInterval('P0.5Y');
?>

将导致
致命错误: 未捕获异常 'Exception',消息为 'DateInterval::__construct(): 未知或格式错误 (P0.5Y)'
kevinpeno at gmail dot com
13 年前
注意,虽然 DateInterval 对象具有 $invert 属性,但您不能直接在构造函数中提供负数,类似于在 XSD 中指定负数 ("-P1Y")。如果您这样做,您将得到一个异常。

相反,您需要使用正间隔 ("P1Y") 进行构造,并指定 $invert 属性 === 1。
daniellehr at gmx dot de
12 年前
或者,您可以使用 DateInterval::createFromDateString() 来处理负间隔

<?php
$date
= new DateTime();
$date->add(DateInterval::createFromDateString('-89 days'));
userexamplecom at mailinator dot com
8 年前
注意,如果您有一个 DateTime 对象在 1 月 31 日,并且添加了一个月的 DateInterval,那么您将在 3 月而不是 2 月。

例如
---
// 假设当前日期是 2017-01-31
$today = new DateTime('now', $timeZoneObject);
$today->add(new DateInterval('P1M'));
echo $today->format('m');
// 输出: 03
---
jawzx01 at gmail dot com
12 年前
如前所述,要创建一个负 DateInterval 对象,您需要编写以下代码

<?php
$date1
= new DateTime();
$eightynine_days_ago = new DateInterval( "P89D" );
$eightynine_days_ago->invert = 1; // 使其为负数。
$date1->add( $eightynine_days_ago );
?>

然后 $date1 现在是 89 天前的日期。
Anonymous
3 年前
请注意,要添加时间,您必须输入 P,即使期间为空。

添加 1 小时

<?php

$plusOneHour
= (new DateTime('now'))->add(new DateInterval("PT1H"));

var_dump($plusOneHour);

?>
sloanlance+php.net gmail com
6 年前
⚠️ 重要的是要记住 "admin at torntech dot com" 在之前评论中给出的关于 DateInterval 的警告 (https://php.net/manual/en/dateinterval.construct.php#116750)。重申一下

某些版本的 PHP (例如,5.6.31) 存在一个 bug,不允许在作为 DateInterval 构造函数参数给出的 ISO 8601 持续时间字符串中使用小数部分。也就是说,以下示例将失败

<?php
// 'P0.5Y' 符合 ISO 8601 标准
$interval = new DateInterval('P0.5Y'); // 抛出异常
?>

<?php
// 'PT585.829S' 符合 ISO 8601 标准
$interval = new DateInterval('PT585.829S'); // 抛出异常
?>

如果此 bug 影响到您,请访问 PHP 错误追踪系统的此 bug 报告,并投票说明它影响到您:https://bugs.php.net/bug.php?id=53831
lsloan-php dot net at umich dot edu
8 年前
虽然 PHP 将时间段称为 "间隔",但 ISO 8601 将其称为 "持续时间"。在 ISO 8601 中,"间隔" 是另外一种东西。

虽然 ISO 8601 允许持续时间的所有部分使用小数 (例如,"P0.5Y"),但 DateInterval 不允许。在计算持续时间时请谨慎。如果持续时间具有小数部分,它在存储到 DateInterval 对象中时可能会丢失。
Ray.Paseur sometimes uses Gmail
8 年前
要恢复间隔规范字符串

<?php
function get_interval_spec(DateTime $alpha, DateTime $omega)
{
$intvl = $alpha->diff($omega);

$date = NULL;
if (
$intvl->y) $date .= $intvl->y . 'Y';
if (
$intvl->m) $date .= $intvl->m . 'M';
if (
$intvl->d) $date .= $intvl->d . 'D';

$time = NULL;
if (
$intvl->h) $time .= $intvl->h . 'H';
if (
$intvl->i) $time .= $intvl->i . 'M';
if (
$intvl->s) $time .= $intvl->s . 'S';
if (
$time) $time = 'T' . $time;

$text ='P' . $date . $time;
if (
$text == 'P') return 'PT0S';
return
$text;
}
grzeniufication
4 年前
如果您想将间隔对象持久化到数据库中,实现 __toString() 方法会很有用。与序列化后的输出相比,格式化的间隔值更容易被人理解。以下是一个示例

<?php

namespace App;

class
DateInterval extends \DateInterval
{
public function
__toString()
{
return
$this->format('P%yY%mM%dDT%hH%iM%sS');
}
}

$interval1 = new DateInterval('P1Y');
$interval2 = new DateInterval(strval($interval1));
assert($interval1 == $interval2);
bkilinc at deyta dot net
10 年前
interval_spec 期间指定符,对月份和分钟使用两个 'M'。
To Top