How to loop through months that have been already passed - php

I have the following to loop through each month of the year. However, it seems to skip February.
$start = new DateTime('2015-01-01');
$start->modify('last day of this month');
$current = new DateTime('now');
$end = new DateTime('2018-01-01');
$interval = DateInterval::createFromDateString('1 month');
$period = new DatePeriod($start, $interval, $end);
$timestamps = array();
foreach ($period as $dt) {
$dt->modify('last day of this month');
echo 'C:' . $current->format('d F Y') . '<br>';
echo 'S:' . $start->format('d F Y') . '<br>';
echo 'D:' . $dt->format('d F Y') . '<br>';
echo '<br><br>';
}
However, the above outputs:
C:17 March 2015
S:31 January 2015
D:31 January 2015
C: 17 March 2015
S:31 January 2015
D:31 March 2015
C: 17 March 2015
S:31 January 2015
D:30 April 2015
Can anyone spot my mistake? I expected the second D to have a value of the 28 February 2015.
I just want a list of months that have already been passed.
Update
The problem highlighted by MLeFevre in the comments is that working with date intervals can be tricky. See Example #3 Beware when adding months http://php.net/manual/en/datetime.add.php.

Rather than use a DatePeriod, why not just use the modify method slightly differently like this:
$current = new DateTime('now');
$end = new DateTime('2018-01-01');
while($current < $end) {
$current->modify('last day of next month');
echo 'C:' . $current->format('d F Y') . '<br>';
}
In your question, you're firstly adding a month, then going to the end of that month. This doesn't work, as the length of each month varies.
Sample output:
C:30 April 2015
C:31 May 2015
C:30 June 2015
C:31 July 2015
C:31 August 2015
C:30 September 2015
C:31 October 2015
C:30 November 2015
C:31 December 2015
C:31 January 2016
C:29 February 2016
C:31 March 2016
// etc.
To loop from $start to $current, you could change the logic slightly like this:
$start = new DateTime('2015-01-31'); // start from end of month
$current = new DateTime('now');
do {
echo 'C:' . $start->format('d F Y') . '<br>';
} while($start->modify('last day of next month') < $current);
Output:
C:31 January 2015
C:28 February 2015

It happen because February has 28 days and your interval is 1 month (30 days). So it skips 30 days from 30 January to 2 March. Then it move to last day of March.
Change
$start->modify('last day of this month');
to
$start->modify('first day of this month');

Your first date is 31-Jan-2015. Since February has no 31st, it's going to March 3rd. Then you are telling it to go to the end of that month which is why you are getting the end of March after January and not February.

Related

How To Get Next Wednesday With PHP?

I have this situation :
17 January 2017 is Tuesday.
I'm expecting my code will generate 25 January 2017 as NEXT Wednesday. Not 18 January 2017.
19 January 2017 is Thursday.
I'm expecting my code will generate 25 January 2017 as NEXT Wednesday too.
but this code :
$payment_date = '17 January 2017';
echo $payment_date . '<br>';
$payment_date = date('d M Y', strtotime('next Wednesday', strtotime($payment_date)));
echo $payment_date;
gives me 18 January 2017 as next Wednesday. how to get 25 January 2017 as next Wednesday when my code runs between 15 - 21 January 2017?
thank you
$payment_date = date('d M Y', strtotime('next wednesday next week', strtotime($payment_date)));
Try using +1 week Wednesday instead of Next Wednesday:
$payment_date = date('d M Y', strtotime('+1 week Wednesday', strtotime($payment_date)));

how to print all date for a month or more

