• 首页
  • vue
  • TypeScript
  • JavaScript
  • scss
  • css3
  • html5
  • php
  • MySQL
  • redis
  • jQuery
  • DateTime::sub()

    date_sub

    (PHP 5 >= 5.3.0, PHP 7)

    对一个 DateTime 对象减去一定量的日、月、年、小时、分钟和秒。

    说明

    面向对象风格
    publicDateTime::sub(DateInterval$interval): DateTime
    过程化风格
    date_sub(DateTime$object,DateInterval$interval): DateTime

    DateInterval对象,表示要减去多少量的时间。

    参数

    $object

    仅过程化风格:由date_create()返回的DateTime类型的对象。此函数会修改这个对象。

    $interval

    DateInterval对象

    返回值

    返回被修改的 DateTime 对象,或者在失败时返回FALSE.

    范例

    Example #1DateTime::sub()例程

    面向对象风格

    <?php
    $date = new DateTime('2000-01-20');
    $date->sub(new DateInterval('P10D'));
    echo $date->format('Y-m-d') . "\n";
    ?>
    

    过程化风格

    <?php
    $date = date_create('2000-01-20');
    date_sub($date, date_interval_create_from_date_string('10 days'));
    echo date_format($date, 'Y-m-d');
    ?>
    

    以上例程会输出:

    2000-01-10
    

    FurtherDateTime::sub()例程

    <?php
    $date = new DateTime('2000-01-20');
    $date->sub(new DateInterval('PT10H30S'));
    echo $date->format('Y-m-d H:i:s') . "\n";
    $date = new DateTime('2000-01-20');
    $date->sub(new DateInterval('P7Y5M4DT4H3M2S'));
    echo $date->format('Y-m-d H:i:s') . "\n";
    ?>
    

    以上例程会输出:

    2000-01-19 13:59:30
    1992-08-15 19:56:58
    

    减去一定量的月份的时候需要注意

    <?php
    $date = new DateTime('2001-04-30');
    $interval = new DateInterval('P1M');
    $date->sub($interval);
    echo $date->format('Y-m-d') . "\n";
    $date->sub($interval);
    echo $date->format('Y-m-d') . "\n";
    ?>
    

    以上例程会输出:

    2001-03-30
    2001-03-02
    

    注释

    在 PHP 5.2 之后,可以使用DateTime::modify()作为替代。

    参见

    • DateTime::add() 给一个 DateTime 对象增加一定量的天,月,年,小时,分钟以及秒。
    • DateTime::diff() Returns the difference between two DateTime objects
    • DateTime::modify() 修改日期时间对象的值
    Note that the sub() and add() methods will modify the value of the object you're calling the method on! This is very untypical for a method that returns a value of its own type. You could misunderstand it that the method would return a new instance with the modified value, but in fact it modifies itself! This is undocumented here. (Only a side note on procedural style mentions it, but it obviously does not apply to object oriented style.)
    If you use diff() after sub(), the effects of the sub() will be repeated on the date object.
    It doesn't matter if the object is the one diffed or doing the diffing (i.e. which object you call diff() from).
    <?php
    $today = new DateTime();
    $newdate = new DateTime();
    print_r($newdate);
    $newdate->sub(new DateInterval("PT1S"));
    print_r($newdate);
    $s = $newdate->diff($today);
    print_r($newdate);
    $s = $today->diff($newdate);
    print_r($newdate);
    $s = $today->diff($newdate);
    print_r($newdate);
    ?>
    Prints:
    DateTime Object
    (
      [date] => 2010-11-30 18:43:48
      [timezone_type] => 3
      [timezone] => America/Los_Angeles
    )
    DateTime Object
    (
      [date] => 2010-11-30 18:43:47
      [timezone_type] => 3
      [timezone] => America/Los_Angeles
    )
    DateTime Object
    (
      [date] => 2010-11-30 18:43:46
      [timezone_type] => 3
      [timezone] => America/Los_Angeles
    )
    DateTime Object
    (
      [date] => 2010-11-30 18:43:45
      [timezone_type] => 3
      [timezone] => America/Los_Angeles
    )
    DateTime Object
    (
      [date] => 2010-11-30 18:43:44
      [timezone_type] => 3
      [timezone] => America/Los_Angeles
    )
    Note that using add() instead of sub() does NOT have the same effect.
    This is particularly undesirable -- in this example you make a datetime, use sub() to make it a relative time in the past, and then date->diff() to confirm the difference. But the diff() inadvertendly makes the difference 2x.
    When trying to pass daylight saving state change time, sub() works incorrectly.
    $t = new DateTime( '2014-03-30 02:00:00' );
    $t->add( new DateInterval('PT1H') );
    echo $->format('Y-m-d H:i:s');
    output will be: '2014-03-30 04:00:00'.
     Well, it's ok because at 3:00 a.m. daylight saving time begins in my country, so after 02:59:59 must be 04:00:00.
    But if I try to subtract time:
    $t = new DateTime( '2014-03-30 04:00:00' );
    $t->sub( new DateInterval('PT1H') );
    echo $->format('Y-m-d H:i:s');
    output will be: '2014-03-30 04:00:00'.
    Yes, completely the same, not '2014-03-30 02:00:00' as it should be.
    As noted above when subtracting months, results can be suspect. I needed to create an array of end of month dates for 6 months starting at Oct and going back. Using:
    <?php
    //Instantiate array
    $dateset = [];
    //Create new date object
    $date = new \DateTime('2018-10-31);
    //Add to array
    $dateset[] = $date->format('Y-m-d');
    //Go back 5 months
    $nbr = 6;
    for($i = 1; $i < $nbr; $i++){
      $date->sub(new \DateInterval('P1M'));
      $dateset[] = $date->format('Y-m-d');
    }
    ?>
    Results in:
    array:6 [▼
     0 => "2018-10-31"
     1 => "2018-10-01"
     2 => "2018-09-01"
     3 => "2018-08-01"
     4 => "2018-07-01"
     5 => "2018-06-01"
    ]
    However, using ->modify("last day of last month") accurately gives month ending dates:
    <?php
    //Instantiate array
    $dateset = [];
    //Create new date object
    $date = new \DateTime('2018-10-31);
    //Add to array
    $dateset[] = $date->format('Y-m-d');
    //Go back 5 months
    $nbr = 6;
    for($i = 1; $i < $nbr; $i++){
      $date->modify('last day of last month');
      $dateset[] = $date->format('Y-m-d');
    }
    ?>
    Results in:
    array:6 [▼
     0 => "2018-10-31"
     1 => "2018-09-30"
     2 => "2018-08-31"
     3 => "2018-07-31"
     4 => "2018-06-30"
     5 => "2018-05-31"
    ]
    CAUTION: Never subtract months from the current day, always do so from the 1st of the month. 
    Let us imagine that it is May 31, 2019, so 2019-05-31, the function will not give 2019-04-31 because April is not 31 days old but 30, it will create problems.