PHP get a list of dates Mon - Sun - php

I would like to get a list of dates in the following format for a given year;
array:4 [▼
"04" => "25 Jan 2016 - 31 Jan 2016"
"03" => "18 Jan 2016 - 24 Jan 2016"
"02" => "11 Jan 2016 - 17 Jan 2016"
"01" => "4 Jan 2016 - 10 Jan 2016"
]
The array key shows the week number. The array value shows the dates.
If the year given is equal to the current year then I only want it to show dates up until the current week.
How can I achieve this?

This user defined getDates() function which takes weeknumber and year as input will return the desired result.
<?php
echo "<pre>";
print_r(getDates('4', '2016'));
echo "</pre>";
function getDates($weekNumber, $year) {
$returnArr = array();
for($i=$weekNumber; $i >= 1; $i--) {
$wno = $i<=9 ? "0".$i : $i;
$calStr = $year . "W" . $wno;
$startDate = date('d M Y',strtotime($calStr));
$endDate = date('d M Y', strtotime($startDate. ' + 6 day'));
$weekDays = $startDate . ' - ' . $endDate;
$returnArr[$wno] = $weekDays;
}
return $returnArr;
}
Output
Array
(
[04] => 25 Jan 2016 - 31 Jan 2016
[03] => 18 Jan 2016 - 24 Jan 2016
[02] => 11 Jan 2016 - 17 Jan 2016
[01] => 04 Jan 2016 - 10 Jan 2016
)

Related

Add year function boolean and replace 3-letter month with its month number in an array of strings

Background information:
The log file is copied and read out at regular intervals.
Log file lines do not have a year specification.
Months are continuous.
Before January is always the previous year.
If January lines do not appear in the log file, then it is only about the current year. Example:
2023 mar,
2023 apr,
2023 may,
2023 jun
If January occurs one or more times in the month cycle, then the current year is from the beginning of the last occurrence (January). Example:
2021 nov,
2021 dec,
2021 dec
2022 jan, // new year
2022 jan,
2022 feb,
...
2022 dec,
2023 jan, // new year, last jan = actual year
2023 jan,
2023 feb,
...
Code:
Recognize which year it is based on the 3-letters and lines and add the correct year to each line.
$arr = [
// without first Dec, Jan and Jan lines:
// all subsequent lines are the current year
"Dec 23 21:37:56 hello",
"Jan 12 02:08:23 hello",
"Jan 16 17:34:33 hello",
"Feb 4 12:21:09 hello",
"Mar 19 17:07:26 hello",
"Apr 1 00:00:03 hello",
"Apr 12 23:07:39 hello",
"May 21 04:09:34 hello",
"Jun 7 23:34:56 hello",
"Jul 1 14:45:34 hello",
"Aug 13 11:37:23 hello",
"Sep 29 07:36:03 hello",
"Oct 30 09:01:00 hello",
"Nov 10 11:00:03 hello",
"Dec 25 21:47:51 hello"
];
Create a function to find the years.
function setYear()
{
global $arr, $y;
$first = explode(' ', $arr[array_key_first($arr)]);
// if the 1st line doesn't start with Jan, then it's the previous year.
if (!in_array('01', $first)) {
$y = date("Y", strtotime("-1 year"));
} else {
$y = date("Y");
}
return $y;
}
Convert date year and month integer
$arr = preg_replace_callback(
'/^(\w+)\s+(\d+)\s/',
function ($matches) {
global $y;
$yy = setYear($y);
return date($yy . ' m d', strtotime($matches[0] . ' ' . date("Y"))) . ' ';
},
$arr
);
echo '<pre>';
print_r($arr);
echo '</pre>';
Unexpected result:
Array
(
[0] => 2022 12 23 21:37:56 hello
[1] => 2022 01 12 02:08:23 hello
[2] => 2022 01 16 17:34:33 hello
[3] => 2022 02 04 12:21:09 hello
[4] => 2022 03 19 17:07:26 hello
// ...
[9] => 2022 11 10 11:00:03 hello
[10] => 2022 12 25 21:47:51 hello
)
Expected result:
Array
(
[0] => 2023 12 23 21:37:56 hello
[1] => 2022 01 12 02:08:23 hello
[2] => 2022 01 16 17:34:33 hello
[3] => 2022 02 04 12:21:09 hello
[4] => 2022 03 19 17:07:26 hello
// ...
[9] => 2022 11 10 11:00:03 hello
[10] => 2022 12 25 21:47:51 hello
)
Use a static variable instead of bringing global variables into scope with global. The static keyword will ensure that the previous iterations' declaration is retained and is accessible. If Jan is encountered or was encountered before, set the flag as true. Until the flag is set to true, subtract 1 year from the date's year.
Code: (Demo)
var_export(
preg_replace_callback(
'/^([a-z]{3}) +\d+/i',
function($m) {
static $encounteredJan = false;
$encounteredJan = $encounteredJan || $m[1] === 'Jan';
return date('Y m d', strtotime($m[0] . ($encounteredJan ? '' : ' -1 year')));
},
$arr
)
);
If you cannot rely on Jan existing in the dataset, then (assuming you never need to jump more than one year forward), just check if the current month is less than the last encountered month. If, say, going from Sep to Apr (10 to 4), then you can safely assume that the year should be increased/incremented.
Code: (Demo)
var_export(
preg_replace_callback(
'/^([a-z]{3}) +\d+/i',
function($m) {
static $lastMonthInt = 0;
static $year = null;
$year ??= date('Y', strtotime('-1 year'));
$currentMonthInt = date('n', strtotime($m[1]));
if ($currentMonthInt < $lastMonthInt) {
++$year;
}
$lastMonthInt = $currentMonthInt;
return "$year " . date('m d', strtotime($m[0]));
},
$arr
)
);
Final edit:
To ensure that the highest generated year is the current year, use array_reverse() to process the data from latest entry to the earliest entry. Compare the standardized timestamp expression against the previous timestamp. When the current stamp is greater than the last, decrement the year. When finished processing, call array_reverse() on the result to return it to its original order.
Code: (Demo)
var_export(
array_reverse(
preg_replace_callback(
'/^[a-z]{3} +\d+ \d\d:\d\d:\d\d/i',
function($m) {
static $lastStamp = null;
static $year = null;
$year ??= date('Y');
$currentStamp = date('m d H:i:s', strtotime($m[0]));
if ($currentStamp > ($lastStamp ?? $currentStamp)) {
--$year;
}
$lastStamp = $currentStamp;
return "$year $currentStamp";
},
array_reverse($arr)
)
)
);

