Php Date Function with complexity - php

My question: if the date is on Monday then my timer should start from 8:30 am and should calculate the time difference from 8:30 till date assigned, in this case its 2017-06-02 14:20:00 for first one. So time difference should be 5 hours 50 min.
Second case, date created on 2017-06-02 09:50:00 and date assigned is: 2017-06-03 13:20:00. SO it should calculate from 9:50 till 9:00pm and again start from 8:30 till 13:20:00 (if next day lies on mon-sat. If next day is sun then timer should calculate from 11am till 1:20pm. and should give me duration in hours and minutes.
How would I do that? Its in Php & MySQL. I am not any frameworks or CMS systems. Its native php.
My Data:
Date Created: 2017-06-02 02:50:00
Date Assigned: 2017-06-02 14:20:00
Date Created: 2017-06-02 09:50:00
Date Assigned: 2017-06-03 13:20:00
Mon - Sat = 8:30am - 9:00pm
Sunday = 11am - 5pm
Thank you in advance.

Edited: This function checks first what day is your dateassigned, then calculates the time difference based on your criteria.
<?php
echo getTimeLapsedCustom('2017-06-02 14:20:00') . "<br>";
echo getTimeLapsedCustom('2017-06-03 13:20:00') . "<br>";
function getTimeLapsedCustom($time){
$timecreated = '';
$timeassigned = $time;
$datetime2 = DateTime::createFromFormat('Y-m-d H:i:s', $timeassigned);
if($datetime2->format('D') === 'Sun'){
$timecreated = $datetime2->format('Y-m-d') . ' 11:00:00';
}else{
$timecreated = $datetime2->format('Y-m-d') . ' 08:30:00';
}
$datetime1 = DateTime::createFromFormat('Y-m-d H:i:s', $timecreated);
$interval = $datetime1->diff($datetime2);
return $interval->format('%h hours %i min');
}
Results:
5 hours 50 min
4 hours 50 min

Related

DateTime modify function skips February

When adding a month to with DateTime::modify method, the result skips February.
Why isn't it outputing 2020-02-31?
How to output 2020-02-29 using DateTime? (Last day of the month).
$date = new DateTime("2020-01-31");
echo $date->modify("+1 month")->format("Y-m-d"); // 2020-03-02
PHP DateTime::modify("+n month") adds between 28 to 31 days to the current day, depending of the month and year.
Solution
I suggest you increment months from the first day of the month by using the modify and format methods:
// Instanciates the DateTime object.
$date = new DateTime("2020-01-01");
// Adds a month to the date.
$date->modify("+1 month"); // 2020-02-01
// Format the date with "t" (gets the last day of the month).
$date->format("Y-m-t"); // 2020-02-29
Incrementing from the first day of the month will never raise the February problem which is quite a quite common, thinking that PHP DateTime will smartly add a month from 2020-02-29 and output 2020-03-31.
Why it happens?
In the Gregorian calendar, the average length of a month is 30.436875 days:
30 days in April, June, September and November;
31 days in January, March, May, July, August, October and December;
28 days or 29 days (in leap years) in February.
PHP will add to the current date the exact number of days there is in the given month.
Thus, PHP will adjust the date after the first increntation if you are incrementing from the
last day of the month.
E.g.:
Let's add a month from the final day of March (31th).
Since the current month (March) has 31 days in it, PHP will increment 31 days to the date. Adding 31 days from 2020-03-31 will result in skipping the whole month of April.
$date = new DateTime("2020-03-31"); // 2020-03-31
echo $date->modify("+1 month")->format("Y-m-d"); // 2020-05-01 | Added 31 days (since March has 31 days).
echo $date->modify("+1 month")->format("Y-m-d"); // 2020-06-01 | Added 31 days (since the new date is May 1st, which is a month with 31 days).
echo $date->modify("+1 month")->format("Y-m-d"); // 2020-07-01 | Added 30 days
Now, let's add a month to the final day of April (30th).
We can see that since the next months all have 30+ days in it, final day will stay the same,
until February of the next year. Since February always has between 28 and 29 days, adding 31 days to it will pass the month, and resulting date will be March 2nd.
$date = new DateTime("2020-04-30");
echo $date->modify("+1 month")->format("Y-m-d"); // 2020-05-30 | Added 30 days.
echo $date->modify("+1 month")->format("Y-m-d"); // 2020-06-30 | Added 31 days.
echo $date->modify("+1 month")->format("Y-m-d"); // 2020-07-30 | Added 30 days.
// ...
echo $date->modify("+1 month")->format("Y-m-d"); // 2021-01-30 | Added 31 days
echo $date->modify("+1 month")->format("Y-m-d"); // 2021-03-02 | Added 31 days (since January has 31 days).
echo $date->modify("+1 month")->format("Y-m-d"); // 2021-04-02 | Added 31 days (since the new date is March 2nd, which is a month with 31 days).
This is why it is recommended to increment months from the first day of the month,
since the 1st is common to all months.
$date = new DateTime("2020-01-01"); // 2020-01-01
echo $date->modify("+1 month")->format("Y-m-d"); // 2020-02-01 | Added 31 days
echo $date->modify("+1 month")->format("Y-m-d"); // 2020-03-01 | Added 29 days (since 2020 is leap year, yee haw).
echo $date->modify("+1 month")->format("Y-m-d"); // 2020-04-01 | Added 31 days
I'm making an assumption that you are programming in php. If so, the documentation indicates that you will receive the results you are getting php DateTime::modify().
The documentation specifically indicates to "Beware"
Example #2 Beware when adding or subtracting months
<?php
$date = new DateTime('2000-12-31');
$date->modify('+1 month');
echo $date->format('Y-m-d') . "\n";
$date->modify('+1 month');
echo $date->format('Y-m-d') . "\n";
?>
The above example will output:
2001-01-31
2001-03-03
If you just need to move to the end of the next +1 month, what we often do in R is go to the end of the current month and then add +1 day and then go to the end of the month again. If you know that you are always at the end of the month, then just add +1 day and then go to the end of the month.
Other posts have some additional suggestions in this space
How to find the last day of the month from date?
Example from this post:
$date = new DateTime('now');
$date->modify('last day of this month');
echo $date->format('Y-m-d');

PHP Date 4 Weeks Ago

I have the following code which outputs 20191027 as a result.
If I amend the 2nd line (i.e. set timezone to Auckland), it gives me the result 20191028. Why is this?
date_default_timezone_set("Europe/London");
#date_default_timezone_set("Pacific/Auckland");
$date_format = 'Ymd';
$day = "Sunday 4 week ago";
$start_of_the_week = strtotime($day);
$next_day = $start_of_the_week + (60 * 60 * 24 * 1);
$next_day = date($date_format, $next_day);
echo $next_day;
Check 2 outputs:
https://3v4l.org/A7ppT (20191027)
https://3v4l.org/Mfto3 (20191028)
In Europe/London timezone...
DST ended on Sun 27-Oct-2019 at 02:00:00 A.M. when local clocks were
set backward 1 hour
Keep in mind that that strtotime operates on unix timestamps where there is no concept of DST but the date function adjusts the unix timestamp to local timezone when formatting it. So:
$start_of_the_week = strtotime("Sunday 4 week ago"); // $start_of_the_week is some unix timestamp
echo date("Y-m-d H:i:s", $start_of_the_week); // 2019-10-27 00:00:00 Europe/London time
$next_day = $start_of_the_week + (60 * 60 * 24 * 1); // you're adding 24 hours to a unix timestamp
echo date("Y-m-d H:i:s", $next_day); // 2019-10-27 23:00:00 Europe/London time
And 2019-10-27 23:00:00 is still a Sunday. The solution is to add days instead of hours:
$next_day = strtotime("+1 day", $start_of_the_week); // 2019-10-28 00:00:00
As discussed in the comments, the issue is with Europe/London finishing daylight savings time on that day 4 weeks ago, so adding 24 hours to that time only took you forward by 23 hours. You can avoid issues like this by using DateTime objects and only working with days:
$date_format = 'Y-m-d H:i:s';
$day = "Sunday 4 week ago";
date_default_timezone_set("Europe/London");
$date = new DateTime($day);
$date->modify('+1 day');
echo $date->format($date_format) . "\n";
date_default_timezone_set("Pacific/Auckland");
$date = new DateTime($day);
$date->modify('+1 day');
echo $date->format($date_format) . "\n";
Output:
2019-10-28 00:00:00
2019-10-28 00:00:00
Demo on 3v4l.org
You can specify the timezone directly to the DateTime constructor too:
$date_format = 'Y-m-d H:i:s';
$day = "Sunday 4 week ago";
$date = new DateTime($day, new DateTimeZone("Europe/London"));
$date->modify('+1 day');
echo $date->format($date_format) . "\n";
$date = new DateTime($day, new DateTimeZone("Pacific/Auckland"));
$date->modify('+1 day');
echo $date->format($date_format) . "\n";
Demo on 3v4l.org
there is a difference between every time zone.
For Example
"India is 10 hours and 30 minutes ahead of Washington, DC, USA". If the echo the time of these time zones, it would end in giving different results.
In your case "Auckland, New Zealand is 13 hours ahead of London, UK", hence it is giving different O/P's
Hope this resolves your answer to the question :)

