Correct way to add days - php

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.

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!

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

Try like
return date('Y-m-d', strtotime("+7 day",$date));

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

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.

Related

How to sum hours with existing datetime in PHP?

I have two fields which store data like 2018-03-26 11:20:35 and 02:25:10(2 hours 25 minutes and 10 seconds) first data is date and time. second one is only time. I want to sum it and finally my result should 2018-03-26 13:45:45
How to do that in php code?
I have tried this way:
<?php
$date = '2018-03-26 11:20:35';
//echo $date;
//echo "<br>";
$hours = '02:25:10'; /* this data dynamic */
$sumTime = strtotime($date) + strtotime($hours);
$new_time = date("Y-m-d H:i:s", $sumTime);
echo $new_time;
Output:
Warning: date() expects parameter 2 to be integer, float given in C:\my-project-path\test.php on line 7
Here's a simple solution, some checks are skipped:
// convert your date to DateTime object
$date = '2018-03-26 11:20:35';
$dt = new DateTime($date);
// convert your period to DateInterval
$hours = '02:25:10'; /* this data dynamic */
$parts = explode(':', $hours);
$interval = new DateInterval('PT' . (int)$parts[0] . 'H' . $parts[1] . 'M' . $parts[2] . 'S');
// Add interval to date
$dt->add($interval);
// Format date as you need
echo $dt->format('Y-m-d H:i:s');
You could create a duration in seconds by comparing today at "00:00:00" and today at $hours. Actually, strtotime($hours) returns the timestamp of today at $hours, so, the addition of the two timestamp don't give the expected result.
If $hours is lesser than 24 hours, you could use:
$date = '2018-03-26 11:20:35';
$hours = '02:25:10';
$d0 = strtotime(date('Y-m-d 00:00:00'));
$d1 = strtotime(date('Y-m-d ').$hours);
$sumTime = strtotime($date) + ($d1 - $d0);
$new_time = date("Y-m-d H:i:s", $sumTime);
echo $new_time;
Outputs:
2018-03-26 13:45:45
You should check DateTime::add:
http://php.net/manual/en/datetime.add.php
http://php.net/manual/en/datetime.examples-arithmetic.php
Example:
<?php
// Convert h:m:s format to PThHmMsS format
sscanf('02:25:10', '%d:%d:%d', $hour, $minute, $second);
$intervalSpec = sprintf('PT%dH%dM%dS', $hour, $minute, $second);
$datetime = new DateTimeImmutable('2018-03-26 11:20:35');
$newDatetime = $datetime->add (new DateInterval($intervalSpec));
echo $newDatetime->format(DateTime::W3C);
It could be done with some simple string manipulation:
$dt = new DateTime("$date UTC");
$modify = preg_replace('/:/', ' hours ', $hours, 1);
$modify = preg_replace('/:/', ' minutes ', $modify, 1);
$modify .= ' seconds';
$dt->modify($modify);
demo
If you have MySQL as your data storage, you could do:
DATE_ADD(field1, INTERVAL field2 HOUR_SECOND)
demo
you can do something like:
$hour = $hours->format('H'); //This way you get a string which contains the hours
$date->modify('+'.$hour.' hour'); //you modify your date adding the hours
I'm assuming you only need the hours, and not minutes and seconds
EDIT:
you can do like that using regexp
$date = new \DateTime('2018-03-26 11:20:35');
$hours ='02:25:10';
preg_match("/^([0-9].*):([0-9].*):([0-9].*)/",$hours,$matches);
$date->modify('+'.$matches[1].' hour');
$date->modify('+'.$matches[2].' minute');
echo $date->modify('+'.$matches[3].' second')->format('Y-m-d H:i:s');

How to get End Date, if start date and number of days are given in laravel 5.3

