Date difference with leap year - php

I have 5 different schedules for 5 weeks:
first week = Monday to Friday (8am to 5pm) && Rest days on Saturday and Sunday
second week = Monday to Friday (10am to 6pm) && Rest days on Saturday and Sunday
third week = Monday to Friday (11am to 7pm) && Rest days on Saturday and Sunday
fourth week = Monday Rest Day && Tuesday to Saturday (10:30 am to 6:30pm) && Sunday Rest Day
fifth week = Monday Rest Day && Tuesday to Saturday (8:30 am to 5:30pm) && Sunday Rest Day
Base on my calculation array [0],[0] which is Monday of first week is set to April 25, 2011.
I have this code to compute the difference between input date and start date, which is April 25, 2011.
$tdays = floor((strtotime($date2) - strtotime($date1))/86400);
I could now compute my work schedule starting April of 2011 up until February of 2012.
However if I enter a date beyond February 2012, the output is wrong due to leap year. Is there a technique for this?

If you are able to make use of php 5.3 you should use date_diff()
or try something like this :
<?php
function dateDifference($startDate, $endDate)
{
$startDate = strtotime($startDate);
$endDate = strtotime($endDate);
if ($startDate === false || $startDate < 0 || $endDate === false || $endDate < 0 || $startDate > $endDate)
return false;
$years = date('Y', $endDate) - date('Y', $startDate);
$endMonth = date('m', $endDate);
$startMonth = date('m', $startDate);
// Calculate months
$months = $endMonth - $startMonth;
if ($months <= 0) {
$months += 12;
$years--;
}
if ($years < 0)
return false;
// Calculate the days
$offsets = array();
if ($years > 0)
$offsets[] = $years . (($years == 1) ? ' year' : ' years');
if ($months > 0)
$offsets[] = $months . (($months == 1) ? ' month' : ' months');
$offsets = count($offsets) > 0 ? '+' . implode(' ', $offsets) : 'now';
$days = $endDate - strtotime($offsets, $startDate);
$days = date('z', $days);
return array($years, $months, $days);
}
?>

Related

Divide days into week day using Carbon excluding Saturday and Sunday

I have days in a month that excluded saturday and sunday. How to divide the range of the days into weeks? If it start with friday, then first week only friday.
you can do it like this
for ($i = 0; $i <= 4; $i++) {
$k = $i - 1;
$from_text = strtotime("this week thursday -$i week");
$to_text = strtotime("-$k week -1 day");
$ymd_week_range = date('Y-m-d', $from_text) . ',' . date('Y-m-d', $to_text);
$day_from = date('j', $from_text);
$day_to = date('j', $to_text);
$month_from = date('M', $from_text);
$month_to = date('M', $to_text);
$year_from = date('Y', $from_text);
$year_to = date('Y', $to_text);
$weeks[$ymd_week_range] = "$month_from $day_from - $month_to $day_to, $year_to";
}

How to show week list for the specific date and week start from sunday

I have week list dates logic from the specific date which returns following results.
12/05/2016 Monday
12/06/2016 Tuesday
12/07/2016 Wednesday
12/08/2016 Thursday
12/09/2016 Friday
12/10/2016 Saturday
12/11/2016 Sunday
Logic:
// set current date
$date = '12/08/2016';
// parse about any English textual datetime description into a Unix timestamp
$ts = strtotime($date);
// calculate the number of days since Monday
$dow = date('w', $ts);
$offset = $dow - 1;
if ($offset < 0) {
$offset = 6;
}
// calculate timestamp for the Monday
$ts = $ts - $offset*86400;
// loop from Monday till Sunday
for ($i = 0; $i < 7; $i++, $ts += 86400){
print date("m/d/Y l", $ts) . "\n";
echo "<br>";
}
Currently getting days from Monday to Sunday but don't know how to start a week from Sunday?
Replace "1" with "0".
$offset = $dow - 0;

PHP - How to calculate one month or one year later