3 days is only 2 days and 11 hours away?

This is a follow up to this question: Counting down days not showing the right number of days
I'm still confused about dates and times.
Setting the start and end times:
// start date: set the time of when you click the link
$startTime = strtotime('now');
$plantStart = date('M d, Y h:i:s', $startTime);
// end date: 3 days from the time of when you click the link
$date = strtotime("+3 day", $startTime);
$plantEnd = date('M d, Y h:i:s', $date);
This gives me:
Mar 17, 2014 07:33:45 (start)
Mar 20, 2014 07:33:45 (end)
Now, the problem.. when I do this:
// show how many days/hours till $plantEnd date
$d = new DateTime($plantEnd);
$daysHours = $d->diff(new DateTime())->format('%d Days, %H Hours');
echo $daysHours;
The result is always something like: 2 Days, 11 Hours its never 3 days 0 hours or 2 days 23 hours.. Is it still just getting the time till 0:00:00 on the 3rd day instead of to the exact minute of the time?
As Yohann Tilotti mention in the comments, the issue it that new DateTime() is never initialized in the diff() function.
What you probably meant was: $d->diff(new DateTime($plantStart)).
You can see a running example here: http://ideone.com/FU8akb
Like I commented, stick to one method of dates. The preferred method being DateTime:
$plantStart = new DateTime('now');
echo $plantStart->format('Y-m-d H:i:s');
// Output: 2014-03-17 12:56:00
$plantEnd = new DateTime('now + 3 days');
echo $plantEnd->format('Y-m-d H:i:s');
// Output: 2014-03-20 12:56:00
$daysHours = $plantEnd->diff(new DateTime())->format('%d Days, %H Hours');
echo $daysHours;
// Output: 3 Days, 00 Hours

