I have a problem. My English is pretty bad. I need to do an overtime calculation with PHP. There is already a code for this. But when the working time is more than 2 days, the calculation is wrong.
Working Start: 2018-09-09 13:43
Working End: 2018-09-11 07:13
Result: 07:18 | 04:00 | 04:00 | 02:00 | 17:18
I can't figure out the problem, please help.
I'd like to give you more details, but I'm pretty bad. I hope you understand me.
Thanks.
<?php
function intersection($s1, $e1, $s2, $e2,$day) {
return subintersection($s1,$e1,$s2,$e2)+subintersection($s1,$e1,$s2+$day,$e2+$day);
}
function subintersection($s1, $e1, $s2, $e2) {
if ($e1 < $s2)
return 0;
if ($s1 > $e2)
return 0;
if ($s1 < $s2)
$s1 = $s2;
if ($e1 > $e2)
$e1 = $e2;
return $e1 - $s1;
}
function minuteToHours($time, $format = '%02d:%02d') {
if ($time < 1) {
return;
}
$hours = floor($time / 60);
$minutes = ($time % 60);
return sprintf($format, $hours, $minutes);
}
function calculateWork($strstart, $strend, $arg = NULL){
$day= 3600*24;
$strS = strtotime($strstart);
$strE = strtotime($strend);
$date_start = date('Y-m-d', $strS);
$date_end = date('Y-m-d', $strE);
$hour_start = date('H:i', $strS);
$hour_end = date('H:i', $strE);
$start = strtotime($hour_start);
$end = strtotime($hour_end);
if($date_start != $date_end){
$end = $end + 3600*24;
}
$tip1_start = strtotime("06:00");
$tip1_end = strtotime("20:00");
$tip2_start = strtotime("20:00");
$tip2_end = strtotime("00:00") + 3600*24;
$tip3_start = strtotime("00:00");
$tip3_end = strtotime("04:00");
$tip4_start = strtotime("04:00");
$tip4_end = strtotime("06:00");
$tip1 = intersection( $start, $end, $tip1_start, $tip1_end, $day) / 60;
$tip2 = intersection( $start, $end, $tip2_start, $tip2_end, $day) / 60;
$tip3 = intersection( $start, $end, $tip3_start, $tip3_end, $day) / 60;
$tip4 = intersection( $start, $end, $tip4_start, $tip4_end, $day) / 60;
if(null !== minuteToHours($tip1, '%02d:%02d')){
$t1 = minuteToHours($tip1, '%02d:%02d');
}
if(null !== minuteToHours($tip2, '%02d:%02d')){
$t2 = minuteToHours($tip2, '%02d:%02d');
}
if(null !== minuteToHours($tip3, '%02d:%02d')){
$t3 = minuteToHours($tip3, '%02d:%02d');
}
if(null !== minuteToHours($tip4, '%02d:%02d')){
$t4 = minuteToHours($tip4, '%02d:%02d');
}
$topla = $tip1 + $tip2 + $tip3 + $tip4;
$total = minuteToHours($topla, '%02d:%02d');
return "{$t1}|{$t2}|{$t3}|{$t4}|{$total}";
}
echo calculateWork("2018-09-09 13:43", "2018-09-11 07:01");
//07:18|04:00|04:00|02:00|17:18
Related
Suppose I have two strings like "08:50" (start) and "23:50" (end).
Now I know that the morning is from 06:00 to 22:00 and the night is from 22:00 and 06:00.
The question is, how can I know how much time is in the morning and how much in the night? It should be 9 hours in the morning and 1 hour 50 minutes in the night.
I have done a code, but sometimes (with particolar values) it crashes, and it loses couple of minutes:
function analizza_mattina_sera($result2)
{
$inizio_giorno = oreToMinuti("06:00");
$fine_giorno = oreToMinuti("22:00");
$inizio_notte = oreToMinuti("22:00");
$fine_notte = oreToMinuti("06:00");
$conto_minuti_giorno = "";
$conto_minuti_notte = "";
while ($row2 = mysql_fetch_array($result2)) {
$data1 = strtotime($row2["anno"]
."-". $row2["mese"]
."-". $row2["giorno"]
." ". $row2["ora_effettiva"]);
$data2 = strtotime($row2["anno"]
."-". $row2["mese"]
."-". $row2["giorno"]
." ". $row2["ora_teorica"]);
$differenza = (($data2 - $data1) / 3600) / (1 / 60);
if ($row2["verso"] == "entrata") {
$ora_usa = $row2["ora_effettiva"];
if (oreToMinuti($ora_usa) < $inizio_giorno) {
$conto_minuti_notte = $fine_notte - oreToMinuti($ora_usa);
}
if (oreToMinuti($ora_usa) > $inizio_giorno) {
$conto_minuti_giorno = oreToMinuti($ora_usa) - $inizio_giorno;
}
}
else {
$ora_usa = $row2["ora_effettiva"];
if (oreToMinuti($ora_usa) < $fine_giorno) {
if (oreToMinuti($ora_usa) < $fine_notte) {
$conto_minuti_notte = ($fine_notte - oreToMinuti($ora_usa)) - $conto_minuti_notte;
}
else {
$conto_minuti_giorno = oreToMinuti($ora_usa) - $inizio_giorno - $conto_minuti_giorno;
}
}
else {
$conto_minuti_notte = oreToMinuti($ora_usa) - $inizio_notte;
$conto_minuti_giorno = $fine_giorno - $conto_minuti_giorno - $inizio_giorno;
}
}
}
return str_replace("-", "", ($conto_minuti_giorno == "" ? 0 : $conto_minuti_giorno)
."_". ($conto_minuti_notte == "" ? 0 : $conto_minuti_notte)) ."<br />";
}
You can try this (you should add some validation).
Here is how to use it, it will return an array of morning period in minutes and night period in minutes:
categorizePeriod('08:50', '23:50');
Here are the functions:
function minutesDiff($startTime, $endTime)
{
$isNextDay = ($startTime > $endTime) ? 1 : 0;
$start = explode(':', $startTime);
$end = explode(':', $endTime);
$diffInSeconds = abs(mktime($start[0], $start[1], 0, null, date('j'), null) - mktime($end[0], $end[1], 0, null, date('j') + $isNextDay, null));
return floor($diffInSeconds/60);
}
function inMorning($time, array $morning)
{
return ($morning[0] <= $time && $time <= $morning[1]);
}
function categorizePeriod($startTime, $endTime, array $morning = array('06:00', '22:00'))
{
if ($startTime == $endTime) {
return array(0, 0);
} else if ($startTime > $endTime) {
$beforeMidnight = categorizePeriod($startTime, '23:59', $morning);
$afterMidnight = categorizePeriod('00:00', $endTime, $morning);
return array(
$beforeMidnight[0] + $afterMidnight[0] + (int)inMorning('00:00', $morning),
$beforeMidnight[1] + $afterMidnight[1] + (int)!inMorning('00:00', $morning),
);
}
if (inMorning($startTime, $morning) && inMorning($endTime, $morning)) {
return array(
minutesDiff($startTime, $endTime),
0
);
} elseif (!inMorning($startTime, $morning) && !inMorning($endTime, $morning)) {
return array(
0,
minutesDiff($startTime, $endTime)
);
} elseif (inMorning($startTime, $morning) && !inMorning($endTime, $morning)) {
return array(
minutesDiff($startTime, $morning[1]),
minutesDiff($morning[1], $endTime)
);
} elseif (!inMorning($startTime, $morning) && inMorning($endTime, $morning)) {
return array(
minutesDiff($morning[0], $endTime),
minutesDiff($startTime, $morning[0])
);
}
}
I hope this is what you are looking for.. I have converted to hours..
Say for e.g.
Start - 4.30 and End - 21.30 then morning 15.5 hours and night 1.5 hours
Start - 4.30 and End - 22.30 then morning 16 hours and night 2 hours
Start - 6.30 and End - 21.30 then morning 15 hours and night 0 hours
Start - 6.30 and End - 22.30 then morning 15.5 hours and night 0.5 hours
Following is the script may be helpful to you.
<?php
//Get the timeslote how many hours spent in the morning and how many hours spent in the night
$start = "00:00";
$end = "00:00";
$morningSlote = "06:00 - 22:00";
$nightSlote = "22:00 - 06:00";
$startTime = strtotime($start);
$endTime = strtotime($end);
$startDate = date("m/d/Y");
$endDate = date("m/d/Y");
if($startTime > $endTime) {
//Date will be changed
//i.e. 11.30 PM - 2.30 AM
//i.e. 11.30 PM - 6.20 PM
$startDate = date("m/d/Y H:i:s",strtotime($start));
$endDate = date("m/d/Y H:i:s",strtotime("+1 day".$end));
} else if($endTime > $startTime) {
//No date will be changed
//i.e. 2.30 AM - 11.30 PM
//i.e. 2.30 AM - 6.30 AM
$startDate = date("m/d/Y H:i:s",strtotime($start));
$endDate = date("m/d/Y H:i:s",strtotime($end));
}
$output = getCorrectTimeslote($startDate, $endDate, $morningSlote, $nightSlote);
echo "<br>spent in the morning: ".$output["morningSession"]." Hours";
echo "<br>spent in the night: ".$output["nightSession"]." Hours";
function getCorrectTimeslote($startDate, $endDate, $morningSlote, $nightSlote) {
$output = array();
$morningSloteStart = "";
$morningSloteEnd = "";
$nightSloteStart = "";
$nightSloteEnd = "";
$morningSloteExplodedResult = array();
if(strpos($morningSlote,"-") !== false) {
$morningSloteExplodedResult = explode("-",$morningSlote);
$morningSloteStart = date("m/d/Y H:i:s",strtotime(trim($morningSloteExplodedResult[0])));
$morningSloteEnd = date("m/d/Y H:i:s",strtotime(trim($morningSloteExplodedResult[1])));
}
$nightSloteExplodedResult = array();
if(strpos($nightSlote,"-") !== false) {
$nightSloteExplodedResult = explode("-",$nightSlote);
$nightSloteStart = date("m/d/Y H:i:s",strtotime(trim($nightSloteExplodedResult[0])));
$nightSloteEnd = date("m/d/Y H:i:s",strtotime("+1 day".trim($nightSloteExplodedResult[1])));
}
if((isset($morningSloteStart) && !empty($morningSloteStart)) && (isset($morningSloteEnd) && !empty($morningSloteEnd)) && (isset($nightSloteStart) && !empty($nightSloteStart)) && (isset($nightSloteEnd) && !empty($nightSloteEnd))) {
$morningSession = 0;
$nightSession = 0;
if($endDate >= $startDate) {
if($morningSloteStart >= $startDate) {
//No date will be changed
if($endDate > $nightSloteStart) {
//i.e. 2.30 AM - 11.30 PM
if($morningSloteStart > $startDate) {
$nightSession = ago($morningSloteStart,$startDate);
}
$morningSession = ago($morningSloteEnd,$morningSloteStart);
$nightSession += ago($endDate,$nightSloteStart);
} else if($endDate >= $morningSloteStart) {
//i.e. 2.30 AM - 6.30 AM
//i.e. 2.30 AM - 6.30 AM
$nightSession = ago($morningSloteStart,$startDate);
$morningSession = ago($endDate,$morningSloteStart);
} else {
$morningSession = 0;
$nightSession = ago($endDate,$startDate);
}
} else if($endDate >= $nightSloteEnd) {
//Date will be changed
if($morningSloteStart < $startDate && $endDate < $nightSloteStart) {
//23:30 - 22:30
$morningSloteStart = date("m/d/Y H:i:s", strtotime("+1 day".$morningSloteStart));
$morningSloteEnd = date("m/d/Y H:i:s", strtotime("+1 day".$morningSloteEnd));
$nightSloteStart = date("m/d/Y H:i:s", strtotime("+1 day".$nightSloteStart));
$nightSession = ago($morningSloteStart,$startDate);
$morningSession = ago($morningSloteStart,$morningSloteEnd);
$nightSession += ago($endDate,$nightSloteStart);
} else {
//Removing date addition
$endDate = date("m/d/Y H:i:s", strtotime("-1 day".$endDate));
//i.e. 11.30 PM - 6.00 AM && 6.00 AM - 6.20 PM
$nightSession = ago($startDate,$nightSloteEnd);
$morningSession = ago($endDate,$morningSloteStart);
}
} else {
if($startDate >= $morningSloteStart && $nightSloteStart >= $endDate) {
//i.e. 6.30 AM - 9.30 AM
$nightSession = 0;
$morningSession = ago($endDate,$startDate);
} else if($startDate >= $morningSloteStart && $nightSloteStart < $startDate) {
//i.e. 22.30 PM - 23.59
$nightSession = ago($startDate,$endDate);
$morningSession = 0;
} else if($startDate >= $morningSloteStart && $nightSloteStart < $endDate) {
//i.e. 5.30 PM - 23.59
$nightSession = ago($nightSloteStart,$endDate);
$morningSession = ago($startDate,$nightSloteStart);
} else {
//Date will be changed
//i.e. 11.30 PM - 6.00 AM && 6.00 AM - 2.30 AM
$morningSession = 0;
$nightSession = ago($endDate,$startDate);
}
}
}
}
$output["morningSession"] = $morningSession/60; //hours
$output["nightSession"] = $nightSession/60; //hours
return $output;
}
function ago($datetime1,$datetime2) {
$date1 = new DateTime($datetime1);
$date2 = new DateTime($datetime2);
$interval = $date1->diff($date2);
$minutes = 0;
if($interval->days >= 1) $minutes += $interval->days * 24 * 60;
if($interval->h >= 1) $minutes += $interval->h * 60;
if($interval->i >= 1) $minutes += $interval->i;
return $minutes;
}
?>
$time = array("18:10:00", "23:10:12", "10:05:00");
How to get the total time from this array. I need output like 51:25:12, Please help me
Try this short code:
It fill up your all case. Like as case:$a=array("18:30:00", "23:30:12", "10:05:00");.
function sum_time($array) {
$i = 0;
foreach ($array as $time) {
sscanf($time, '%d:%d:%d', $hour, $min,$sec);
$i += ($hour * 60 + $min)*60+$sec;
}
if ($h = floor($i / 3600)) {
$i %= 3600;
if ($m = floor($i / 60)) {
$i %= 60;
}
}
return sprintf('%02d:%02d:%02d', $h, $m,$i);
}
$a=array("18:30:00", "23:30:12", "10:05:00");
echo sum_time($a);
<?php
$time = array("18:10:00", "23:10:12", "10:05:00");
$hours=0;
$min=0;
$sec=0;
foreach($time as $time_array)
{
$time_exp=explode(':',$time_array);
$hours=$hours+$time_exp[0];
$min=$min+$time_exp[1];
$sec=$sec+$time_exp[2];
}
$time_output='';
$time_output=$hours.':'.$min.':'.$sec;
echo $time_output;
?>
// sample data
$time = array("18:50:00", "23:10:12", "10:05:00");
//variable initialization
$seconds = $mins = $hours = array();
//loop through all sample data items
foreach($time as $tk => $tv) {
//explode each item with seperator
$tv_parts = explode(":", $tv);
$seconds[] = $tv_parts['2'];
$mins[] = $tv_parts['1'];
$hours[] = $tv_parts['0'];
}
//add up all items respectively
$ts = array_sum($seconds);
$tm = array_sum($mins);
$th = array_sum($hours);
//adjust seconds if they are more than 59
if($ts > 59) {
$ts = $ts % 60;
$tm = $tm + floor($ts / 60);
}
//adjust minutes if they are more than 59
if($tm > 59) {
$tm = $tm % 60;
$th = $th + floor($tm / 60);
}
//padding for adjusting it to two digits when sum is below 10
$th = str_pad($th, 2, "0", STR_PAD_LEFT);
$tm = str_pad($tm, 2, "0", STR_PAD_LEFT);
$ts = str_pad($ts, 2, "0", STR_PAD_LEFT);
//final output
echo "$th:$tm:$ts";
You can refer more details about array_sum, floor and str_pad on official documentation site for PHP.
Easiest way to do this is as follows:
$time = array("18:10:00", "23:10:12", "10:05:00");
$sum="00:00:00";
$sum_new = explode(':',$sum);
foreach ($time as $t)
{
$time_new = explode(':',$t);
$sum_new[0]=$sum_new[0]+$time_new[0];
$sum_new[1]=$sum_new[1]+$time_new[1];
$sum_new[2]=$sum_new[2]+$time_new[2];
}
$sum = implode(':',$sum_new);
echo $sum;
First explode current date string via : and than just sum up parts. Don't forget to fix overflow of time parts:
function sum($times) {
$total = array(
'h' => 0,
'm' => 0,
's' => 0,
);
foreach ($times as $t) {
$timeArray = explode(":", $t);
$total['h'] += $timeArray[0];
$total['m'] += $timeArray[1];
$total['s'] += $timeArray[2];
}
if ($total['s'] >= 60) {
$total['m'] += $total['s'] % 60;
$intpart = floor($total['s']);
$total['s'] = $total['s'] - $intpart;
}
if ($total['m'] >= 60) {
$total['h'] += $total['m'] % 60;
$intpart = floor($total['m']);
$total['m'] = $total['m'] - $intpart;
}
return $total;
}
$totals = sum(array("18:10:00", "23:10:12", "10:05:00"));
echo implode(':', $totals);
Try this:
<?php
$time = array("18:10:00", "23:10:12", "10:05:00");
$seconds = 0;
foreach($time as $t)
{
$timeArr = array_reverse(explode(":", $t));
foreach ($timeArr as $key => $value)
{
if ($key > 2) break;
$seconds += pow(60, $key) * $value;
}
}
$hours = floor($seconds / 3600);
$mins = floor(($seconds - ($hours*3600)) / 60);
$secs = floor($seconds % 60);
echo $hours.':'.$mins.':'.$secs;
I need to add multiple time values as in Hours:mins, so I use
strtotime($value1) + strtotime($value2)
to add all of them, how do I put them back as hours:mins ?
cant use
date("h:i")
it only works if hours < 24.
I appreciate your help. Thanks
Here is an function that will sum all your time values in format HH:MM:
function sum_time() {
$i = 0;
foreach (func_get_args() as $time) {
sscanf($time, '%d:%d', $hour, $min);
$i += $hour * 60 + $min;
}
if ($h = floor($i / 60)) {
$i %= 60;
}
return sprintf('%02d:%02d', $h, $i);
}
// use example
echo sum_time('01:05', '00:02', '05:59'); # 07:06
demo
Try this :
function time_convert($s) {
$m = 0; $hr = 0; $td = "now";
if ($s > 59) {
$m = (int)($s/60);
$s = $s-($m*60); // sec left over
$td = "$m min";
}
if ($m > 59) {
$hr = (int)($m / 60);
$m = $m - ($hr*60); // min left over
$td = "$hr hr";
if ($hr > 1) {
$td .= "s";
}
if ($m > 0) {
$td .= ", $m min";
}
}
return $td;
}
And use it:
$time = (int) strtotime($v1) + strtotime($v2);
echo time_convert($time);
May it helps
The function strtotime() returns the time in seconds since January 1 1970 00:00:00 UTC. So adding the return value of this function might not do what you would expect.
Instead of using the date functions we can manipulate the string and perform some basic arithmetic operations:
<?php
$value1 = "12:44";
$value2 = "13:47";
$arr1 = explode(':', $value1);
$arr2 = explode(':', $value2);
$totalMinutes = (int)$arr1[0] * 60 + (int)$arr1[1] + (int)$arr2[0] * 60 + (int)$arr2[1];
$hours = (int) ($totalMinutes / 60);
$minutes = $totalMinutes % 60; // Modulus: remainder when dividing with 60
echo $hours . ':' . $minutes;
?>
Another way with DateTime
$dt1 = new DateTime($value1);
$dt2 = new DateTime($value2);
$interval = $dt1->diff($dt2);
echo $interval->format('%a day(s) %h hour(s) %i minute(s)') . '<br />';
echo ($interval->format('%a') * 24 + $interval->format('%h')) . ' hour(s) ';
echo $interval->format('%i minute(s)');
I use Codeigniter and it has the timespan() function that returns the time as 1 Year, 10 Months, 2 Weeks, 5 Days, 10 Hours, 16 Minutes.
What I'd like to do is only show the time formatted in x hours ago if the time is within the last 24 hours, otherwise just show a normal datetime.
I feel like there's got to be a function already made to do this but I haven't had any luck finding it.
This is the timespan function included with Codeigniter, how can I alter it?
/**
* Timespan
*
* Returns a span of seconds in this format:
* 10 days 14 hours 36 minutes 47 seconds
*
* #access public
* #param integer a number of seconds
* #param integer Unix timestamp
* #return integer
*/
if ( ! function_exists('timespan'))
{
function timespan($seconds = 1, $time = '')
{
$CI =& get_instance();
$CI->lang->load('date');
if ( ! is_numeric($seconds))
{
$seconds = 1;
}
if ( ! is_numeric($time))
{
$time = time();
}
if ($time <= $seconds)
{
$seconds = 1;
}
else
{
$seconds = $time - $seconds;
}
$str = '';
$years = floor($seconds / 31536000);
if ($years > 0)
{
$str .= $years.' '.$CI->lang->line((($years > 1) ? 'date_years' : 'date_year')).', ';
}
$seconds -= $years * 31536000;
$months = floor($seconds / 2628000);
if ($years > 0 OR $months > 0)
{
if ($months > 0)
{
$str .= $months.' '.$CI->lang->line((($months > 1) ? 'date_months' : 'date_month')).', ';
}
$seconds -= $months * 2628000;
}
$weeks = floor($seconds / 604800);
if ($years > 0 OR $months > 0 OR $weeks > 0)
{
if ($weeks > 0)
{
$str .= $weeks.' '.$CI->lang->line((($weeks > 1) ? 'date_weeks' : 'date_week')).', ';
}
$seconds -= $weeks * 604800;
}
$days = floor($seconds / 86400);
if ($months > 0 OR $weeks > 0 OR $days > 0)
{
if ($days > 0)
{
$str .= $days.' '.$CI->lang->line((($days > 1) ? 'date_days' : 'date_day')).', ';
}
$seconds -= $days * 86400;
}
$hours = floor($seconds / 3600);
if ($days > 0 OR $hours > 0)
{
if ($hours > 0)
{
$str .= $hours.' '.$CI->lang->line((($hours > 1) ? 'date_hours' : 'date_hour')).', ';
}
$seconds -= $hours * 3600;
}
$minutes = floor($seconds / 60);
if ($days > 0 OR $hours > 0 OR $minutes > 0)
{
if ($minutes > 0)
{
$str .= $minutes.' '.$CI->lang->line((($minutes > 1) ? 'date_minutes' : 'date_minute')).', ';
}
$seconds -= $minutes * 60;
}
if ($str == '')
{
$str .= $seconds.' '.$CI->lang->line((($seconds > 1) ? 'date_seconds' : 'date_second')).', ';
}
return substr(trim($str), 0, -1);
}
}
This function will accept a string, a numeric (unix) timestamp, or a DateTime object. It also accepts jQuery.now(). Time may be in the future or past.
function time_ago($time=false, $just_now=false) {
if ($time instanceOf DateTime)
$time = $time->getTimestamp();
elseif (is_numeric($time))
$time = date('m/d/y h:i A', $time);
if (strtotime($time) === false)
$time = date('m/d/y h:i A', time());
$interval = date_create($time)->diff(date_create('now'));
$adjective = strtotime($time) > time() ? 'from now' : 'ago';
return (
$interval->days > 0 ?
$time : (
$interval->h < 1 && $interval->i < 1 && $just_now ?
'just now' :
(
$interval->h > 1 ?
$interval->h.' hour'.(
$interval->h > 1 ?
's' :
''
).' ago' :
$interval->i.' minutes'.' '.$adjective
)
)
);
}
echo time_ago('8/22/2012 5:00 PM'); // 3 hours ago
echo time_ago('8/21/2012 5:00 PM'); // 8/21/2012 5:00 PM
echo time_ago(time()); // 0 hours ago
echo time_ago(time(), true); // just now
echo time_ago(strtotime('5 days ago')); // 08/17/12 08:18 PM
echo time_ago(strtotime('5 hours ago')); // 5 hours ago
echo time_ago(strtotime('5 minutes ago')); // 5 minutes ago
echo time_ago(strtotime('+5 minutes')); // 5 minutes from now
echo time_ago('jQuery.now()', true); // just now
echo time_ago('sweet explosions, bro!', true); // just now
Documentation
date - http://php.net/manual/en/function.date.php
DateTime object - http://www.php.net/manual/en/book.datetime.php
DateInterval object - http://www.php.net/manual/en/class.dateinterval.php
is_numeric - http://php.net/manual/en/function.is-numeric.php
if( time() - $yourTime <= 86400 ) { // 86400 seconds in a day
echo timespan($yourTime);
} else {
echo date('m/d/Y \a\t H:i:s', $yourTime);
}
Don't rely on a framework, especially a bad one, for everything!
Fiddle with $format to suit your needs. Will accept almost anything as input.
<?php
/**
* RelativeTime - pretty printed
* #author Dejan Marjanovic
*/
class Site5_RelativeTime
{
private $interval = '';
public function __construct()
{
call_user_func_array(array($this, 'calculate'), func_get_args());
}
public function calculate($start, $end = NULL)
{
if ( empty($start))
return false;
if (empty($end))
$end = time();
if ( ! is_numeric($start))
$start = strtotime($start);
if ( ! is_numeric($end))
$end = strtotime($end);
if($start > $end)
$future = TRUE;
$start = '#' . $start;
$end = '#' . $end;
if ( ! ($start instanceof DateTime))
$start = new DateTime($start);
if ($end === null)
$end = new DateTime();
if ( ! ($end instanceof DateTime))
$end = new DateTime($end);
$interval = $end->diff($start);
$get_plural = function($int, $str)
{
return $int > 1? $str.'s': $str;
};
$format = array();
if ($interval->y !== 0)
$format[] = "%y " . $get_plural($interval->y, "year");
if ($interval->m !== 0)
$format[] = "%m " . $get_plural($interval->m, "month");
if ($interval->d !== 0)
$format[] = "%d " . $get_plural($interval->d, "day");
if ($interval->h !== 0)
$format[] = "%h " . $get_plural($interval->h, "hour");
if ($interval->i !== 0)
$format[] = "%i " . $get_plural($interval->i, "minute");
if ($interval->s !== 0)
{
if ( ! count($format))
{
$this->interval = "less than a minute";
return;
}
else
{
$format[] = "%s " . $get_plural($interval->s, "second");
}
}
if (count($format) > 1)
{
$format = array_shift($format) . " and " . array_shift($format);
}
else
{
$format = array_pop($format);
}
$tense = ($future === TRUE)? 'from now': 'ago';
$this->interval = $interval->format($format) . ' ' . $tense;
}
public function __toString()
{
return $this->interval;
}
}
How can I calculate the number of Saturdays and Sundays between two dates in php?
Is there any inbuilt function for that purpose?
There is a related question here already, Calculate business days
You can use this to subtract from 7 to get the weekend days, or similar.
I don't think there is a built in for that, but this should do the job :
$startTime = START_TIMESTAMP;
$endTime = END_TIMESTAMP;
$time = $startTime;
$count = 0;
while(date('w', $time) != 0) { // 0 (for Sunday) through 6 (for Saturday)
$time += 86400;
}
while($time < $endTime) {
$count++;
$time += 7 * 86400;
}
Let us all KISS (Keep It Simple Stupid). Why make it so complicated?
function countWeekendDays($start, $end)
{
// $start in timestamp
// $end in timestamp
$iter = 24*60*60; // whole day in seconds
$count = 0; // keep a count of Sats & Suns
for($i = $start; $i <= $end; $i=$i+$iter)
{
if(Date('D',$i) == 'Sat' || Date('D',$i) == 'Sun')
{
$count++;
}
}
return $count;
}
You can calculate it mathematically like this - Based on Roland's Answer
private function getNumberOfWeekendDays(\DateTimeInterface $startDate, \DateTimeInterface $endDate): int
{
$startNumber = (int) $startDate->format('N');
$endNumber = (int) $endDate->format('N');
$daysBetweenStartAndEnd = $endDate->diff($startDate)->d;
$weekendDays = (int) (2 * ($daysBetweenStartAndEnd + $startNumber) / 7);
$weekendDays = $weekendDays - ($startNumber == 7 ? 1 : 0) - ($endNumber == 7 ? 1 : 0);
return $weekendDays;
}
<?php
date_default_timezone_set("Europe/Lisbon");
$d1 = new DateTime("2009-06-01"); /* inclusive */
$d2 = new DateTime("2009-07-01"); /* exclusive */
$interval = $d2->diff($d1);
$number_of_days = $interval->format("%d");
$number_of_weekends = $number_of_days / 7;
$remainder = $number_of_days % 7;
if ($remainder >=2 && $d1->format("D") == "Sat")
$number_of_weekends++;
elseif ($d1->format("w") + $remainder >= 8)
$number_of_weekends++;
I may have missed by one in the last condition, be sure to check it with different starting dates. (Feel free to edit this answer if you spot an error).
there's definitely no built in function for that but you can use strtotime to loop days
$start = strtotime('2010-01-01');
$end = strtotime('2010-01-09');
function numWeekdays( $start_ts, $end_ts, $day, $include_start_end = false ) {
$day = strtolower( $day );
$current_ts = $start_ts;
// loop next $day until timestamp past $end_ts
while( $current_ts < $end_ts ) {
if( ( $current_ts = strtotime( 'next '.$day, $current_ts ) ) < $end_ts) {
$days++;
}
}
// include start/end days
if ( $include_start_end ) {
if ( strtolower( date( 'l', $start_ts ) ) == $day ) {
$days++;
}
if ( strtolower( date( 'l', $end_ts ) ) == $day ) {
$days++;
}
}
return (int)$days;
}
echo numWeekDays( $start, $end, 'saturday', false );
I searched for awhile for a simple solution that worked and decided to write my own and came up with this
$start = date('Y-m-d');
$end = date('Y-m-d', strtotime($start.' +1 year'));
$current = $start;
$count = 0;
while($current != $end){
if(date('l', strtotime($current)) == 'Saturday'){
$count++;
}
$current = date('Y-m-d', strtotime($current.' +1 day'));
};
echo $count;