I'd like to calculate next billing date of Recurly plan in PHP.
There are 2 types of billing cycle: yearly | monthly.
I tried to use DateTime and DateInterval classes, but didn't get expected results.
<?php
$referenceTime = new \DateTime('2016-01-31');
$oneMonthLater = $referenceTime->modify('+1 month');
var_dump($oneMonthLater);
// public 'date' => string '2016-03-02 00:00:00.000000'
Adding one month to the 31st of Januray gives me the second of March and not the 29th (or 28th) of February as I would expect.
The same for the 31st of August:
<?php
$referenceTime = new \DateTime('2016-08-31');
$oneMonthLater = $referenceTime->modify('+1 month');
var_dump($oneMonthLater);
// public 'date' => string '2016-10-01 00:00:00.000000'
If yearly, I expect Feb 29, 2016 + 1 year => Feb 28, 2017
Thanks.
Try this, if date > 28 use last day of next month else use +1 month
$get_date = strtotime("31-01-2016");
$dt = explode("-",$get_date);
$dt = $dt[0];
var_dump(($dt > 28) ? date("d-m-Y", strtotime("31-01-2016 last day of next month")) : date("d-m-Y", strtotime("31-01-2016 +1 month")));
DEMO
You can call modify with PHP's DateTime object to calculate the next date relative to the current date. The following code shows how you would do it with your specific situation.
$next_bill_date = new DateTime();
switch($plan_interval_unit) {
case "year":
$next_bill_date->modify("last day of next month");
break;
case "month":
$next_bill_date->modify("last day of this month next year");
break;
}
May be something like that:
if (date('d') !== date('d', strtotime('+1 month'))
date ('Y-m-d H:i:s', strtotime('last day of next month'));
if (date('d') !== date('d', strtotime('+1 year'))
date ('Y-m-d H:i:s', strtotime('last day of this month next year'));
You can use PHP inbuilt strtotime() function
// One month from today
$date = date('Y-m-d', strtotime('+1 month'));
// One month from a specific date
$date = date('Y-m-d', strtotime('+1 month', strtotime('2016-12-06')));
function get_next_billing_date($now, $type, $format = 'Y-m-d')
{
$date = new DateTime($now);
$y = $date->format("Y");
$m = $date->format("m");
$d = $date->format("d");
if ($type == 'year') {
$y++;
if ($m == 2 && $d == 29) {
$d = 28;
}
} else if ($type == 'month') {
if ($m == 12) {
$y++;
$m = 1;
} else {
$m++;
}
$first_date = sprintf("%04d-%02d-01", $y, $m);
$last_day_of_next_month = date('t', strtotime($first_date));
if ($d > $last_day_of_next_month) {
$d = $last_day_of_next_month;
}
} else {
// not supported
return false;
}
$date->setDate($y, $m, $d);
return $date->format($format);
}

PHP. How to get a list of week days of selected month?

I have code which returns number of business days in selected month/years. I need to get a list of week days to control It, for example:
if (friday) {
$i = 1;
}
if (thursday) {
$i = 0;
}
And code which I use for calculating weekdays:
<?php
//The function returns the no. of business days between two dates and it skips the holidays
function getWorkingDays($startDate,$endDate,$holidays){
// do strtotime calculations just once
$endDate = strtotime($endDate);
$startDate = strtotime($startDate);
//The total number of days between the two dates. We compute the no. of seconds and divide it to 60*60*24
//We add one to inlude both dates in the interval.
$days = ($endDate - $startDate) / 86400 + 1;
$no_full_weeks = floor($days / 7);
$no_remaining_days = fmod($days, 7);
//It will return 1 if it's Monday,.. ,7 for Sunday
$the_first_day_of_week = date("N", $startDate);
$the_last_day_of_week = date("N", $endDate);
//---->The two can be equal in leap years when february has 29 days, the equal sign is added here
//In the first case the whole interval is within a week, in the second case the interval falls in two weeks.
if ($the_first_day_of_week <= $the_last_day_of_week) {
if ($the_first_day_of_week <= 6 && 6 <= $the_last_day_of_week) $no_remaining_days--;
if ($the_first_day_of_week <= 7 && 7 <= $the_last_day_of_week) $no_remaining_days--;
}
else {
// (edit by Tokes to fix an edge case where the start day was a Sunday
// and the end day was NOT a Saturday)
// the day of the week for start is later than the day of the week for end
if ($the_first_day_of_week == 7) {
// if the start date is a Sunday, then we definitely subtract 1 day
$no_remaining_days--;
if ($the_last_day_of_week == 6) {
// if the end date is a Saturday, then we subtract another day
$no_remaining_days--;
}
}
else {
// the start date was a Saturday (or earlier), and the end date was (Mon..Fri)
// so we skip an entire weekend and subtract 2 days
$no_remaining_days -= 2;
}
}
//The no. of business days is: (number of weeks between the two dates) * (5 working days) + the remainder
//---->february in none leap years gave a remainder of 0 but still calculated weekends between first and last day, this is one way to fix it
$workingDays = $no_full_weeks * 5;
if ($no_remaining_days > 0 )
{
$workingDays += $no_remaining_days;
}
//We subtract the holidays
foreach($holidays as $holiday){
$time_stamp=strtotime($holiday);
//If the holiday doesn't fall in weekend
if ($startDate <= $time_stamp && $time_stamp <= $endDate && date("N",$time_stamp) != 6 && date("N",$time_stamp) != 7)
$workingDays--;
}
return $workingDays;
}
//Example:
$holidays=array("2008-12-25","2008-12-26","2009-01-01");
echo getWorkingDays("2008-12-22","2009-01-02",$holidays)
// => will return 7
?>
Is It possible to make It? Thank you for answers.
You can try something like below:
$startDate = new DateTime( '2013-04-01' ); //intialize start date
$endDate = new DateTime( '2013-04-30' ); //initialize end date
$holiday = array('2013-04-11','2013-04-25'); //this is assumed list of holiday
$interval = new DateInterval('P1D'); // set the interval as 1 day
$daterange = new DatePeriod($startDate, $interval ,$endDate);
$i = 0;
foreach($daterange as $date){
if($date->format("N") == 5) // OR if($date->format("l") == "Friday")
$i++;
}
echo $i;
try this, it increase $i on every occurrence of Friday between two dates
$startdate ="2008-12-22";
$enddate="2009-01-22";
$i=0;
while($startdate <= $enddate)
{
$startdate = date("Y-m-d", strtotime("+1 day", strtotime($startdate)));
$day = date("d",strtotime($startdate));
$month = date("m",strtotime($startdate));
$year = date("Y",strtotime($startdate));
if(date("l", mktime(0, 0, 0, $month, $day, $year)) == "Friday" )
{
echo $day."-".$month."-".$year." is ".date("l", mktime(0, 0, 0, $month, $day, $year))."\n" ;
$i++; \\ increase $i on every occurrence of Friday
}
}
Demo

Given a day and month, return the most recent date of that day and month in the form day-month-year

Given a date like "4 May", how do I get the most recent 4th May in the format "4 May, 2010"?
If the day/month combination has not yet occurred this year, it should show the date for last year (e.g. "31 December" should translate to "31 December, 2009").
Try something like this:
$cmpDate = strtotime('March 15');
$cmpDay = date('d',$cmpDate);
$cmpMonth = date('m',$cmpDate);
$currentDay = date('d');
$currentMonth = date('m');
if(($currentDay > $cmpDay && $currentMonth == $cmpMonth) || ($cmpMonth > $currentMonth) {
// Add one year
}
my tip is to use date('z') (= day of the year) for comparisons
$date = '11 Aug';
$ts = strtotime($date);
$recent = date('z', $ts) <= date('z') ? $ts : strtotime("$date previous year");
Try this (this is psuedo-code):
<?php
$currMonth = (int)date("m");
$currentDate = (int)date("d");
$currentYear = (int)date("Y");
// extract date and month from given date as needed,
// call it $givenMonth, $givenDate
if (($givenMonth <= $currMonth) && ($givenDate <= $givenDate)) {
$givenYear = $currentYear;
}
else {
$givenYear = $currYear - 1;
}
echo "Given date is: " + $currentMonth + "/" + $currentDate + "/" + $currentYear;
?>
function recentizer($date) {
$year = date('Y', time());
return (strtotime($date) < time()) ?
$date . ' ' . $year : $date . ' ' . ($year-1);
}
Example:
$dates = array('4 May', '6 February', '23 December');
foreach ($dates as $date) {
echo recentizer($date) . "\n";
}
Outputs:
4 May 2010
6 February 2010
23 December 2009
You can use this function:
echo date('m/d/y',strtotime('5 Sep',strtotime('-1 year'.str_repeat(' +1 year',(time()-strtotime('5 Sep'))/abs(time()-strtotime('5 Sep')) ) )) );
and change '5 Sep' to whatever date you want.
It works by setting the base year in strtotime to the current prior year (ie, '-1 year'), and then adjusts back to the current year (ie '+1 year') if the current time is greater than the time provided in your string.

Categories