PHP Add two hours to a date within given hours using function

How would I structure the conditions to add two hours only to dates between 08:30 in the morning until 18:30 of the evening, excluding Saturday and Sunday?
In the case that a time near the border (e.g. 17:30 on Tuesday) is given, the left over time should be added to the beginning of the next "valid" time period.
For example: if the given date was in 17:30 on Tuesday, the two hour addition would result in 9:30 on Wednesday (17:30 + 1 hour = 18:30, 8:30 + the remainder 1 hour = 9:30). Or if the given date was in 17:00 on Friday, the result would be 9:00 on Monday (17:00 Friday + 1.5 hours = 18:30, 8:30 Monday + the remainder .5 hours = 9:00)
I know how to simply add two hours, as follows:
$idate1 = strtotime($_POST['date']);
$time1 = date('Y-m-d G:i', strtotime('+120 minutes', $idate1));
$_POST['due_date'] = $time1;
i have tried this this function and it works great except when i use a date like ( 2013-11-26 12:30 ) he gives me ( 2013-11-27 04:30:00 )
the problem is with 12:30
function addRollover($givenDate, $addtime) {
$starttime = 8.5*60; //Start time in minutes (decimal hours * 60)
$endtime = 18.5*60; //End time in minutes (decimal hours * 60)
$givenDate = strtotime($givenDate);
//Get just the day portion of the given time
$givenDay = strtotime('today', $givenDate);
//Calculate what the end of today's period is
$maxToday = strtotime("+$endtime minutes", $givenDay);
//Calculate the start of the next period
$nextPeriod = strtotime("tomorrow", $givenDay); //Set it to the next day
$nextPeriod = strtotime("+$starttime minutes", $nextPeriod); //And add the starting time
//If it's the weekend, bump it to Monday
if(date("D", $nextPeriod) == "Sat") {
$nextPeriod = strtotime("+2 days", $nextPeriod);
}
//Add the time period to the new day
$newDate = strtotime("+$addtime", $givenDate);
//print "$givenDate -> $newDate\n";
//print "$maxToday\n";
//Get the new hour as a decimal (adding minutes/60)
$hourfrac = date('H',$newDate) + date('i',$newDate)/60;
//print "$hourfrac\n";
//Check if we're outside the range needed
if($hourfrac < $starttime || $hourfrac > $endtime) {
//We're outside the range, find the remainder and add it on
$remainder = $newDate - $maxToday;
//print "$remainder\n";
$newDate = $nextPeriod + $remainder;
}
return $newDate;
}
I don't know if you still need this but here it is anyway. Requires PHP 5.3 or higher
<?php
function addRollover($givenDate, $addtime) {
$datetime = new DateTime($givenDate);
$datetime->modify($addtime);
if (in_array($datetime->format('l'), array('Sunday','Saturday')) ||
17 < $datetime->format('G') ||
(17 === $datetime->format('G') && 30 < $datetime->format('G'))
) {
$endofday = clone $datetime;
$endofday->setTime(17,30);
$interval = $datetime->diff($endofday);
$datetime->add(new DateInterval('P1D'));
if (in_array($datetime->format('l'), array('Saturday', 'Sunday'))) {
$datetime->modify('next Monday');
}
$datetime->setTime(8,30);
$datetime->add($interval);
}
return $datetime;
}
$future = addRollover('2014-01-03 15:15:00', '+4 hours');
echo $future->format('Y-m-d H:i:s');
See it in action
Here's an explanation of what's going on:
First we create a DateTime object representing our starting date/time
We then add the specified amount of time to it (see Supported Date and Time Formats)
We check to see if it is a weekend, after 6PM, or in the 5PM hour with more than 30 minutes passed (e.g. after 5:30PM)
If so we clone our datetime object and set it to 5:30PM
We then get the difference between the end time (5:30PM) and the modified time as a DateInterval object
We then progress to the next day
If the next day is a Saturday we progress to the next day
If the next day is a Sunday we progress to the next day
We then set our time to 8:30AM
We then add our difference between the end time (5:30PM) and the modified time to our datetime object
We return the object from the function

Calculating next business day

How can I calculate Next Business Day given a Zend_Date and a cutoff time of 5pm? Business days are M-F (weekdays).
Example:
Fri 4 pm should return same date
Sat anytime should return next Mon
Tue 8 pm should return Wed
I think this has been asked before, Next business day of given date in PHP, but here it is using Zend_Date:
$now = new Zend_Date();
if (($now->get(Zend_Date::WEEKDAY_DIGIT) % 6 == 0)
|| ($now->isLater('17:00:00', Zend_Date::TIMES))
) {
$now->set(
strtotime('+1 weekday', $now->toString(Zend_Date::TIMESTAMP)),
Zend_Date::TIMESTAMP
);
}
echo $now->toString(Zend_Date::W3C);

Categories