i want to print all date from today to specific day this specific day will be taken from database
$sql=mysqli_query($conn,"select * from tbl_activities where db_id='$id'")or die(mysqli_error($conn));
$row=mysqli_fetch_array($sql);
$day=$row['db_day'];
this code give me number of date example 10 days
i want to print date from today to 13 days
for($i=1;$i<=$day;$i++){
}
output will be like this
Thursday 21st of July 2016
Friday 22st of July 2016
23st of July 2016
24st of July 2016
25st of July 2016
26st of July 2016
27st of July 2016
28st of July 2016
29st of July 2016
30st of July 2016
31st of July 2016
1st of August 2016
try my edited code.
$day=$row['db_day'];
$start_day = strtotime(date("Y-m-d"));
$end_day = $start_day + 86400 * $day;
while($end_day >= $start_day){
echo date("j F, Y",$start_day)."\r\n";
$start_day = $start_day + 86400;
}
I hope its helps
<?php
$date = date('Y-m-d');
$end_date = date('Y-m-d', strtotime('+9 days')); //add the num of days u need here
while (strtotime($date) <= strtotime($end_date)) {
echo "<pre>".$date = date ("Y-m-d", strtotime("+1 day", strtotime($date)));
}
You could use the Datetime class and it's associated methods
/* formats for dates */
$df='Y-m-d H:i:s';
$dfo='l jS \of F, Y';
/* variable, number of days from NOW */
$days=14;
/* set the timezone and date interval */
$timezone=new DateTimeZone('Europe/London');
$interval=new DateInterval('P1D');
/*establish date range */
$ts=date( $df, strtotime('yesterday') );
$tf=date( $df, strtotime('1st August 2016') );
/* Alternatively... */
$tf=date( $df, strtotime('now +'.$days.' days') );
/* create instances of the `Datetime` class for both dates */
$start=new DateTime( $ts, $timezone );
$end=new DateTime( $tf, $timezone );
/* show the dates in the range */
while( $start->add( $interval ) <= $end ){
echo $start->format( $dfo ). '<br />';
}
Will output:
Thursday 21st of July, 2016
Friday 22nd of July, 2016
Saturday 23rd of July, 2016
Sunday 24th of July, 2016
Monday 25th of July, 2016
Tuesday 26th of July, 2016
Wednesday 27th of July, 2016
Thursday 28th of July, 2016
Friday 29th of July, 2016
Saturday 30th of July, 2016
Sunday 31st of July, 2016
Monday 1st of August, 2016
Tuesday 2nd of August, 2016
Wednesday 3rd of August, 2016
Thursday 4th of August, 2016

PHP Date function skipping February. Does anybody know of a work around for this date bug?

I am displaying month titles 3 month into the future as well as getting the 1st and last day of each of those months.
for($i = 1; $i < 4; $i++) { // For each month for 3 months
$monthTitle = date('F Y', strtotime('+'.$i.' month'));
$begin_date = date('Y-m-01', strtotime('+'.$i.' month')); // First day of calendar month in future.
$end_date = date('Y-m-t', strtotime('+'.$i.' month')); // Last day of calendar months in future.
};
Nov. 29, 2015 output is:
December 2015
2015-12-01
2015-12-31
January 2016
2016-01-01
2016-01-31
February 2016
2016-02-01
2016-02-29
This was working great right up until yesterday, Nov. 29, 2015 but today Nov. 30, 2015 it skips February.
Nov. 30, 2015 output is:
December 2015
2015-12-01
2015-12-31
January 2016
2016-01-01
2016-01-31
March 2016
2016-03-01
2016-03-31
I'm guessing a bug but does anybody know of a work around?
Thanks to #devlin carnate for pointing me in the right direction.
for($i = 1; $i < 4; $i++) { # for each month
$tmp = date('Y-m-15'); // Get the middle of the month to avoid PHP date bug.
$begin_date = date('Y-m-01', strtotime($tmp . '+'.$i.' month')); // First day of calendar month in future.
$end_date = date('Y-m-t', strtotime($begin_date)); // Last day of calendar months in future.
$monthTitle = date('F Y', strtotime($begin_date));
};
This seems to work very well.
You can use DateInterval to add one month to the current date, so you can get the first and the last day of month.
<?php
$date = new DateTime('2015-12-01');
$i = 0;
while($i < 3){
printf("%s | first day: %s, | last day: %s <br>", $date->format('F Y'), $date->format('d'), $date->format('t'));
$date->add(new DateInterval('P1M'));
$i++;
}
Output:
December 2015 - first day: 01, | last day: 31
January 2016 - first day: 01, | last day: 31
February 2016 - first day: 01, | last day: 29
if last day of next month is needed then you can use this
$d = new DateTime( '2010-01-31' );
$d->modify( 'last day of next month' );
echo $d->format( 'Y-m-d' ), "\n";

Parsing dates with inconsistent formats in PHP

