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

Categories