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';
Related
I should be able to get the first Wednesday of each month, I can do it easily using:
$firstWedNextMonth = date ('d-m-Y', strtotime('first wednesday of next month'));
echo "The first wed of next month is: ".$firstWedNextMonth;
However, considering that the first Wednesday of next month is March 6th, the system must show this date until 3:00:00 on Thursday March 7th, at 3:00:01 instead it must indicate Wednesday, April 3rd. I do not know how to do it. Thank you
I think, this should work. +27 hours is 24 hours + your margin (3 hours). You can test it setting $now to whatever you want, instead of the current time.
$now = time();
$firstWedThisMonth = date ('d-m-Y', strtotime('first wednesday of this month', $now));
$firstWedNextMonth = date ('d-m-Y', strtotime('first wednesday of next month', $now));
$boundaryDateTime = strtotime('+27 hours', strtotime($firstWedThisMonth));
if ($now <= $boundaryDateTime) {
echo "The first wed of next month is: ".$firstWedThisMonth;
} else {
echo "The first wed of next month is: ".$firstWedNextMonth;
}
I'm looking to find the date of the 29th of this month, the 29th of next month, the 29th of last month and so on...
I know you can use this kind of code to find days of the week:
$friday_last = date("d/m/Y", strtotime("last Friday"));
$friday_due = date("d/m/Y", strtotime("this Friday"));
Is there a similar way to find a certain day (29th) of each month or would I have to use a different code?
You need to use DateTime() as it makes working with dates much easier. You'll notice I start by going to the first day of each month. That's so this doesn't break when you get to the 29th-30th of each month as weird date things start to happen.
echo (new DateTime())->modify('first day of this month')->format("29/m/Y");
echo (new DateTime())->modify('first day of previous month')->format("29/m/Y");
echo (new DateTime())->modify('first day of next month')->format("29/m/Y");
Demo
echo (new DateTime())->modify('first day of this month')->modify('-2 months')->format("29/m/Y");
Demo
Using date() with strtotime() will gives you 29th from each month within this year:
<?php
for ($i = 1; $i <= 12; $i++) {
$d = "2016-" . $i . "-29";
echo "29th of Month $i is: " . date("l", strtotime($d)) . '<br>';
}
?>
Output:
29th of Month 1 is: Friday
29th of Month 2 is: Monday
29th of Month 3 is: Tuesday
29th of Month 4 is: Friday
29th of Month 5 is: Sunday
29th of Month 6 is: Wednesday
29th of Month 7 is: Friday
29th of Month 8 is: Monday
29th of Month 9 is: Thursday
29th of Month 10 is: Saturday
29th of Month 11 is: Tuesday
29th of Month 12 is: Thursday
To create an array with current and next 11 months 29th day (for previous months replace +1 month with -1 month. In this example I use +1 to explain february issue, that is not present in past february):
$baseDate = date_create()->modify( 'first day of this month' );
$dates = array();
for( $i = 0; $i<12; $i++ )
{
$newDate = clone $baseDate;
$dates[] = $newDate->modify( '+28 days' );
$baseDate->modify( '+1 month' );
}
The problem — as you can imagine — is with february:
foreach( $dates as $date )
{
echo $date->format( 'Y-m-d' ).PHP_EOL;
}
Will output:
2016-05-29
2016-06-29
2016-07-29
2016-08-29
2016-09-29
2016-10-29
2016-11-29
2016-12-29
2017-01-29
2017-03-01 <-----
2017-03-29
2017-04-29
If you want a result like “29th month's day OR last month's day” modify above for loop in this way:
for( $i = 0; $i<12; $i++ )
{
$newDate = clone $baseDate;
if( $newDate->modify( '+28 days' )->format( 'm' ) != $baseDate->format( 'm' ) )
{
$newDate->modify( 'last day of previous month' );
}
$dates[] = $newDate;
$baseDate->modify( '+1 month' );
}
Result:
2016-05-29
2016-06-29
2016-07-29
2016-08-29
2016-09-29
2016-10-29
2016-11-29
2016-12-29
2017-01-29
2017-02-28 <-----
2017-03-29
2017-04-29
I'm not sure when this started, but now you can do so by using just date() and strtotime(), like this:
$d = date("Y-m-d 00:00:00", strtotime('first day of 2 months ago'));
$l = date("Y-m-d 00:00:00", strtotime('last day of 2 months ago'));
print_r($d);
print_r($l);
Assuming today (2023-02-01) The above will display:
2022-12-01 00:00:00
2022-12-31 00:00:00
Sample:
https://onlinephp.io/c/db73f
I'm trying to create a simple weekly agenda. Here is my code:
$daterange = new DatePeriod(
new DateTime('2016-04-08'),
new DateInterval('P1D'),
new DateTime(date('Y-m-d',strtotime ( '1 week' , strtotime ( '2016-04-08' ) )))
);
Then a simple loop:
foreach ($daterange as $k => $row) {
echo $row->format('d') ." - " . $row->format('D') . "<br>";
}
Produces something like:
08 - Fri
09 - Sat
10 - Sun
11 - Mon
12 - Tue
13 - Wed
14 - Thu
Which works perfectly fine, but what I need is to display dates starting from Sunday or Monday, based on first day of the week. The desired result should be:
10 - Sun
11 - Mon
12 - Tue
13 - Wed
14 - Thu
15 - Fri
16 - Sat
You could use something like this:
date('Y-m-d', strtotime('last Monday', '2016-04-08'));
You can replace last Monday with next Monday/last Sunday/next Sunday, depending on what you need. This will give you the previous/next first day of the week for current day. You could then obtain a 7 day interval, starting from this date.
It is generally considered bad to mix DateTime and strtotime(), date(), etc., so here's another solution:
// The question is ambiguous on this, so we'll use a
// variable to configure the preferred first weekday
$firstWeekDay = 'Sunday';
$dateTime = new DateTime();
// If today isn't the first week day, get the last one
if ($dateTime->format('l') !== $firstWeekDay)
{
$dateTime->modify("last {$firstWeekDay}");
}
$period = new DatePeriod(
$dateTime,
new DateInterval('P1D'),
6 // Just tell PHP to create 6 (7 - the 1 start day) more dates
);
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";
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.