-2

I've tried to add 7 days to 2013-10-26 and got back 2013-11-01. But it have to be 2013-11-02. My old function was something like this:

public static function add($date, $years = 0, $months = 0, $days = 0)
{
    $date = explode('-', $date);
    return date(
        'Y-m-d', 
        mktime(0, 0, 0, $date[1] + $months, $date[2] + $days, $date[0] + $years)
    );
}

This was correct but too slow. I've made a new one that is more specialized:

public static function adddays($date, $days = 1)
{
    if ($days == 0) return $date;
    return date('Y-m-d', strtotime($date) + 86400 * $days);
}

It works mostly correct. Not in this case. If you let calculate strtotime('2013-10-26') % 86400 then you will find out it is 10p.m. and for some reason it makes a difference.

I'm working with version 5.3.2.


Speed test:

Repeated 1000 runs for the 3 versions

DateTime : +7 day : strtotime

26ms : 43ms : 41ms
30ms : 44ms : 42ms
25ms : 42ms : 43ms
30ms : 48ms : 49ms

So more lines and a faster result. I choose DateTime of Amal.

$date = new DateTime('2013-10-26');
$days_to_add = 7;
$date->add(new DateInterval('P' . $days_to_add . 'D'));
$date->format('Y-m-d');

Thank you. But there is still the question why it wasn't working correctly from the beginning.

George Stocker
  • 57,289
  • 29
  • 176
  • 237
ortreum
  • 53
  • 6

5 Answers5

1

The best method is to use DateTime class:

$date = new DateTime('2013-10-26');
$days_to_add = 7;
$date->add(new DateInterval('P' . $days_to_add . 'D'));
echo $date->format('Y-m-d');

Output:

2013-11-02

Demo!

Amal Murali
  • 75,622
  • 18
  • 128
  • 150
  • @ortreum: What do you mean? Are you trying to subtract dates? – Amal Murali Oct 22 '13 at 13:04
  • My function adddays must be able to add -n and n days. $datetime->{($days > 0) ? 'add' : 'sub'}(new DateInterval('P' . (abs($days + 0)) . 'D')); is slidely (15-20%) slower now. And with a buffer it calculates everything only once. – ortreum Oct 22 '13 at 13:18
  • @ortreum: If you only care about speed, then use `strtotime()` and `gmdate()` as Glavic suggested. If not, it's best to use DateTime. – Amal Murali Oct 24 '13 at 16:59
1

You can use DateTime class to manipulate dates:

function add($date, $years = 0, $months = 0, $days = 0)
{
    return date_create($date)->modify("$years year $months month $days day")->format('Y-m-d');
}

Demo


But there is still the question why it wasn't working correctly from the beginning.

Because you are using date function that is timezone and DST aware with combination with strtotime which isn't. For your example, you could use gmdate that will always return time in UTC/GMT.


Speed test different combinations, and you will see that fastest one is gmdate+strtotime combination. My run on 1M loops:

addDays_v1 needed 4.5433s
addDays_v2 needed 7.4234s
addDays_v3 needed 7.6924s
addDays_v4 needed 24.1624s
Glavić
  • 42,781
  • 13
  • 77
  • 107
0

Try like

return date('Y-m-d', strtotime("+7 day",$date));
GautamD31
  • 28,552
  • 10
  • 64
  • 85
0

You can try like this-

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

Reff: http://in1.php.net/manual/en/datetime.add.php

Suresh Kamrushi
  • 15,627
  • 13
  • 75
  • 90
-3

Changing the last line to:

return date('Y-m-d', strtotime($date . ' 00:00:00 UTC') + 86400 * $days);

And everything is working fine. I've got my 2013-11-02.

ortreum
  • 53
  • 6
  • @Glavić rules are rules but to answer right after posting .. in the same minute... – Svetoslav Oct 22 '13 at 12:37
  • @Svetlio: I agree with you in this case, when this question was already answered 1000x times; but if this question was not asked on SO already, then this would be wanted behaviour. All I wanted to say, that questioner CAN be answerer ;) – Glavić Oct 22 '13 at 12:44