I'am writing a function in laravel that calculates the end date given the start date and no. of days and stores it in the database.
This is what I have come up with:
public function store(Request $request)
{
$it = new iternary;
$it->StartDate = Input::get("StartDate");
$it->NoPeople = Input::get("NoPeople");
$it->NoDays = Input::get("NoDays");
(int)$ttemp=$it->NoDays;
$it->budget = Input::get("budget");
$EndDate = date('Y-m-d', mktime(0, 0, 0, date('m'), date('d') + $it-
>NoDays, date('Y')));
$it->EndDate = $EndDate;
$it->save();
return view('success');
}
But this gives me the wrong output.
It gives me end date same as start date.
Can you'll help please.
Thanks
You can do it like this,
$startDate = new \Carbon\Carbon('2017-05-09')
$endDate = $startDate->addDays('10')
Further info about adding and subtracting in carbon can be found here here
You can also use PHP's default DateTime class for modification,
$date = new DateTime('2017-05-09')
$date->modify('+ 10 days')
$date->modify('-1 month')
$date->modify('next year')
$date->modify('previous month')
and so on
I am not much aware about Carbon dates in laravel. But in PHP, you can try this:
$startDate = '2017-05-09';
$days = 3;
$dayStr = $days == 1 ? 'day' : 'days';
echo date('Y-m-d', strtotime('+ '.$days. ' '.$dayStr, strtotime($startDate )));
Demo

Add number of days of an existing days

I have a problem and I don't understand where it is :
So If I do :
$end_date = date('Y-m-d H:i:s',strtotime("+ $frequency days")); --> it works
If I do :
$end = $o_user->end;
$o_user->end = date($end, strtotime("+ $frequency days")); ---> not work
I tested and the 2 dates have the format : Y-m-d H:i:s
Where is my error ? Please help me. Thx in advance
Date's first param is the format, not an another date.
It should be something like this:
$o_user->end = date("Y-m-d H:i:s", strtotime($end . " +$frequency days"));
Maybe you just want to do
$o_user->end->modify("+ $frequency days");
It's even more readable and compact.
BTW your error is that date() function expect as first parameter a string (the date format)
Change to $o_user->end = date('Y-m-d H:i:s', strtotime($end, "+". $frequency. "days"));
You can use below code
$i_frequency = 4;
$end = '2016-05-23 10:48:42';
echo "==" . date('Y-m-d', strtotime("+$i_frequency days", strtotime($end)));
OR
$i_frequency = 4;
$end = '2016-05-23 10:48:42';
echo "==" . addDate($end, $i_frequency);
function addDate($date, $day)//add days
{
$sum = strtotime(date("Y-m-d", strtotime("$date")) . " +$day days");
$dateTo = date('Y-m-d', $sum);
return $dateTo;
}

Adding three months to a date in PHP