I have two queries, both related to dates.
1) I have dates in these formats, which I'm looking to normalise into the same format before saving into a database:
Saturday 26 July
Monday 28 - Wednesday 30 July
July 24th, 2014
Thu 4 Sep
Thu 28 Aug — Fri 19 Sep
24-07-2014
Single days are quite easy to work out using strtotime(), but ranges of dates are a bit more tricky.
This, for example, doesn't work:
$dateString = "Monday 28 - Wednesday 30 July";
if (strpos($dateString, "-")) {
$datePieces = explode("-", $dateString);
$startDate = strtotime($datePieces[0]);
$endDate = strtotime($datePieces[1]);
} else {
$startDate = strtotime($dateString);
$endDate = strtotime($dateString);
}
echo '<pre>';
echo date('d F Y', $startDate);
echo '<br/>';
echo date('d F Y', $endDate);
Because the month is only on one side of the explode(), doing it this way returns:
01 January 1970
30 July 2014
2) I need a way of working out what year the date is (it will always be in the future). Something along the lines of:
if (the month in the date string has elapsed) {
the year of the date is this year + 1
}
As long as each source provides you with a consistent format you can use DateTime() and DateTime::createFromFormat() to process the dates for you.
//Saturday 26 July
$date = DateTime::createFromFormat('l j F', 'Saturday 26 July');
//July 24th, 2014
$date = new DateTime('July 24th, 2014');
//Thu 4 Sep
$date = DateTime::createFromFormat('D j M', 'Thu 4 Sep');
//Thu 28 Aug — Fri 19 Sep
list($start, $end) = explode(' - ', 'Thu 28 Aug — Fri 19 Sep');
$start = DateTime::createFromFormat('D j M', $start);
$end = DateTime::createFromFormat('D j M', $end);
//24-07-2014
$date = new DateTime('24-07-2014');
I'm going to leave handling Monday 28 - Wednesday 30 July to you since you'll need to do a little more work to get the month from the second date and apply it to the first. But this should show you how to go about this.

current week contains the last friday of the month

I am trying creating a script that will change an image on a page if the last friday in the month is during the current week. For example if I am on any of the day of week (Monday to Sunday) that contains the last friday of the month during the week I will get an output that differs from the rest of the month.
I was helped on a previous question with this code but it only works if the last day of the month is today. However I need the function to know if the last day of the month is on either Monday, Tuesday, Wednesday, Thursday is still in the current week as my week runs from Monday to Sunday:
// Be sure to check your timezone `date_default_timezone_set`
$today = new DateTime();
$last_friday = new DateTime('last Friday of this month');
// For testing
$friday_april = new DateTime('2014-4-25');
if ($today->format('Y-m-d') === $last_friday->format('Y-m-d')) {
print 'Today is friday';
}
if ($friday_april->format('Y-m-d') === $last_friday->format('Y-m-d')) {
print 'Yes, a test friday is also a friday';
}
Any help would be great!
Change your date format for the comparisons.
W should suffice.
Why?!
Because then the same string (the ISO week number) will be produced for dates within the same week (beginning on Mondays).
Given this month, April 2014, the week number of the week containing the last Friday is 17.
2014-04-19 Sat => 16 ✗
2014-04-20 Sun => 16 ✗
2014-04-21 Mon => 17 ✓
2014-04-22 Tue => 17 ✓
2014-04-23 Wed => 17 ✓
2014-04-24 Thu => 17 ✓
2014-04-25 Fri => 17 ✓
2014-04-26 Sat => 17 ✓
2014-04-27 Sun => 17 ✓
2014-04-28 Mon => 18 ✗
2014-04-29 Tue => 18 ✗
2014-04-30 Wed => 18 ✗
Summary
if ($today->format('W') === $last_friday->format('W')) {
// Do victory dance
}
You need a loop. Go through the loop and add a day until you get to the next month. Count how many Fridays you encounter (including today) from today to the start of the next month. If its only 1, then the last Friday is in this week.
use strtotime and date so it should look like this:
$today = new DateTime();
$last_friday = strtotime('last Friday of this month');
// For testing
$friday_april = new DateTime('2014-4-25');
if ($today->format('Y-m-d') === date('Y-m-d', $last_friday)) {
print 'Today is friday';
}
if ($friday_april->format('Y-m-d') === date('Y-m-d', $last_friday)) {
print 'Yes, a test friday is also a friday';
}
$today = getdate();
$weekStartDate = $today['mday'] - $today['wday'];
$weekEndDate = $today['mday'] - $today['wday']+6;
echo "week start date:".$weekStartDate;
echo "<br/>";
echo "week end date:".$weekEndDate;
By this code you can get start and end days of the current week
$thisWeekHasLastFridayOfMonth = function () {
$lastFridayThisMonth = date('Y-m-d',strtotime('last Friday of this month'));
$testDate = date('Y-m-d',strtotime('today'));
$thisWeekSunday = (date('N',strtotime($testDate))!=1?date('Y-m-d',strtotime('last Sunday')):date('Y-m-d'));
$thisWeekSaturday = (date('N',strtotime($testDate))!=7?date('Y-m-d',strtotime('next Saturday')):date('Y-m-d'));
//echo $lastFridayThisMonth . '<br>' . $thisWeekSunday . '<br>' . $thisWeekSaturday;
if (strtotime($lastFridayThisMonth) >= strtotime($thisWeekSunday) &&
strtotime($lastFridayThisMonth) <= strtotime($thisWeekSaturday))
return true;
else
return false;
};
echo $thisWeekHasLastFridayOfMonth?'True':'False';

Categories