PHP Select every other Wednesday - php

I need help Select every other Wednesday starting on 5/2/12. This code below selects every other Wednesday starting on the week it currently is. But i need to set the beginning week. I am familiar with PHP, but not familiar with php dates. So please be as specific as possible.
I found this:
$number_of_dates = 10;
for ($i = 0; $i < $number_of_dates; $i++) {
echo date('m-d-Y', strtotime('Wednesday +' . ($i * 2) . ' weeks')). "<br>".PHP_EOL;
}

Use mktime to create your starting date and pass that as the second argument to strtotime so that counting starts from there:
$startDate = mktime(0, 0, 0, 5, 2, 2012); // May 2, 2012
for ($i = 0; $i < $number_of_dates; $i++) {
$date = strtotime('Wednesday +' . ($i * 2) . ' weeks', $startDate);
echo date('m-d-Y', $date). "<br>".PHP_EOL;
}
See it in action.

Give it a date in the string, instead of "Wednesday" (that chooses the next Wednesday), write:
strtotime('20120502 +' . ($i * 2) . ' weeks'))
To choose that date. (Format is yyyymmdd).

If you have PHP 5.2.0 or newer, you can do it easily this way:
$date = new DateTime('2006-05-02');
for ($i=0; $i<10; $i++) {
echo $date->format('m-d-Y').'<br/>'.PHP_EOL;
$date->modify('+1 week');
}

You could also use the DatePeriod and DateInterval classes to make life easier.
Standard disclaimer: both of the classes above require PHP >= 5.3.0.
$number_of_dates = 10;
$start_date = new DateTime("5/2/12");
$interval = DateInterval::createFromDateString("second wednesday");
$period = new DatePeriod($start_date, $interval, $number_of_dates - 1);
foreach ($period as $date) {
echo $date->format("m-d-Y") . "<br>" . PHP_EOL;
}

Related

Working dates between two given dates in Php

Please, i need assistance in this code.I have checked others in Stakeoverflow, but it is not combatible, hence this question. I want to generate all working /weekdays between two dates.I have found a code, but it is generating all days, including weekend. How do i eliminate the weekend from the list or ensure the list generated is ONLY for weekdays?
<?php
$start_Date = date('Y-m-d');
$end_Date = date('Y-m-d', strtotime('30 weekdays'));
//echo $start_Date."<br/>";
//echo $end_Date."<br/>";
// Specify the start date. This date can be any English textual format
$date_from = $start_Date;
$date_from = strtotime($date_from); // Convert date to a UNIX timestamp
// Specify the end date. This date can be any English textual format
$date_to = $end_Date;
$date_to = strtotime($date_to); // Convert date to a UNIX timestamp
// Loop from the start date to end date and output all dates inbetween
$c = 0;
for ($i = $date_from; $i <= $date_to; $i += 86400) {
$c++;
echo $c . "=> " . date("Y-m-d", $i) . '<br />';
}
I expect 30days to be generated but with this code, I am getting 42days . Weekend has been added,instead of weekdays ONLY .
Just add this to your loop:
$w = date('w',$i);// day of week - Sunday == 0, Saturday == 6
if($w == 0 || $w == 6){
continue;
}
DEMO
Your code is almost working only have to add a if checking in your code
your code
for ($i = $date_from; $i <= $date_to; $i += 86400) {
$c++;
echo $c . "=> " . date("Y-m-d", $i) . '<br />';
}
please replace with that one
for ($i = $date_from; $i <= $date_to; $i += 86400) {
$day = date("w", $i);
if($day != 0 && $day!= 6){ // will continue if not Sunday or Saturday
$c++;
echo $c . "=> " . date("Y-m-d", $i) . '<br />';
}
}
You also can take help from php.net
Thanks
You may need to get the day of the week, like date("D"), then use it in your for loop to check..something like this?:
$Weekends = array("Sat","Sun");
for....
$DayOfWeek = date("D",$i);
if(!in_array($DayOfWeek, $Weekend)){
// increment...
}

Loop and Increment date from $_POST variable - PHP

