datetime: split a month 10-day periods - php
I send a earlier date and it returns me the periods between the earlier date and today cut by tens of days.
Example with 14/01/2016
I need the result to be exactly as below:
11 Jan 2016 to 20 Jan 2016
21 Jan 2016 to 31 Jan 2016
01 Feb 2016 to 10 Feb 2016
11 Feb 2016 to 20 Feb 2016
21 Feb 2016 to 29 Feb 2016
01 Mar 2016 to 10 Mar 2016
11 Mar 2016 to 20 Mar 2016
21 Mar 2016 to 31 Mar 2016
01 Apr 2016 to 10 Apr 2016
11 Apr 2016 to 20 Apr 2016
Here my code:
function date_interval($startTime = false){
if( ! $startTime){
return array();
} else {
if(date('d',$startTime) < 10){
$actual = mktime(0, 0, 0, date('m',$startTime), 1, date('Y',$startTime));
} elseif(date('d',$startTime) < 20){
$actual = mktime(0, 0, 0, date('m',$startTime), 10, date('Y',$startTime));
} else {
$actual = mktime(0, 0, 0, date('m',$startTime), 20, date('Y',$startTime));
}
if(date('d',time()) < 10) {
$target = mktime(0, 0, 0, date('m',time()), 10, date('Y',time()));
} elseif(date('d',time()) < 20) {
$target = mktime(0, 0, 0, date('m',time()), 20, date('Y',time()));
} else {
$target = mktime(0, 0, 0, date('m',time())+1, 1, date('Y',time()));
}
$current = $actual;
$last = $actual;
while($current < $target) {
if(date('d',$current) < 10){
$current = mktime(0, 0, 0, date('m',$current), 10, date('Y',$current));
} elseif(date('d',$current) < 20){
$current = mktime(0, 0, 0, date('m',$current), 20, date('Y',$current));
} else {
$current = mktime(0, 0, 0, date('m',$current)+1, 1, date('Y',$current));
}
$dateTime[date("Y-m-d", $last) .'~'. date("Y-m-d", $current)] = date('d M Y',$last) . ' - ' . date('d M Y',$current));
$last = $current;
}
}
return $dateTime;
}
Datetime is the darling class from php that solves this type of problem nicely.
Here you feed the startdate to the function as DATETIME object and the function throws back a stack of list tags.
In the loop startDay is beeing modyfied first by adding 10 days to make the jump and then by one to avoid the overlap.
If you want a final line with the (less then ten days) time period from last startDay till today you can add something like:
$return .= '<li>From '.$startDay->format('d M Y').' to '.$today->format('d M Y').'</li>';
after the loop
function date_interval(DATETIME $startDay = NULL)
{
if( NULL == $startDay){
return array(); }
$return = '';
$today = new DATETIME('now');
while( $today->diff( $startDay )->format('%a%') > 10 )
{
$return .= '<li>From '.$startDay->format('d M Y').' to ';
$startDay->modify('+10 days');
$return .= $startDay->format('d M Y').'</li>
';
$startDay->modify('+1 day');
}
return $return;
}
I altered the above more general solution to do exactly what you describe:
<?php
function date_interval(DATETIME $startDay = NULL)
{
if( NULL == $startDay){
return array(); }
$return = '';
$today = new DATETIME('now');
$startMonth = new DateTime('first day of '.$startDay->format('M Y') );
$firstRun = TRUE;
while( $today > $startDay )
{
$return .= '<li>From '.$startDay->format('d M Y').' to ';
if( $firstRun == TRUE ){
if( (int)$startDay->format('d') > 10 )
$startMonth->modify('+10 days');
if( (int)$startDay->format('d') > 20 )
$startMonth->modify('+10 days');
$startDay = $startMonth;
$firstRun = FALSE;
}
$lastOfMonth = new DateTime('last day of '.$startDay->format('M Y') );
if( $lastOfMonth->diff( $startDay )->format('%a%') > 10 )
$startDay->modify('+9 days');
else
$startDay = $lastOfMonth;
$return .= $startDay->format('d M Y').'</li>
';
$startDay->modify('+1 day');
}
return $return;
}
echo date_interval( date_create_from_format('Y-m-d','2016-01-21') )."\n";
?>
See this function using DateTime:
function date_interval( $start = Null )
{
if( !$start ) return array();
$cur = new DateTime( sprintf( '%s-%02d', $start->format('Y-m'), [1,11,21,21][ floor(($start->format('j')-1)/10) ] ) );
$end = new DateTime();
$retval = [];
while( $cur <= $end )
{
$key = $cur->format( 'Y-m-d~' );
$val = $cur->format( 'd M Y - ' );
if( $cur->format( 'j' ) > 20 ) $cur->modify( 'last day of this month' );
else $cur->modify( '+ 9 days' );
$retval[ $key.$cur->format( 'Y-m-d' ) ] = $val.$cur->format( 'd M Y' );
$cur->modify( '+ 1 days' );
}
return $retval;
}
Calling it in this way:
$startDate = '14/01/2016';
$array = date_interval( DateTime::createFromFormat( 'd/m/Y', $startDate ) );
print_r( $array );
According with your keys/values schema, the resulting array is:
Array
(
[2016-01-11~2016-01-20] => 11 Jan 2016 - 20 Jan 2016
[2016-01-21~2016-01-31] => 21 Jan 2016 - 31 Jan 2016
[2016-02-01~2016-02-10] => 01 Feb 2016 - 10 Feb 2016
[2016-02-11~2016-02-20] => 11 Feb 2016 - 20 Feb 2016
[2016-02-21~2016-02-29] => 21 Feb 2016 - 29 Feb 2016
[2016-03-01~2016-03-10] => 01 Mar 2016 - 10 Mar 2016
[2016-03-11~2016-03-20] => 11 Mar 2016 - 20 Mar 2016
[2016-03-21~2016-03-31] => 21 Mar 2016 - 31 Mar 2016
[2016-04-01~2016-04-10] => 01 Apr 2016 - 10 Apr 2016
[2016-04-11~2016-04-20] => 11 Apr 2016 - 20 Apr 2016
[2016-04-21~2016-04-30] => 21 Apr 2016 - 30 Apr 2016
)
We operate only on one date ($cur), initially created from passed argument; we set the day of month using array [1,11,21,21] and selecting key by the rounded down division by 10 of original day (in your example, (14-1)/10 = 1.3, rounded as 1, that is 11 in [1,11,21,21] array). This is a quick way to resolve the 31th day exception.
Then we perform a loop until $cur date is greater than today date: we create starting part of key and value, we modify $cur adding it nine days or selecting last month's day, we create complete key and value of returned array. At the end of each loop, we increment $cur by 1 day.
Related
Given start date get all the months name until current month?
Given start date how to get all the months until current month? For eg. If given date is 1st Jan 2019 output should be: Jan 2019 Feb 2019 Mar 2019 Apr 2019 May 2019 Jun 2019 Jul 2019 Aug 2019 Sep 2019 Oct 2019 Nov 2019 Dec 2019 Jan 2020 Feb 2020 Mar 2020 Solved it with slightly different approach. Thank you all for hints and answers. <?php $startTime = strtotime("1 January 2019"); $startYear = date("Y", $startTime); $currentYear = date("Y"); $yearDiff = $currentYear - $startYear; $currentMonth = date("m", time()); for($i=0; $i < intval($currentMonth) + ($yearDiff * 12) ; $i++) { $t = strtotime("+". $i . " months", $startTime); $monthName = date("M", $t) ." ". date('Y', $t); echo $monthName . "<br/>\n"; } ?>
here you go , hope this work $start = new DateTime('2019-01-01'); $end = new DateTime('2020-03-02'); $interval = DateInterval::createFromDateString('1 month'); $period = new DatePeriod($start, $interval, $end); foreach ($period as $dt) { echo $dt->format("F Y") . "<br>\n"; }
Laravel - add new data into result
I have this function to get all max-offers from maxoffers table: public function maxoffers($id) { $offers = Maxoffer::where('article_id', $id)->latest()->get(['id', 'price', 'start', 'user_id']); return $offers; } and I get this: [{"id":121,"price":67,"start":"Sat, 23 Apr 2016 00:00:00 +0000","user_id":8},{"id":114,"price":45,"start":"Sun, 08 May 2016 00:00:00 +0000","user_id":9},{"id":113,"price":53,"start":"Sun, 24 Apr 2016 00:00:00 +0000","user_id":8},{"id":111,"price":55,"start":"Wed, 01 Jun 2016 00:00:00 +0000","user_id":11},{"id":110,"price":53,"start":"Fri, 03 Jun 2016 00:00:00 +0000","user_id":8},{"id":107,"price":53,"start":"Wed, 03 Aug 2016 00:00:00 +0000","user_id":8},{"id":106,"price":53,"start":"Mon, 01 Aug 2016 00:00:00 +0000","user_id":8},{"id":105,"price":53,"start":"Tue, 16 Aug 2016 00:00:00 +0000","user_id":8},{"id":104,"price":55,"start":"Thu, 21 Apr 2016 00:00:00 +0000","user_id":11},{"id":101,"price":57,"start":"Wed, 17 Aug 2016 00:00:00 +0000","user_id":8}] Now I have also: $start = 'Sun, 03 Apr 2016 00:00:00'; $end = 'Sat, 23 Sep 2016 00:00:01'; I need to go through $maxoffers from $start date to $end date day by day. If there is no date for that day, I need to add a new object into $maxoffers with the following data: {"title":,"price":100,"start":"DATE_WHICH_NOT_EXCIST INTO_OFFERS","user_id":8} So how I can go through $maxoffers and if there is not some date in period from $start to $end then to add new data to result? UPDATE: I try: public function maxoffers($id) { $start_date = ; $end_date = ; $offers = Maxoffer::where('article_id', $id) ->where('start', '>=', $start_date) ->where('start', '<=', $end_date) ->get(['id', 'price', 'start', 'user_id']); $start_date = 'Sun, 03 Apr 2016 00:00:00'; $end_date = 'Sat, 23 Sep 2016 00:00:00'; while (strtotime($start_date) <= strtotime($end_date)) { $start_date = date ("Y-m-d", strtotime("+1 day", strtotime($start_date))); $count = 0; foreach($offers as $offer) { if(strtotime($offer->start) == strtotime($start_date)) { $count++; } } if($count == 0) { Maxoffer::create(['title' => null, 'price' => '100', 'start' => $start_date, 'user_id' => 8 ]); } } // do some code to update $offers variable before you return it return $offers; } but give me this error:
It is ver simple. YOu just need to use Carbon for date manipulation. $offers = []; //for example I am using an empty array $start_date = \Carbon\Carbon::parse('Sun, 03 Apr 2016 00:00:00'); $end_date = \Carbon\Carbon::parse('Sat, 23 Sep 2016 00:00:00'); while(!$start_date->eq($end_date)) { $flag = true; foreach ($offers as $offer) { if ($offer['start'] == $start_date->toRfc2822String()) { $flag = false; break; } } if($flag) { $temp = []; $temp['title'] = "Title "; $temp['price'] = "100"; $temp['start'] = $start_date->toDateString(); $temp['user_id'] = 8; array_push($offers,$temp); } $start_date->addDay(); } Here Just Pass the valid format of date for $start_date and $end_date. In your case it is valid so no problem there. Now use eq() method for date comparison and add one day for every iteration. I used $temp as an example. You can define this array's values and keys as you want. Since you are not using collection you need to iterate to each element in array to see if that date exists or not.
Inserting a loop into a loop?
How do I get my output to look like this with the Week number inserted? Week 1 Monday, January 18, 2016 Wednesday, January 20, 2016 Friday, January 22, 2016 Week 2 Monday, January 25, 2016 Wednesday, January 27, 2016 Friday, January 29, 2016 Week 3 Monday, February 01, 2016 Wednesday, February 03, 2016 Friday, February 05, 2016 Here is my code: $d = new DateTime('2016-01-17'); $inc = new DateInterval('P1D'); $dateOptions = ''; $required = array(1,3,5); for ($i=0; $i<28; ++$i) { $d = $d->add($inc); if (in_array($d->format('w'), $required)) { $t = $d->format('l, F d, Y'); echo "$t<br \>"; } } Thanks in advance.
$d = new DateTime('2016-01-17'); $inc = new DateInterval('P1D'); $dateOptions = ''; $required = array(1,3,5); $j = 1; for ($i = 0; $i <28; ++$i) { $d = $d->add($inc); if($d->format('w') == 1){ echo 'Week '.$j.PHP_EOL; $j++; } if (in_array($d->format('w'), $required)) { $t = $d->format('l, F d, Y'); echo $t.PHP_EOL; } }
This should do what you want... $d = new DateTime('2016-01-17'); $inc = new DateInterval('P1D'); $dateOptions = ''; $required = array(1,3,5); $week = null; $week_no = 0; for ($i=0; $i<28; ++$i) { $d = $d->add($inc); if (in_array($d->format('w'), $required)) { if($week!=$d->format('W')){ $week_no++; $week = $d->format('W'); echo "Week $week_no<br \>"; } $t = $d->format('l, F d, Y'); echo "$t<br \>"; } } The $week variable keeps track of the dates Week number (from the PHP date() function). The $week_no keeps track of your incremental number of weeks starting at 1. The if statement check to see if the the current week number is different to the previous weeks ($week). If it's different it adds 1 to your $week_no a is different to the previous
You can do something like this: $d = new DateTime('2016-01-17'); $inc = new DateInterval('P1D'); $dateOptions = ''; $required = array(1,3,5); $counter = $week = 0; for ($i=0; $i<28; ++$i){ $d = $d->add($inc); if (in_array($d->format('w'), $required)) { if($counter % 3 == 0){ echo "Week " . ($week + 1) . "<br />"; ++$week; } $t = $d->format('l, F d, Y'); echo $t . "<br />"; ++$counter; } } Output: Week 1 Monday, January 18, 2016 Wednesday, January 20, 2016 Friday, January 22, 2016 Week 2 Monday, January 25, 2016 Wednesday, January 27, 2016 Friday, January 29, 2016 Week 3 Monday, February 01, 2016 Wednesday, February 03, 2016 Friday, February 05, 2016 Week 4 Monday, February 08, 2016 Wednesday, February 10, 2016 Friday, February 12, 2016 $counter will keep track of number of dates being printed and $week will print the week number after every three dates.
check http://php.net/manual/en/function.date.php W => ISO-8601 week number of year, weeks starting on Monday (added in PHP 4.1.0) you just need to add this if before the date printing if ($d->format('w') == 1){ echo "Week " . $d->format('W') . "<br \>"; } something like this will do the trick $d = new DateTime('2016-01-17'); $inc = new DateInterval('P1D'); $dateOptions = ''; $required = array(1,3,5); for ($i=0; $i<28; ++$i) { $d = $d->add($inc); if ($d->format('w') == 1){ echo "Week " . $d->format('W') . "<br \>"; } if (in_array($d->format('w'), $required)) { $t = $d->format('l, F d, Y'); echo "$t<br \>"; } } Output: Week 01 Monday, January 18, 2016 Wednesday, January 20, 2016 Friday, January 22, 2016 Week 02 Monday, January 25, 2016 Wednesday, January 27, 2016 Friday, January 29, 2016 Week 03 Monday, February 01, 2016 Wednesday, February 03, 2016 Friday, February 05, 2016 Week 04 Monday, February 08, 2016 Wednesday, February 10, 2016 Friday, February 12, 2016
Try with this code. $d = new DateTime('2016-01-17'); $inc = new DateInterval('P1D'); $dateOptions = ''; $required = array(1,3,5); $counter = $week = 0; for ($i=0; $i<21; ++$i){ $d = $d->add($inc); if (in_array($d->format('w'), $required)) { if($counter % 3 == 0){ $week_num = $week + 1; echo "Week $week_num<br />"; ++$week; } $t = $d->format('l, F d, Y'); echo "$t<br />"; ++$counter; } } Output Week 1 Monday, January 18, 2016 Wednesday, January 20, 2016 Friday, January 22, 2016 Week 2 Monday, January 25, 2016 Wednesday, January 27, 2016 Friday, January 29, 2016 Week 3 Monday, February 01, 2016 Wednesday, February 03, 2016 Friday, February 05, 2016
How to show the past 24 months from now?
I need to write a simple loop routine to show 24 months back starting with today's month. How would I do that? $start = date(M) - 24; $end = date(M); foreach() { echo ''; // Dec, Jan... }
Something like this should work: for($i = 1; $i <= 24; $i++) { echo date("M", strtotime("-$i months")) . "\n"; } Result Feb Jan Dec Nov Oct Sep Aug Jul Jun May Apr Mar Feb Jan Dec Nov Oct Sep Aug Jul Jun May Apr Mar See a demo
for ($i = 1; $i <= 24; $i++) { $months[] = date("Y-m%", strtotime( date( 'Y-m-01' )." -$i months")); } or for full textual representation of month you need to pass "F": echo date("y:F:d"); for previous month you can use echo date("y:F:d",strtotime("-24 Months"))
echo the before year and month using a function in php?
i am a newbie of php, supposed my blog created on 2011 year 1 month.and the article stored time as this 1305357473. now i want to use a function, which can output the before year and moth as this. 2011 year 1 month 2011 year 2 month 2011 year 3 month 2011 year 4 month 2011 year 5 month ...... i want to make the function can output the current and the past year and month. this is my function and output the result. but i don't know how to finish. function outYearMonth($year,$month){ $year=date(Y); $past_month=strtotime(date(1)) ; $month=strtotime(date(m)); $jg_month=round($month - $past_month); $month=array(); for($i==0;$i<=$jg_month;$i++){ $month[]= date(1)+1; } }
This code: $months = 10; //count of months $date = date_create( 'now' ); echo date_format( $date, 'Y M' ); for ( $i = 0; $i < $months; $i++ ) { date_sub( $date , date_interval_create_from_date_string( '1 months' ) ); echo date_format( $date, 'Y M' ); } Will output: 2011 May 2011 Apr 2011 Mar 2011 Feb 2011 Jan 2010 Dec 2010 Nov 2010 Oct 2010 Sep 2010 Aug 2010 Jul
echo date('Y m'); will give you this year and month echo date('Y m',strtotime('last month',time())) will give you last month for looping through all the month just get the current month and make a loop $currentMonth = (int) date('m',time()); $currentYear = date('Y',time()); for($i=0; $i <= $currentMonth; $i++) { echo "$currentYear $i"; } will echo all months 2011 1 2011 2 2011 3 2011 4 2011 5