I have a variable called $effectiveDate containing the date 2012-03-26.
I am trying to add three months to this date and have been unsuccessful at it.
Here is what I have tried:
$effectiveDate = strtotime("+3 months", strtotime($effectiveDate));
and
$effectiveDate = strtotime(date("Y-m-d", strtotime($effectiveDate)) . "+3 months");
What am I doing wrong? Neither piece of code worked.
Change it to this will give you the expected format:
$effectiveDate = date('Y-m-d', strtotime("+3 months", strtotime($effectiveDate)));
This answer is not exactly to this question. But I will add this since this question still searchable for how to add/deduct period from date.
$date = new DateTime('now');
$date->modify('+3 month'); // or you can use '-90 day' for deduct
$date = $date->format('Y-m-d h:i:s');
echo $date;
I assume by "didn't work" you mean that it's giving you a timestamp instead of the formatted date, because you were doing it correctly:
$effectiveDate = strtotime("+3 months", strtotime($effectiveDate)); // returns timestamp
echo date('Y-m-d',$effectiveDate); // formatted version
You need to convert the date into a readable value. You may use strftime() or date().
Try this:
$effectiveDate = strtotime("+3 months", strtotime($effectiveDate));
$effectiveDate = strftime ( '%Y-%m-%d' , $effectiveDate );
echo $effectiveDate;
This should work. I like using strftime better as it can be used for localization you might want to try it.
Tchoupi's answer can be made a tad less verbose by concatenating the argument for strtotime() as follows:
$effectiveDate = date('Y-m-d', strtotime($effectiveDate . "+3 months") );
(This relies on magic implementation details, but you can always go have a look at them if you're rightly mistrustful.)
The following should work,Please Try this:
$effectiveDate = strtotime("+1 months", strtotime(date("y-m-d")));
echo $time = date("y/m/d", $effectiveDate);
Following should work
$d = strtotime("+1 months",strtotime("2015-05-25"));
echo date("Y-m-d",$d); // This will print **2015-06-25**
Add nth Days, months and years
$n = 2;
for ($i = 0; $i <= $n; $i++){
$d = strtotime("$i days");
$x = strtotime("$i month");
$y = strtotime("$i year");
echo "Dates : ".$dates = date('d M Y', "+$d days");
echo "<br>";
echo "Months : ".$months = date('M Y', "+$x months");
echo '<br>';
echo "Years : ".$years = date('Y', "+$y years");
echo '<br>';
}
As of PHP 5.3, DateTime along with DateInterval could be a feasible option to achieve the desired result.
$months = 6;
$currentDate = new DateTime();
$newDate = $currentDate->add(new DateInterval('P'.$months.'M'));
echo $newDate->format('Y-m-d');
If you want to subtract time from a date, instead of add, use sub.
Here are more examples on how to use DateInterval:
$interval = new DateInterval('P1Y2M3DT4H5M6S');
// This creates an interval of 1 year, 2 months, 3 days, 4 hours, 5 minutes, and 6 seconds.
$interval = new DateInterval('P2W');
// This creates an interval of 2 weeks (which is equivalent to 14 days).
$interval = new DateInterval('PT1H30M');
// This creates an interval of 1 hour and 30 minutes (but no days or years, etc.).
The following should work, but you may need to change the format:
echo date('l F jS, Y (m-d-Y)', strtotime('+3 months', strtotime($DateToAdjust)));
public function getCurrentDate(){
return date("Y-m-d H:i:s");
}
public function getNextDateAfterMonth($date1,$monthNumber){
return date('Y-m-d H:i:s', strtotime("+".$monthNumber." months", strtotime($date1)));
}

Using PHP date to display weekly dates

I'm not really sure what to call this. But basically I want to be able to have a user click on "Popular Stories from This Week", and it will take them to a page that will have other stuff but mainly the dates. For example, July 10-17.
I'm currently using this code:
$seven_days_ago = date('j') - 7;
$time_span = date('F ' . $seven_days_ago . ' - j');
Now, I ran into a problem when we entered July, because it would display something like July -3 - 4. I need a way for it to detect if the seven days ago variable is negative, and figure out what it should display. Help?
Thanks!
You can use strtotime for this:
$seven_days_ago = strtotime('-7 days');
$time_span = date('F j', $seven_days_ago) . ' - ' . date('F j');
The above gives me "June 28 - July 5" for $time_span.
you need to use strtotime
$timeago = strtotime("7 days ago");
What about using
$unix_timestamp = mktime(0, 0, 0, date("m"), date("d")-7, date("Y"));
and just take the returned unix timestamp?
Update
Just a little code snipped that will give you a full working example. However I don't like it that much :)
<?php
$today = date("d F");
list($today_day, $today_month) = explode(" ", $today);
$previous = date("d F", mktime(0, 0, 0, date("m"), date("d")-7, date("Y")));
list($previous_day, $previous_month) = explode(" ", $previous);
if($today_month != $previous_month){
echo $previous_month." ".$previous_day." - ".$today_month." ".$today_day;
}else{
echo $today_month." ".$previous_day." - ".$today_day;
}
die();
?>
i just created a very nifty little function. Just pass it the Week number, it returns you an array of that week's days dates.
function findWeekDates($weekNumber=null, $year=null ) {
// receives a specific Week Number (0 to 52) and returns that week's day dates in an array.
// If no week specified returns this week's dates.
$weekNumber = ($weekNumber=='') ? date('W'): $weekNumber ;
$year = ($year=='') ? date('Y'): $year ;
$weekNumber=sprintf("%02d", $weekNumber);
for ($i=1;$i<=7;$i++) {
$arrdays[] = strtotime($year.'W'.$weekNumber.$i);
}
return $arrdays;
}
Example Usage - find a given week start and end dates:
$week= (isset($_GET['week']) && $_GET['week'] !=='')? $_GET['week'] : date('W') ;
$year = (isset($_GET['year']) && $_GET['year'] !=='')? $_GET['year'] : date('Y') ;
if($week>52) {
$week = 1;
$year++;
}else if($week<1) {
$week=52;
$year--;
}
$week_days = findWeekDates($week, $year);
$starting_date = date('Y-m-d', $week_days[0]);
$ending_date = date('Y-m-d', $week_days[6]);
hope this helps...

Categories