RESOLVED in answer below
Creating a scheduling tool for my users and I am having an issue trying to increment my variable obtained from a dropdown selection:
$date_select = $_POST['date_select'];
I'm sure it's a textbook fix, but to put it simply...I need to increment $date_select by +1 week for 52 weeks.
I have a dropdown menu starting with the current date, and looping to the end of 365 days, incrementing by 1. No problem here.
<select name="date_select" form="create_schedule">
<?php
for($i = 0; $i <= 365; $i++){
$d=strtotime($i . " Day");
$day = date("n-j-y l", $d) . "<br>";
echo "<option>" . $day . "</option>";
}
?>
</select>
This selection is represented by:
$date_select = $_POST['date_select'];
Next to that, before submitting, users can select a radio button - either M, T, W, Th, F, Sat, or Sun to indicate if they would like to apply their request to that selected day, for every week, for the rest of the year. (Which is what I'm trying to do...which is: increment $date_select by "+1 Week" until the for loop is finished)
This selection is represented by:
$repeat = $_POST['repeat'];
This is the closest I've gotten...the code below increments for every "Monday" like I want for example...if $repeat == 'M', but the numerical dates are wrong...
if(isset($_POST['repeat'])){
for($i = 0; $i <= 52; $i++){
$date = strtotime($i . " week", strtotime($date_select));
echo date("n-j-y l", $date) . "<br/>";
}
For example: if the date selected is 7-4-16 Monday, the output is this:
11-26-07 Monday
12-3-07 Monday
12-10-07 Monday
12-17-07 Monday
12-24-07 Monday
12-31-07 Monday
1-7-08 Monday
And so forth...
Thank you in advance.
RESOLVED The issue was in the date format..."m-d-Y" is not equivalent to "m/d/Y" when incrementing days weeks or months in regards to how it is output. Somewhere along the lines, "American" date format values and "European" date format values were getting mixed up. I changed the date format within both of the for-loops and got it working.
"Note: Be aware of dates in the m/d/y or d-m-y formats; if the separator is a slash (/), then the American m/d/y is assumed. If the separator is a dash (-) or a dot (.), then the European d-m-y format is assumed. To avoid potential errors, you should YYYY-MM-DD dates or date_create_from_format() when possible."
http://www.w3schools.com/php/func_date_strtotime.asp
Here is the working solution in case anyone is trying to do something similar
<select name="date_select" form="create_schedule">
<?php
for($i = 0; $i <= 365; $i++){
$d=strtotime($i . " Day");
$day = date("m/d/Y l", $d) . "<br>";
echo "<option>" . $day . "</option>";
}
?>
</select>
if(isset($_POST['repeat'])){
$repeat = $_POST['repeat'];
echo "<br/>";
for($i = 0; $i <= 13; $i++){
$d=strtotime($i . " week", strtotime($date_select));
echo date("m/d/Y l", $d) . "<br/>";
}
}
So on PHP you have to classes that can be really helpfull doing that
\DateTime and \DateInterval
So to do what you want I would recommend
$firstDate = \DateTime::createFromFormat('Y-m-d', $date_select));
$baseDate = clone $firstDate;
$intervalToAdd = new \DateInterval('P1w')
if(isset($_POST['repeat'])){
for($i = 0; $i <= 52; $i++){
$date [$i] = $baseDate->add($intervalToAdd);
echo '<option>'.$date[$i]->format('Y-m-d').'</option>';
}

PHP Calculating dates for every Thursday and Sunday for X weeks

I have written a round robin tournament generator in PHP for an online electronic sports league, and I need to calculate the dates for each game in the tournament. Games are played every Thursday and Sunday over the course of many weeks (the number of weeks is dependent on how many teams are participating). Given the starting week and the number of weeks what would be the best way to calculate those dates?
I'm guessing it requires using some combination of DateTime, DateInterval, and DatePeriod; but I am having trouble figuring out how it would be done.
Update:
Apologies for not providing the code before. Here is the solution I had originally come up with. I didn't know if there was a simpler way of doing it. The function was called submitSchedule where the dates were generated.
<html>
<body>
<?php
function roundRobin($teams) {
$len = count($teams);
$schedule = array();
for ($i = 0; $i < $len - 1; $i++)
{
$home = array_slice($teams, 0, $len / 2);
$away = array_slice($teams, $len / 2);
$day = array();
for ($j = 0; $j < $len / 2; $j++)
{
array_push($day, array($home[$j], $away[$j]));
}
array_push($schedule, $day);
$temp = $away[0];
for ($j = 0; $j < count($away) - 1; $j++)
{
$away[$j] = $away[$j + 1];
}
$away[count($away) - 1] = $home[count($home) - 1];
for ($j = count($home) - 1; $j > 1; $j--)
{
$home[$j] = $home[$j - 1];
}
$home[1] = $temp;
$teams = array_merge($home, $away);
}
return $schedule;
}
function roundRobinBalanced($teams)
{
$schedule = roundRobin($teams);
for ($i = 1; $i < count($schedule); $i+=2)
{
$schedule[$i][0] = array_reverse($schedule[$i][0]);
}
return $schedule;
}
function doubleRoundRobinBalanced($teams)
{
$sched2 = roundRobinBalanced($teams);
for ($i = 0; $i < count($sched2); $i++)
{
$sched2[$i] = array_reverse($sched2[$i]);
}
return array_merge(roundRobinBalanced($teams), $sched2);
}
function tripleRoundRobinBalanced($teams)
{
return array_merge(doubleRoundRobinBalanced($teams), roundRobinBalanced($teams));
}
function submitSchedule($schedule, $start, $intervals, &$con)
{
mysqli_query($con, "TRUNCATE TABLE matches");
$curDate = $start;
echo "<pre>";
for ($i = 0; $i < count($schedule); $i++)
{
for ($j = 0; $j < count($schedule[$i]); $j++)
{
$temp0 = $schedule[$i][$j][0];
$temp1 = $schedule[$i][$j][1];
$temp2 = date_format($curDate, "Y-m-d");
mysqli_query($con,"INSERT INTO matches (T1ID, T2ID, gameDate) VALUES ('$temp0', '$temp1', '$temp2')");
echo "<span style=\"background:lightblue;\">( " . date_format(new DateTime(), "Y-m-d H:i:s") . " )</span>" . "> INSERT INTO matches (T1ID, T2ID, gameDate) VALUES (". $schedule[$i][$j][0] . ", " . $schedule[$i][$j][1] . ", \"" . date_format($curDate, "Y-m-d") . "\")<br>";
}
date_add($curDate, date_interval_create_from_date_string($intervals[$i % count($intervals)]));
}
echo "</pre>";
}
$teams = array();
$con=mysqli_connect("localhost:3306","root","REMOVED","schedule");
// Check connection
if (mysqli_connect_errno()) {
echo "Failed to connect to MySQL: " . mysqli_connect_error();
}
//Select all items from the 'teams' table and order them first in descending order by points, then in ascending order by 'teamName'
$result = mysqli_query($con,"SELECT * FROM teams");
while($row = mysqli_fetch_array($result))
{
array_push($teams, $row['TID']);
}
if (count($teams) % 2 == 1)
{
array_push($teams, null);
}
shuffle($teams);
$schedule = tripleRoundRobinBalanced($teams);
// echo "<pre>" . json_encode($schedule, JSON_PRETTY_PRINT, JSON_FORCE_OBJECT) . "</pre>";
echo "<pre>";
print_r($schedule);
echo "</pre>";
// ---- List of possible DateTime expressions ----
// thursday
// next thursday
// YYYY-MM-DD
// DD/MM/yy
// thursday + 1 day
$start = new DateTime("thursday"); // Indicates the date of the first game
$jump = array("3 days", "4 days"); // Indicates the time intervals of each game (e.g. If day 1 starts on thursday, day 2 starts on sunday, day 3 starts on thursday, etc.)
submitSchedule($schedule, $start, $jump, $con);
mysqli_close($con);
?>
</body>
</html>
The way to achieve this is by using PHP's DateTime classes as you guessed. They are really very useful. I would suggest a little function something like this:-
/**
* #param $startWeek ISO week number of the first week
* #param $numWeeks The number of weeks to run including the first
*
* #return \DateTime[] An array of DateTime objects
*/
function getPlayDays($startWeek, $numWeeks)
{
$numWeeks --;
$result = [];
$currYear = (int)(new \DateTime())->format('Y');
$oneDay = new \DateInterval('P1D');
// Start on the first Thursday of the given week.
$startDate = (new \DateTime())->setISODate($currYear, $startWeek, 4);
$endDate = clone $startDate;
$endDate->add(new \DateInterval("P{$numWeeks}W"));
// End on the Sunday of the last week.
$endDate->setISODate((int)$endDate->format('o'), (int)$endDate->format('W'), 7);
$period = new \DatePeriod($startDate, $oneDay, $endDate->add($oneDay));
foreach($period as $day){
if(4 === (int)$day->format('N') || 7 === (int)$day->format('N') ){
$result[] = $day;
}
}
return $result;
}
foreach(getPlayDays(1, 3) as $playDay){
var_dump($playDay->format('D m-d-Y'));
}
You didn't specify how you would identify the starting week, so I have assumed an ISO week number.
Output:-
string 'Thu 01-02-2014' (length=14)
string 'Sun 01-05-2014' (length=14)
string 'Thu 01-09-2014' (length=14)
string 'Sun 01-12-2014' (length=14)
string 'Thu 01-16-2014' (length=14)
string 'Sun 01-19-2014' (length=14)
See it working.
DateTime manual.
This function will quite happily cope with DST changes, leap years and weeks close to the start and end of the year thanks to the built in magic of the DateTime classes :)
proof or STFU.
Have a look at the strtotime function:
http://www.php.net/manual/en/function.strtotime.php
You could do something like this:
$startDate = "May 15, 2014";
$startDate = strtotime($startDate);
And you could get the start of the Sunday match by simply adding three days:
$nextDate = strtotime("+3 day", $startDate);
Your question is a bit vague, but I think this is what you were asking.
Let's say you have the timestamps of the day of starting week (06:00 AM time)...
Every other date will be 7 days (86400 seconds * 7) in the future.
Let's assume you will run this for 52 weeks (1 year)
$firstThu = 1234567890;
$firstSun = 9876543210;
$nextThus = array();
$nextSuns = array();
for($i=0; $i<52; $i++) {
$nextThus[] = date('d/m/Y', $firstThu + (86400 * 7 * $i));
$nextSuns[] = date('d/m/Y', $firstSun + (86400 * 7 * $i));
}
At the end of the loop you will have two arrays with all the 52 weeks dates.

Reverse whole date in php

OK,
i was using following code to reverse a date to use in php yesterday.
<?php
$d=date("F j Y");
$d=explode(" ", $d);
$month=$d[0];
$day=$d[1];
$year=$d[2];
<?php for ($i=10; $i>0; $i--)
{
$date=$month."-".$day--."-".$year;
echo $date;
?>
this was working for me till yesterday 31 March Night. but in the morning on april 1 its started printing
April-1-2012
April-0-2012
April--1-2012 April--2-2012
and so on.
this was the bad logic i used to reverse a date. i realized it soon.
i want this like following.
April-1-2012
March-31-2012
March-30-2012
March-29-2012
and so on
so how this could be possible ?
Thanks in advance.
Well, this also a logic that work perfect for me i made after post of question. but i am really thankful for all answers. that also making me many things clear.
<?php
$d=date("F j Y");
for ($i=0; $i>-10; $i--)
{
$date="<br>".date('F-j-Y', strtotime("+$i days"));
echo $date;
}
?>
This is probably the quickest way to do it
for($i=1; $i <= 10; $i++) {
echo date("F j Y", time()-($i*24*60*60)); //Instead of 24*60*60 write 86400 to increase slight performance
}
Demo
To get an incremental decrease:
$date = date("F j Y");
for ($i = 0; $i < 10; ++$i)
{
$dates[] = date("F-j-Y", strtotime($date . ' - ' . $i . ' day'));
}
If you are using PHP5.2, you can use the DateTime Class and the modify method.
http://www.php.net/manual/en/datetime.modify.php
<?php
$date = new DateTime('2006-12-12');
$date->modify('-1 day');
echo $date->format('F-j-Y');
?>
In 5.3, you can use the sub method in the DateTime class: http://www.php.net/manual/en/datetime.sub.php
<?php
$date = new DateTime('2000-01-20');
$date->sub(new DateInterval('P1D'));
echo $date->format('F-j-Y');
?>
So an example, using the PHP 5.2 DateTime class (example here: http://ideone.com/uwkjj):
$date = new DateTime();
echo $date->format('F-j-Y');
for($i = 0; $i < 10; $i++){
$date->modify('-1 day');
echo $date->format('F-j-Y');
}
And here is an example using PHP5.3 DateTime class with the sub method
$date = new DateTime();
echo $date->format('F-j-Y');
for($i = 0; $i < 9; $i++){
$date->sub(new DateInterval('P1D'));
echo $date->format('F-j-Y');
}
There is also an interesting note on the PHP help page for strtotime: http://www.php.net/manual/en/function.strtotime.php that says not to use it for mathematical operations. I wonder what that means. But I guess subtracting 1 day should be fine.
From PHP manual:
Using this function for mathematical operations is not advisable. It
is better to use DateTime::add() and DateTime::sub() in PHP 5.3 and
later, or DateTime::modify() in PHP 5.2.

PHP - Is there a simple way to loop between two dates and fill in missing values?

I have 2 dates. Lets say they look like this.
$start = 2010/12/24;
$end = 2012/01/05;
I query the database to look for visits between these two dates. I find some. I then populate an array called stats.
$stats['2010/12/25'] = 50;
$stats['2010/12/31'] = 25;
...
As you can see, there are days missing. I need to fill the missing dates with a value of zero. I was thinking something like this. (I have pulled day / month / year from start and end dates.
for($y=$start_year; $y <= $end_year; $y++) {
for($m=$start_month; $m <=$end_month; $m++) {
for($d=$start_day; $d <= $end_day; $d++) {
This would work fine for the year however the months and days wouldn't work. If the start day is the 15th. Days 1-14 of each subsequent month would be missed. I could have a solution like this then...
for($y=$start_year; $y <= $end_year; $y++) {
for($m=1; $m <13; $m++) {
$total_days = cal_days_in_month(CAL_GREGORIAN, $m, $y) + 1;
for($d=1; $d <= $total_days; $d++) {
I would then need a bunch of if statements making sure starting and end months and days are valid.
Is there a better way of doing this? Or could this even be done in my mysql query?
Just to demonstrate the power of some of PHP's newer interval handling method (mentioned by pgl in his answer):
$startDate = DateTime::createFromFormat("Y/m/d","2010/12/24",new DateTimeZone("Europe/London"));
$endDate = DateTime::createFromFormat("Y/m/d","2012/01/05",new DateTimeZone("Europe/London"));
$periodInterval = new DateInterval( "P1D" ); // 1-day, though can be more sophisticated rule
$period = new DatePeriod( $startDate, $periodInterval, $endDate );
foreach($period as $date){
echo $date->format("Y-m-d") , PHP_EOL;
}
Does require PHP >= 5.3.0
EDIT
If you need to include the actual end date, then you need to add a day to $endDate immediately before the foreach() loop:
$endDate->add( $periodInterval );
EDIT #2
$startDate = new DateTime("2010/12/24",new DateTimeZone("Europe/London"));
$endDate = new DateTime("2012/01/05",new DateTimeZone("Europe/London"));
do {
echo $startDate->format("Y-m-d") , PHP_EOL;
$startDate->modify("+1 day");
} while ($startDate <= $endDate);
For PHP 5.2.0 (or earlier if dateTime objects are enabled)
If you're using PHP5.3 then Mark Baker's answer is the one to use. If (as you say in your comment) you're still on PHP5.2 something like this should help you:
$startdate = strtotime( '2010/12/24' );
$enddate = strtotime( '2012/01/05' );
$loopdate = $startdate;
$datesArray = array();
while( $loopdate <= $enddate ) {
$datesArray[$loopdate] = 0;
$loopdate = strtotime( '+1 day', $loopdate );
}
It will create an array of the unix timestamp of every date between the start and end dates as the index and each value set to zero. You can then overwrite any actual results you have with the correct values.
$start_date = DateTime::createFromFormat('Y/m/d', '2010/12/24');
$end_date = DateTime::createFromFormat('Y/m/d', '2012/01/05');
$current_date = $start_date;
while($current_date <= $end_date) {
$current_date = $current_date->add(new DateInterval('P1D'));
// do your array work here.
}
See DateTime::add() for more information about this.
$i = 1;
while(date("Y/m/d", strtotime(date("Y/m/d", strtotime($start)) . "+ $i days")) < $end) {
... code here ...
$i++;
}
I would calculate the difference between start and end date in days, iterate on that adding a day to the timestamp on each iteration.
$start = strtotime("2010/12/24");
$end = strtotime("2012/01/05");
// start and end are seconds, so I convert it to days
$diff = ($end - $start) / 86400;
for ($i = 1; $i < $diff; $i++) {
// just multiply 86400 and add it to $start
// using strtotime('+1 day' ...) looks nice but is expensive.
// you could also have a cumulative value, but this was quicker
// to type
$date = $start + ($i * 86400);
echo date('r', $date);
}
I have this bit of horrible code saved:
while (($tmptime = strtotime('+' . (int) $d++ . ' days', strtotime($from))) && ($tmptime <= strtotime($to))) // this code makes baby jesus cry
$dates[strftime('%Y-%m-%d', $tmptime)] = 0;
(Set $from and $to to appropriate values.) It may well make you cry, too - but it sort of works.
The proper way to do it is to use DateInterval, of course.

Categories