How to calculate number of mondays in a given month? [duplicate]

I need to output a list of dates (only Mondays and Tuesdays) for the next 12 months from current date like so:
Jan 2010
Tue 12 Jan 2010
Mon 18 Jan 2010
Tue 19 Jan 2010
Mon 25 Jan 2010
Feb 2010
Tue 02 Feb 2010
Mon 08 Feb 2010
Tue 09 Feb 2010
Mon 15 Feb 2010
Tue 16 Feb 2010
Mon 22 Feb 2010
Mar 2010
Tue 09 Mar 2010
Mon 15 Mar 2010
Tue 16 Mar 2010
...
Being new to PHP I figured strtotime and looping over the next 52 weeks is the best way to go.
$blockedDatesInput = "08 Mar 2010,12 Apr 2010"; // dont show these dates
$blockedDates = explode ("," , $blockedDatesInput); // convert to array
$currentMonth = ""; // current month marker
// loop over the next 52 weeks to find Mondays and Tuesdays
for($i=0; $i<=52; $i++){
// build the month header
$monthReference = date("M Y", strtotime('+'.$i.' Week'));
// check if date exists in $blockeddate
if (!in_array(date("d M Y", strtotime('+'.$i.' Monday')), $blockedDates) ||
!in_array(date("d M Y", strtotime('+'.$i.' Tuesday')), $blockedDates) ) {
// check if we have to show a new month
if(strcmp($monthReference, $currentMonth) <> 0){
echo $monthReference.'<br />',"\n";
}else{
// output the dates
echo date("D d M Y", strtotime('+'.$i.' Monday')).'<br />',"\n";
echo date("D d M Y", strtotime('+'.$i.' Tuesday')).'<br />',"\n";
}
$currentMonth = date("M Y", strtotime('+'.$i.' Week'));
}
}
However the output from my code is
Jan 2010
Mon 18 Jan 2010
Tue 12 Jan 2010
Mon 25 Jan 2010
Tue 19 Jan 2010
Feb 2010
Mon 08 Feb 2010
Tue 02 Feb 2010
Mon 15 Feb 2010
Tue 09 Feb 2010
Mon 22 Feb 2010
Tue 16 Feb 2010
Mar 2010
Mon 08 Mar 2010
Tue 02 Mar 2010
Mon 15 Mar 2010
Tue 09 Mar 2010
Mon 22 Mar 2010
Tue 16 Mar 2010
Mon 29 Mar 2010
Tue 23 Mar 2010
As you can see the dates are not in the right order and I am at a loss where I am going wrong here.
Is there a more elegant / simple way to solve this?
Version of PHP used is 5.2.11 and no prospect of going to 5.3 anytime soon :-(
Thanks for your help.
Code below modification as suggested by Aly.
Changed the computer date from Tue, 12/01/2010 to Wed, 13/01/2010 to test the output.
$blockedDatesInput = "08 Mar 2010,12 Apr 2010"; // dont show these dates
$blockedDates = explode ("," , $blockedDatesInput); // convert to array
$currentMonth = ""; // current month marker
// loop over the next 52 weeks to find Mondays and Tuesdays
for($i=0; $i<=52; $i++){
// build the month header
$monthReference = date("M Y", strtotime('+'.$i.' Week'));
// check if date exists in $blockeddate
if (!in_array(date("d M Y", strtotime('+'.$i.' Monday')), $blockedDates) ||
!in_array(date("d M Y", strtotime('+'.$i.' Tuesday')), $blockedDates) ) {
// check if we have to show a new month
if(strcmp($monthReference, $currentMonth) <> 0){
echo $monthReference.'<br />',"\n";
}else{
// output the dates (changed the order as suggested by Aly)
echo date("D d M Y", strtotime('+'.$i.' Tuesday')).'<br />',"\n";
echo date("D d M Y", strtotime('+'.$i.' Monday')).'<br />',"\n";
}
$currentMonth = date("M Y", strtotime('+'.$i.' Week'));
}
}
Output again in the wrong order.
Jan 2010
Tue 19 Jan 2010
Mon 18 Jan 2010
Tue 26 Jan 2010
Mon 25 Jan 2010
Feb 2010
Tue 09 Feb 2010
Mon 08 Feb 2010
Tue 16 Feb 2010
Mon 15 Feb 2010
Tue 23 Feb 2010
Mon 22 Feb 2010
This is an interesting one. Here's how I'd do it with functions, though it may warrant its own class to really be modular and reusable:
Set up my date formats and excluded dates
define('INTERNAL_FORMAT', 'Y-m-d');
define('DISPLAY_MONTH_FORMAT', 'M Y');
define('DISPLAY_DAY_FORMAT', 'D d M Y');
// format excluded dates as YYYY-MM-DD, date('Y-m-d'):
$excluded_dates = array(
'2010-03-09',
'2010-04-13',
);
Then I need some utility functions to see how the dates run, and what dates are excluded:
// date('w') returns a string numeral as follows:
// '0' Sunday
// '1' Monday
// '2' Tuesday
// '3' Wednesday
// '4' Thursday
// '5' Friday
// '6' Saturday
function isTuesday($date) {
return date('w', strtotime($date)) === '2';
}
function isWednesday($date) {
return date('w', strtotime($date)) === '3';
}
// handle the excluded dates
function isExcludedDate($internal_date) {
global $excluded_dates;
return in_array($internal_date, $excluded_dates);
}
Now we just need to iterate over every day of the next 365 (the next year) and check to see if they're Tuesday or Wednesday and not on the excluded list. We store this in $months_and_dates:
$start_date = date(INTERNAL_FORMAT);
// something to store months and days
$months_and_dates = array();
// loop over 365 days and look for tuesdays or wednesdays not in the excluded list
foreach(range(0,365) as $day) {
$internal_date = date(INTERNAL_FORMAT, strtotime("{$start_date} + {$day} days"));
$this_day = date(DISPLAY_DAY_FORMAT, strtotime($internal_date));
$this_month = date(DISPLAY_MONTH_FORMAT, strtotime($internal_date));
if ((isTuesday($internal_date) || isWednesday($internal_date))
&& !isExcludedDate($internal_date)) {
$months_and_dates[$this_month][] = $this_day;
}
}
You can print_r() it, or to get the display you want, we do this:
foreach($months_and_dates as $month => $days) {
print $month . "<br>";
print implode('<br>', $days);
print "<br>";
}
Here's the result as of today, January 11, 2010:
Jan 2010
Tue 12 Jan 2010
Wed 13 Jan 2010
Tue 19 Jan 2010
Wed 20 Jan 2010
Tue 26 Jan 2010
Wed 27 Jan 2010
Feb 2010
Tue 02 Feb 2010
Wed 03 Feb 2010
Tue 09 Feb 2010
Wed 10 Feb 2010
Tue 16 Feb 2010
Wed 17 Feb 2010
Tue 23 Feb 2010
Wed 24 Feb 2010
Mar 2010
Tue 02 Mar 2010
Wed 03 Mar 2010
Wed 10 Mar 2010
Tue 16 Mar 2010
Wed 17 Mar 2010
Tue 23 Mar 2010
Wed 24 Mar 2010
Tue 30 Mar 2010
Wed 31 Mar 2010
Apr 2010
Tue 06 Apr 2010
Wed 07 Apr 2010
Wed 14 Apr 2010
Tue 20 Apr 2010
Wed 21 Apr 2010
Tue 27 Apr 2010
Wed 28 Apr 2010
May 2010
Tue 04 May 2010
Wed 05 May 2010
Tue 11 May 2010
Wed 12 May 2010
Tue 18 May 2010
Wed 19 May 2010
Tue 25 May 2010
Wed 26 May 2010
Jun 2010
Tue 01 Jun 2010
Wed 02 Jun 2010
Tue 08 Jun 2010
Wed 09 Jun 2010
Tue 15 Jun 2010
Wed 16 Jun 2010
Tue 22 Jun 2010
Wed 23 Jun 2010
Tue 29 Jun 2010
Wed 30 Jun 2010
Jul 2010
Tue 06 Jul 2010
Wed 07 Jul 2010
Tue 13 Jul 2010
Wed 14 Jul 2010
Tue 20 Jul 2010
Wed 21 Jul 2010
Tue 27 Jul 2010
Wed 28 Jul 2010
Aug 2010
Tue 03 Aug 2010
Wed 04 Aug 2010
Tue 10 Aug 2010
Wed 11 Aug 2010
Tue 17 Aug 2010
Wed 18 Aug 2010
Tue 24 Aug 2010
Wed 25 Aug 2010
Tue 31 Aug 2010
Sep 2010
Wed 01 Sep 2010
Tue 07 Sep 2010
Wed 08 Sep 2010
Tue 14 Sep 2010
Wed 15 Sep 2010
Tue 21 Sep 2010
Wed 22 Sep 2010
Tue 28 Sep 2010
Wed 29 Sep 2010
Oct 2010
Tue 05 Oct 2010
Wed 06 Oct 2010
Tue 12 Oct 2010
Wed 13 Oct 2010
Tue 19 Oct 2010
Wed 20 Oct 2010
Tue 26 Oct 2010
Wed 27 Oct 2010
Nov 2010
Tue 02 Nov 2010
Wed 03 Nov 2010
Tue 09 Nov 2010
Wed 10 Nov 2010
Tue 16 Nov 2010
Wed 17 Nov 2010
Tue 23 Nov 2010
Wed 24 Nov 2010
Tue 30 Nov 2010
Dec 2010
Wed 01 Dec 2010
Tue 07 Dec 2010
Wed 08 Dec 2010
Tue 14 Dec 2010
Wed 15 Dec 2010
Tue 21 Dec 2010
Wed 22 Dec 2010
Tue 28 Dec 2010
Wed 29 Dec 2010
Jan 2011
Tue 04 Jan 2011
Wed 05 Jan 2011
Tue 11 Jan 2011
in a funny coincidence, because today is monday, it is skipping one monday value, that's why they appear out of order. yesterday it would have worked fine.
i.e. your "+ 0 Monday" is NEXT monday, not today.
you may want to look into the "N" format character for date().
Ok now that your computers date is Wednesday you want to print the Mondays before the Tuesdays as the next Monday is closer to Wednesday than the next Tuesday. So try this:
$blockedDatesInput = "08 Mar 2010,12 Apr 2010"; // dont show these dates
$blockedDates = explode ("," , $blockedDatesInput); // convert to array
$currentMonth = ""; // current month marker
// loop over the next 52 weeks to find Mondays and Tuesdays
for($i=0; $i<=52; $i++){
// build the month header
$monthReference = date("M Y", strtotime('+'.$i.' Week'));
// check if date exists in $blockeddate
if (!in_array(date("d M Y", strtotime('+'.$i.' Monday')), $blockedDates) ||
!in_array(date("d M Y", strtotime('+'.$i.' Tuesday')), $blockedDates) ) {
// check if we have to show a new month
if(strcmp($monthReference, $currentMonth) <> 0){
echo $monthReference.'<br />',"\n";
}else{
// output the dates (changed the order as suggested by Aly)
echo date("D d M Y", strtotime('+'.$i.' Monday')).'<br />',"\n";
echo date("D d M Y", strtotime('+'.$i.' Tuesday')).'<br />',"\n";
}
$currentMonth = date("M Y", strtotime('+'.$i.' Week'));
}
}
<?php
/*
#$listDaysOfWeek list days
0 = Monday
1 = Tuesday
2 = Wednesday
3 = Thursday
4 = Friday
5 = Saturday
6 = Sunday
*/
function DatesFromDaysOnWeek(\Datetime $objDateTime, int $numAddDays , array $listDaysOfWeek)
{
$listDaysOfWeek = array_intersect($listDaysOfWeek, range(0,6) );
sort($listDaysOfWeek);
if(empty($listDaysOfWeek) || $numAddDays < 1)
return [];
$results = [];
while ( $numAddDays > 0)
{
foreach($listDaysOfWeek as $numDay)
{
$infoDate = (object) getdate( $objDateTime->getTimestamp() );
if($numDay != $infoDate->wday)
continue;
array_push($results, $objDateTime->format('Y-m-d') );
$numAddDays--;
}
$objDateTime->add(new \DateInterval('P1D'));
}
return $results;
}
#example:
$list = DatesFromDaysOnWeek( (new \DateTime('2019-02-01')) , 4 , [1] );
print_r($list);
$list = DatesFromDaysOnWeek( (new \DateTime('2019-02-01')) , 4 , [2] );
print_r($list);
$list = DatesFromDaysOnWeek( (new \DateTime('2019-02-01')) , 4 , [3] );
print_r($list);
$list = DatesFromDaysOnWeek( (new \DateTime('2019-02-01')) , 4 , [4] );
print_r($list);
$list = DatesFromDaysOnWeek( (new \DateTime('2019-02-01')) , 4 , [5] );
print_r($list);
$list = DatesFromDaysOnWeek( (new \DateTime('2019-02-01')) , 4 , [6] );
print_r($list);
$list = DatesFromDaysOnWeek( (new \DateTime('2019-02-01')) , 4 , [0] );
print_r($list);
$list = DatesFromDaysOnWeek( (new \DateTime('2019-03-01')) , 100 , [1,2] );
print_r($list);

Getting first day of every week in 6 months

I'm trying to figure out how can I get the the first day of week for the last 6 months and can't get to a working solution.
If I write date("Y-m-d 00:00:00", strtotime("-1 week", date("Y-m-d")); It just subtracts 7 days from the current date; what I want to do is to always return the date of Monday from that week.
Expected result:
2011-8-8 00:00:00
2011-8-1 00:00:00
2011-7-25 00:00:00
2011-7-18 00:00:00
etc
This should do it:
for ($i=0; $i<52/2; $i++)
echo date('Y-m-d', mktime(1, 0, 0, date('m'), date('d')-date('w')-$i*7+1, date('Y'))) . " 00:00:00\n";
it's slightly changed from Mike's Post, who wants the sunday instead of the monday.
I'd recommend DateTime::createFromFormat.
Pre-PHP 5.3, you can use strtotime instead:
<?php
define('NUM_WEEKS', 10);
$dates = Array();
$dates[] = strtotime('Monday');
for ($i = 0; $i < NUM_WEEKS-1; $i++)
$dates[] = strtotime('-1 week', $dates[$i]);
foreach ($dates as $date)
echo strftime('%c', $date) . "\n";
?>
Output:
Mon Aug 22 00:00:00 2011
Mon Aug 15 00:00:00 2011
Mon Aug 8 00:00:00 2011
Mon Aug 1 00:00:00 2011
Mon Jul 25 00:00:00 2011
Mon Jul 18 00:00:00 2011
Mon Jul 11 00:00:00 2011
Mon Jul 4 00:00:00 2011
Mon Jun 27 00:00:00 2011
Mon Jun 20 00:00:00 2011
Live demo.
If you're trying to make Saturday (or any other day for that matter)
the first day of the week to select datasets, here's a good
workaround:
<?php $last_sat=date("z", strtotime("last Saturday"));
$second_last_sat=date("z", strtotime("last Saturday-1 week")); ?>
source: http://www.php.net/manual/en/function.strtotime.php
What you'd probably want is
<?php $last_mon=date("z", strtotime("last Monday "));
$second_last_mon=date("z", strtotime("last Monday-1 week")); ?>
etc..

Timestamp of nearest valid month

Just a quickie..
How to derive the unixtime of nearest March or June?
If the current month is February of 2009, the script should give the unixtime of March 01, 2009.
If the current month is April of 2009, the script should give the unixtime of June 01, 2009.
If the current month is October of 2009, the script should give the unixtime of March 01, 2010.
Thank you for any help!
Update: Sorry, my bad. "next" works with days and in cases like "next month" but not "next March" so it's a little more convoluted than the original one liner.
strtotime() is really awesome for things like this:
$tests = array(
strtotime('2 february'),
strtotime('4 april'),
strtotime('9 november'),
);
foreach ($tests as $test) {
echo date('r', $test) . ' => ' . date('r', nextmj($test)) . "\n";
}
function nextmj($time = time()) {
$march = strtotime('1 march', $time);
$june = strtotime('1 june', $time);
if ($march >= $time) {
return $march;
} else if ($june >= $time) {
return $june;
} else {
return strtotime('+1 year', $march);
}
}
Output:
Mon, 02 Feb 2009 00:00:00 +0000 => Sun, 01 Mar 2009 00:00:00 +0000
Sat, 04 Apr 2009 00:00:00 +0000 => Mon, 01 Jun 2009 00:00:00 +0000
Mon, 09 Nov 2009 00:00:00 +0000 => Mon, 01 Mar 2010 00:00:00 +0000
Also see What date formats does the PHP function strtotime() support?

Getting all dates for Mondays and Tuesdays for the next year

I need to output a list of dates (only Mondays and Tuesdays) for the next 12 months from current date like so:
Jan 2010
Tue 12 Jan 2010
Mon 18 Jan 2010
Tue 19 Jan 2010
Mon 25 Jan 2010
Feb 2010
Tue 02 Feb 2010
Mon 08 Feb 2010
Tue 09 Feb 2010
Mon 15 Feb 2010
Tue 16 Feb 2010
Mon 22 Feb 2010
Mar 2010
Tue 09 Mar 2010
Mon 15 Mar 2010
Tue 16 Mar 2010
...
Being new to PHP I figured strtotime and looping over the next 52 weeks is the best way to go.
$blockedDatesInput = "08 Mar 2010,12 Apr 2010"; // dont show these dates
$blockedDates = explode ("," , $blockedDatesInput); // convert to array
$currentMonth = ""; // current month marker
// loop over the next 52 weeks to find Mondays and Tuesdays
for($i=0; $i<=52; $i++){
// build the month header
$monthReference = date("M Y", strtotime('+'.$i.' Week'));
// check if date exists in $blockeddate
if (!in_array(date("d M Y", strtotime('+'.$i.' Monday')), $blockedDates) ||
!in_array(date("d M Y", strtotime('+'.$i.' Tuesday')), $blockedDates) ) {
// check if we have to show a new month
if(strcmp($monthReference, $currentMonth) <> 0){
echo $monthReference.'<br />',"\n";
}else{
// output the dates
echo date("D d M Y", strtotime('+'.$i.' Monday')).'<br />',"\n";
echo date("D d M Y", strtotime('+'.$i.' Tuesday')).'<br />',"\n";
}
$currentMonth = date("M Y", strtotime('+'.$i.' Week'));
}
}
However the output from my code is
Jan 2010
Mon 18 Jan 2010
Tue 12 Jan 2010
Mon 25 Jan 2010
Tue 19 Jan 2010
Feb 2010
Mon 08 Feb 2010
Tue 02 Feb 2010
Mon 15 Feb 2010
Tue 09 Feb 2010
Mon 22 Feb 2010
Tue 16 Feb 2010
Mar 2010
Mon 08 Mar 2010
Tue 02 Mar 2010
Mon 15 Mar 2010
Tue 09 Mar 2010
Mon 22 Mar 2010
Tue 16 Mar 2010
Mon 29 Mar 2010
Tue 23 Mar 2010
As you can see the dates are not in the right order and I am at a loss where I am going wrong here.
Is there a more elegant / simple way to solve this?
Version of PHP used is 5.2.11 and no prospect of going to 5.3 anytime soon :-(
Thanks for your help.
Code below modification as suggested by Aly.
Changed the computer date from Tue, 12/01/2010 to Wed, 13/01/2010 to test the output.
$blockedDatesInput = "08 Mar 2010,12 Apr 2010"; // dont show these dates
$blockedDates = explode ("," , $blockedDatesInput); // convert to array
$currentMonth = ""; // current month marker
// loop over the next 52 weeks to find Mondays and Tuesdays
for($i=0; $i<=52; $i++){
// build the month header
$monthReference = date("M Y", strtotime('+'.$i.' Week'));
// check if date exists in $blockeddate
if (!in_array(date("d M Y", strtotime('+'.$i.' Monday')), $blockedDates) ||
!in_array(date("d M Y", strtotime('+'.$i.' Tuesday')), $blockedDates) ) {
// check if we have to show a new month
if(strcmp($monthReference, $currentMonth) <> 0){
echo $monthReference.'<br />',"\n";
}else{
// output the dates (changed the order as suggested by Aly)
echo date("D d M Y", strtotime('+'.$i.' Tuesday')).'<br />',"\n";
echo date("D d M Y", strtotime('+'.$i.' Monday')).'<br />',"\n";
}
$currentMonth = date("M Y", strtotime('+'.$i.' Week'));
}
}
Output again in the wrong order.
Jan 2010
Tue 19 Jan 2010
Mon 18 Jan 2010
Tue 26 Jan 2010
Mon 25 Jan 2010
Feb 2010
Tue 09 Feb 2010
Mon 08 Feb 2010
Tue 16 Feb 2010
Mon 15 Feb 2010
Tue 23 Feb 2010
Mon 22 Feb 2010
This is an interesting one. Here's how I'd do it with functions, though it may warrant its own class to really be modular and reusable:
Set up my date formats and excluded dates
define('INTERNAL_FORMAT', 'Y-m-d');
define('DISPLAY_MONTH_FORMAT', 'M Y');
define('DISPLAY_DAY_FORMAT', 'D d M Y');
// format excluded dates as YYYY-MM-DD, date('Y-m-d'):
$excluded_dates = array(
'2010-03-09',
'2010-04-13',
);
Then I need some utility functions to see how the dates run, and what dates are excluded:
// date('w') returns a string numeral as follows:
// '0' Sunday
// '1' Monday
// '2' Tuesday
// '3' Wednesday
// '4' Thursday
// '5' Friday
// '6' Saturday
function isTuesday($date) {
return date('w', strtotime($date)) === '2';
}
function isWednesday($date) {
return date('w', strtotime($date)) === '3';
}
// handle the excluded dates
function isExcludedDate($internal_date) {
global $excluded_dates;
return in_array($internal_date, $excluded_dates);
}
Now we just need to iterate over every day of the next 365 (the next year) and check to see if they're Tuesday or Wednesday and not on the excluded list. We store this in $months_and_dates:
$start_date = date(INTERNAL_FORMAT);
// something to store months and days
$months_and_dates = array();
// loop over 365 days and look for tuesdays or wednesdays not in the excluded list
foreach(range(0,365) as $day) {
$internal_date = date(INTERNAL_FORMAT, strtotime("{$start_date} + {$day} days"));
$this_day = date(DISPLAY_DAY_FORMAT, strtotime($internal_date));
$this_month = date(DISPLAY_MONTH_FORMAT, strtotime($internal_date));
if ((isTuesday($internal_date) || isWednesday($internal_date))
&& !isExcludedDate($internal_date)) {
$months_and_dates[$this_month][] = $this_day;
}
}
You can print_r() it, or to get the display you want, we do this:
foreach($months_and_dates as $month => $days) {
print $month . "<br>";
print implode('<br>', $days);
print "<br>";
}
Here's the result as of today, January 11, 2010:
Jan 2010
Tue 12 Jan 2010
Wed 13 Jan 2010
Tue 19 Jan 2010
Wed 20 Jan 2010
Tue 26 Jan 2010
Wed 27 Jan 2010
Feb 2010
Tue 02 Feb 2010
Wed 03 Feb 2010
Tue 09 Feb 2010
Wed 10 Feb 2010
Tue 16 Feb 2010
Wed 17 Feb 2010
Tue 23 Feb 2010
Wed 24 Feb 2010
Mar 2010
Tue 02 Mar 2010
Wed 03 Mar 2010
Wed 10 Mar 2010
Tue 16 Mar 2010
Wed 17 Mar 2010
Tue 23 Mar 2010
Wed 24 Mar 2010
Tue 30 Mar 2010
Wed 31 Mar 2010
Apr 2010
Tue 06 Apr 2010
Wed 07 Apr 2010
Wed 14 Apr 2010
Tue 20 Apr 2010
Wed 21 Apr 2010
Tue 27 Apr 2010
Wed 28 Apr 2010
May 2010
Tue 04 May 2010
Wed 05 May 2010
Tue 11 May 2010
Wed 12 May 2010
Tue 18 May 2010
Wed 19 May 2010
Tue 25 May 2010
Wed 26 May 2010
Jun 2010
Tue 01 Jun 2010
Wed 02 Jun 2010
Tue 08 Jun 2010
Wed 09 Jun 2010
Tue 15 Jun 2010
Wed 16 Jun 2010
Tue 22 Jun 2010
Wed 23 Jun 2010
Tue 29 Jun 2010
Wed 30 Jun 2010
Jul 2010
Tue 06 Jul 2010
Wed 07 Jul 2010
Tue 13 Jul 2010
Wed 14 Jul 2010
Tue 20 Jul 2010
Wed 21 Jul 2010
Tue 27 Jul 2010
Wed 28 Jul 2010
Aug 2010
Tue 03 Aug 2010
Wed 04 Aug 2010
Tue 10 Aug 2010
Wed 11 Aug 2010
Tue 17 Aug 2010
Wed 18 Aug 2010
Tue 24 Aug 2010
Wed 25 Aug 2010
Tue 31 Aug 2010
Sep 2010
Wed 01 Sep 2010
Tue 07 Sep 2010
Wed 08 Sep 2010
Tue 14 Sep 2010
Wed 15 Sep 2010
Tue 21 Sep 2010
Wed 22 Sep 2010
Tue 28 Sep 2010
Wed 29 Sep 2010
Oct 2010
Tue 05 Oct 2010
Wed 06 Oct 2010
Tue 12 Oct 2010
Wed 13 Oct 2010
Tue 19 Oct 2010
Wed 20 Oct 2010
Tue 26 Oct 2010
Wed 27 Oct 2010
Nov 2010
Tue 02 Nov 2010
Wed 03 Nov 2010
Tue 09 Nov 2010
Wed 10 Nov 2010
Tue 16 Nov 2010
Wed 17 Nov 2010
Tue 23 Nov 2010
Wed 24 Nov 2010
Tue 30 Nov 2010
Dec 2010
Wed 01 Dec 2010
Tue 07 Dec 2010
Wed 08 Dec 2010
Tue 14 Dec 2010
Wed 15 Dec 2010
Tue 21 Dec 2010
Wed 22 Dec 2010
Tue 28 Dec 2010
Wed 29 Dec 2010
Jan 2011
Tue 04 Jan 2011
Wed 05 Jan 2011
Tue 11 Jan 2011
in a funny coincidence, because today is monday, it is skipping one monday value, that's why they appear out of order. yesterday it would have worked fine.
i.e. your "+ 0 Monday" is NEXT monday, not today.
you may want to look into the "N" format character for date().
Ok now that your computers date is Wednesday you want to print the Mondays before the Tuesdays as the next Monday is closer to Wednesday than the next Tuesday. So try this:
$blockedDatesInput = "08 Mar 2010,12 Apr 2010"; // dont show these dates
$blockedDates = explode ("," , $blockedDatesInput); // convert to array
$currentMonth = ""; // current month marker
// loop over the next 52 weeks to find Mondays and Tuesdays
for($i=0; $i<=52; $i++){
// build the month header
$monthReference = date("M Y", strtotime('+'.$i.' Week'));
// check if date exists in $blockeddate
if (!in_array(date("d M Y", strtotime('+'.$i.' Monday')), $blockedDates) ||
!in_array(date("d M Y", strtotime('+'.$i.' Tuesday')), $blockedDates) ) {
// check if we have to show a new month
if(strcmp($monthReference, $currentMonth) <> 0){
echo $monthReference.'<br />',"\n";
}else{
// output the dates (changed the order as suggested by Aly)
echo date("D d M Y", strtotime('+'.$i.' Monday')).'<br />',"\n";
echo date("D d M Y", strtotime('+'.$i.' Tuesday')).'<br />',"\n";
}
$currentMonth = date("M Y", strtotime('+'.$i.' Week'));
}
}
<?php
/*
#$listDaysOfWeek list days
0 = Monday
1 = Tuesday
2 = Wednesday
3 = Thursday
4 = Friday
5 = Saturday
6 = Sunday
*/
function DatesFromDaysOnWeek(\Datetime $objDateTime, int $numAddDays , array $listDaysOfWeek)
{
$listDaysOfWeek = array_intersect($listDaysOfWeek, range(0,6) );
sort($listDaysOfWeek);
if(empty($listDaysOfWeek) || $numAddDays < 1)
return [];
$results = [];
while ( $numAddDays > 0)
{
foreach($listDaysOfWeek as $numDay)
{
$infoDate = (object) getdate( $objDateTime->getTimestamp() );
if($numDay != $infoDate->wday)
continue;
array_push($results, $objDateTime->format('Y-m-d') );
$numAddDays--;
}
$objDateTime->add(new \DateInterval('P1D'));
}
return $results;
}
#example:
$list = DatesFromDaysOnWeek( (new \DateTime('2019-02-01')) , 4 , [1] );
print_r($list);
$list = DatesFromDaysOnWeek( (new \DateTime('2019-02-01')) , 4 , [2] );
print_r($list);
$list = DatesFromDaysOnWeek( (new \DateTime('2019-02-01')) , 4 , [3] );
print_r($list);
$list = DatesFromDaysOnWeek( (new \DateTime('2019-02-01')) , 4 , [4] );
print_r($list);
$list = DatesFromDaysOnWeek( (new \DateTime('2019-02-01')) , 4 , [5] );
print_r($list);
$list = DatesFromDaysOnWeek( (new \DateTime('2019-02-01')) , 4 , [6] );
print_r($list);
$list = DatesFromDaysOnWeek( (new \DateTime('2019-02-01')) , 4 , [0] );
print_r($list);
$list = DatesFromDaysOnWeek( (new \DateTime('2019-03-01')) , 100 , [1,2] );
print_r($list);

Categories