Consider the following code that was working perfectly yesterday, but now today (30th March), it has stopped working...
<form class="date">
<select name="date" onchange="this.form.submit()">
<?php
for ($i = 0; $i <= 60; ++$i) {
$time = strtotime(sprintf('+%d months', $i));
$value = date('Y-m', $time);
$label = date('F Y', $time);
$nowvalue = date('Y-m');
$nowlabel = date('F Y');
if(isset($_GET['date'])) {
if(strcmp($value,$_GET['date']) == 0) {
//If 0, $value and $_GET['date'] are the same: The option is selected
printf('<option value="%s" selected>%s</option>', $value, $label);
} else {
printf('<option value="%s">%s</option>', $value, $label);
}
} else {
if($value == $nowvalue) {
printf('<option value="%s" selected>%s</option>', $value, $label);
} else {
printf('<option value="%s">%s</option>', $value, $label);
}
}
}
?>
</select>
</form>
This outputs a select list of upcoming months, that onchange, reloads the page with a different query in the URL for the calendar on that page to react on.
If i manually update the query in the URL, it works fine, but this select list is repeating dates, have a look at the image below...
This cant be a coincidence that all of the months with the shortest days are missing, or in fact have been replaced with the same name as the month before?
Does anyone have an idea why this might be happening?
This is because when you loop through dates on a monthly basis on the 31st of the month you will come across months that have less than 30 days. PHP does automatically adjust the date to the last day of the month but instead goes to the end of the month and then adds the remaining days to it and gets the date that way which is the next month.
So if you get to February, which only has 28 days (most years) it will get to the 28th and add three days and give you March 3rd.
To solve this you need to set the date to the first day of the month and then iterate through the dates.
This is just an FYI as I realise that you've added your own answer.
You could instead use DateTime() to simplify your code (if you want).
So you could end up with something like:
<select name="date" onchange="this.form.submit()">
<?php
$selected = DateTime::createFromFormat('Y-m-d', #$_GET['date'] . '-01') ?: new DateTime('first day of this month');
for ($i = 0; $i <= 60; $i++) {
$date = (new DateTime('first day of this month'))->modify("+$i months");
$select = $date == $selected ? 'selected' : '';
printf('<option value="%s" %s>%s</option>', $date->format('Y-m'), $select, $date->format('F-Y'));
}
?>
</select>
Hope this helps!
As John Conde pointed out, this is because todays dates (the 31st) plus one month is actual May 1st, and April is skipped.
I did the following to set the date to the 1st of the month, then plus one month...
<?php
for ($i = 0; $i <= 60; ++$i) {
$firstofthismonth = '01-' . date('m-Y');
$time = strtotime(sprintf($firstofthismonth . '+%d months', $i));
$value = date('Y-m', $time);
$label = date('F Y', $time);
$nowvalue = date('Y-m');
$nowlabel = date('F Y');
if(isset($_GET['date'])) {
if(strcmp($value,$_GET['date']) == 0) {
//If 0, $value and $_GET['date'] are the same: The option is selected
printf('<option value="%s" selected>%s</option>', $value, $label);
} else {
printf('<option value="%s">%s</option>', $value, $label);
}
} else {
if($value == $nowvalue) {
printf('<option value="%s" selected>%s</option>', $value, $label);
} else {
printf('<option value="%s">%s</option>', $value, $label);
}
}
}
?>
Related
I am trying to show results of each month.
Im having this for loop:
foreach ($overview as $day) {
$year = date("Y") - 1;
if ($day->user == $info->id) {
$startDate = new DateTime($day->Calendar_startdate);
$endDate = new DateTime($day->Calendar_enddate);
$s = $startDate->format('Y-m-d');
$e = $endDate->format('Y-m-d');
if ($s > $year) {
$workdays = number_of_working_days($s, $e);
$daysleft = $daysleft + $workdays;
} else {
}
}
}
This for loop is also in an if statement which echos the months.
Now I need to let it work for the months January, February etc...
I am able to not show results if in the previous year which works well.
If you want to compare $s with $year just change $year to :
$time = new DateTime('now');
/*** you can use `now` for today
/* or you can change to a fixed date exmp: 2016-01-01
*/
$year = $time->modify('-1 year')->format('Y-m-d');
Than you can compare $s > $year
I fixed by checking each month if it contained for example -01-
DB::table('Calendar')->where('Calendar_startdate', 'like','%' . $monthnumber . '%')->where('user', $info->id)->where('Calendar_type',2)->get();
does anyone know how I would echo out the selected date as text with the date month and year separated outside of the form? I tried echoing out $date $month and $year outside of the form however this doesn't give me the correct date thankyou for the help
<?
$date = array('16-01-14','16-01-28','16-02-14','16-02-28','16-03-14','16-03-28','16-04-14','16-04-28',
'16-05-14','16-05-28','16-06-14','16-06-28','16-07-14','16-07-28','16-08-14','16-08-28','16-09-14','16-09-28','16-10-14','16-10-28',
'16-11-14','16-11-28','16-12-14','16-12-28');
$currentdate = date('y-m-d');
echo $currentdate;
?>
<form>
<select style="width:200px;">
<?php
foreach ($date as $i => $d) {
if ($currentdate >= $d && ($i == count($date)-1 || $currentdate < $date[$i+1])) {
$selected = "selected";
} else {
$selected = "";
}
list($year, $month, $day) = explode('-', $d);
echo "<option $selected>" . date("m/d/Y", strtotime($d)) . "</option>";
echo 'the current billing period is';
}
?>
</select>
</form>
Inside of your loop add a $selected_int variable like so:
foreach ($date as $i => $d) {
if ($currentdate >= $d && ($i == count($date)-1 || $currentdate < $date[$i+1])) {
$selected = "selected";
$selected_int = $i;
} else {
$selected = "";
}
list($year, $month, $day) = explode('-', $d);
echo "<option $selected>" . date("m/d/Y", strtotime($d)) . "</option>";
echo 'the current billing period is';
}
Then, you can reference it like:
echo date('Y-m-d', strtotime($date[$selected_int]));
Addition
I know you've already accepted the answer, but I also wanted to make a suggestion now that I see what you are using the $date for. Since you know the start date, and it is in 14-day periods, it would be easy to write that as part of the loop.
$start_date = date('Y-m-d', strtotime(date('Y').'-01-01'); //First day of the year, for the sake of argument.
$interval = 14;
for ($i = 0; date('Y') == date('Y', strtotime($start_date.' +'.($i * $interval).' days')); $i++) {//While this year is equal to the start date's year with the added interval [If I knew what your logic here was I could offer a better suggestion]
if ($currentdate >= date("Y-m-d", strtotime($start_date.' +'.($i * $interval).' days')) && (date('Y') < date("Y", strtotime($start_date.' +'.(($i + 1) * $interval).' days')) || $currentdate < date("m/d/Y", strtotime($start_date.' +'.(($i + 1) * $interval).' days')))) {
$selected = "selected";
$selected_int = $i;
} else {
$selected = "";
}
echo "<option $selected>" . date("m/d/Y", strtotime($start_date.' +'.($i * $interval).' days')) . "</option>";
}
Basically, this takes the start date, shows it as the first date option, then adds 14 days to it with each pass through. Your if/else statement should still be the same. It checks to see if you are on the last interval of the year, or if the current date is less than the next interval, and also that the current date is greater than the current interval.
After your loop, you can get the date by:
echo date("m/d/Y", strtotime($start_date.' +'.($selected_int * $interval).' days'));
I know it seems like a lot, but it would save you from having to make a date array to begin with.
Use strtotime instead list.
....
// list($year, $month, $day) = explode('-', $d);
echo "<option $selected>" . date("m/d/Y", strtotime($d)) . "</option>";
....
EDIT: Additional information - your code requires a lot modification and likely some structure changes but assuming this is for testing a method and "how to do" instead a final product.
You need to submit the selected date, catch it in the script and use the selected date to do what you need - i.e. retrieve data from database - and this should give you some idea.
<?php
// You need to create these dates by using another method. You cannot hard code these. You can create it with date functions easily.
$date = array('16-01-14','16-01-28','16-02-14','16-02-28','16-03-14','16-03-28','16-04-14','16-04-28','16-05-14','16-05-28','16-06-14','16-06-28','16-07-14','16-07-28','16-08-14','16-08-28','16-09-14','16-09-28','16-10-14','16-10-28','16-11-14','16-11-28','16-12-14','16-12-28');
// Checking if we have a posted form, with the button name user clicked
if (isset($_POST["btnSubmit"])) {
// This is your selected day - use it where you need:
$selectedDate = $_POST["selectedDate"];
// This is where your model start singing and gets necessary info for this date - just printing here as sample
print $selectedDate;
// I need dropDownDate to compare in the SELECT to preselect the appropriate date
$dropDownDate = strtotime($selectedDate);
} else {
// First time visit, preselect the nearest date by using current date
$dropDownDate = time();
}
?>
<form method="post">
<select name="selectedDate" style="width:200px;">
<?php
foreach ($date as $i => $d) {
if ($dropDownDate >= strtotime($d) &&
(!isset($date[$i+1]) || ($dropDownDate < strtotime($date[$i+1])))
) {
$selected = 'selected="selected"';
} else {
$selected = "";
}
list($year, $month, $day) = explode('-', $d);
echo "<option $selected>" . date("m/d/Y", strtotime($d)) . "</option>";
}
?>
</select>
<input type="submit" name="btnSubmit" value="Submit">
</form>
Note that I added a "submit" type input (to submit the form) and changed form method to "post", finally named SELECT as "selectedDate". I also changed your date comparison code line in the loop.
Hope this helps.
I keep having issues on the last day of the month, other than that this code works just fine to display all 12 months starting at the current month. On the last day of the month I get duplicates of some months and others do not show at all. Any help would be appreciated. Thanks.
<select id="month" name="month">
<?php
//lists months
for ($i = 0; $i <= 11; ++$i)
{
$time = strtotime(sprintf('+%d months', $i));
$value = date('m', $time);
$label = date('F', $time);
//if month is set stay on that month
if($month==$value)
{ printf('<option value="%s" selected="selected">%s</option>' , $value, $label);
}
else
{printf('<option value="%s">%s</option>', $value, $label);}
}
?>
//first month shows instead of blank
$("#target option:first")
</select>
You may be running into an issue where from the current day X months later is skipping over a month.
Instead of
strtotime(sprintf('+%d months', $i));
Try using
strtotime(sprintf('first day of +%d month', $i));
<?php
function months($selctedMonth='january'){
$months='<select name="month" size="1">';
for ($i = 12; $i > 0; $i--) {
$time = strtotime(sprintf('-%d months', $i));
$label = date('F', $time);
$selctedM = strtolower($selctedMonth) == strtolower($label) ? 'selected' : '';
$months.="<option value='$label' $selctedM >$label</option>";
}
$months.="</select>";
return $months;
}
echo months();
?>
By default, January will be displayed as selected.
if you write <?php echo months('march'); ?> then march will be selected by default.
I need to generate an html code of a list of 10 open days following the current day, by open days I mean business days (m,t,w,t and f), I'm using the following function to translate the date to french:
function f_date() {
$temps = time();
$jours = array('Dimanche', 'Lundi', 'Mardi', 'Mercredi', 'Jeudi', 'Vendredi', 'Samedi');
$jours_numero = date('w', $temps);
$jours_complet = $jours[$jours_numero];
$NumeroDuJour = date('d', $temps);
$mois = array(' ', 'Janvier', 'Février', 'Mars', 'Avril', 'Mai', 'Juin', 'Juillet', 'Août', 'Septembre', 'Octobre', 'Novembre', 'Décembre');
$mois_numero = date("n", $temps);
$mois_complet = $mois[$mois_numero];
$an = date('Y', $temps);
$fr_temps = "$jours_complet, $NumeroDuJour $mois_complet $an";
return "$fr_temps";
}
echo "<br/>".f_date();
And i want to generate the following result:
<select name="ladate">
<option selected="selected" value="Mardi, 29 mai 2012">29 mai 2012</option>
<option value="Mercredi, 30 mai 2012">30 mai 2012</option></select>
....
<option value="Vendredi, 15 juin 2012">15 juin 2012</option></select>
</select>
Please tell me if you need further information.
Thank you.
Since you are only looking for MTWTF and you want the next 10 days, you can always safely look for the next 14 days and ignore the weekends and that will give 10 days. It won't work for holidays or anything like that but you can change it if you need to do that. I'll give you the pseudo-code here, I'll leave all the array mapping and text output to you
for ($days_to_add : 1 to 14) {
$new_date = date_add($days_to_add);
// check the day of the week
if (date('N', $new_date) >= 6) {
// ignore it, it's a weekend
continue;
}
// output the option tag for $new_date
echo "<option ... </option>"
}
This relies on the 10 and 14 day assumption, if you wanted to change that number you could add some sort of counter and only increment the counter if you were looking at a weekday/non-holiday
Just create a loop, increase the days up to ten and ignore all non open days (Sat, Sun). date('N') is your friend to detect the weekday of a given date.
<?php
$i = $openDay = 0;
while($openDay < 10) {
$i++;
$time = strtotime('+'.$i.' days');
$day = date('N', $time);
if ($day == 6 or $day == 7) { // ignore Saturdays and Sundays
continue;
}
echo f_date($time).'<br>';
$openDay++;
}
You also have to modify your date_f() function to use $temps as parameter.
<?php
function f_date($temps = null) {
// $temps = time();
// ...
}
I have a php calendar at http://idea-palette.com/aleventcal/calendar.php.
I want the days that are not part of the current month to show up grayed out(which it does now), and I want it to appear as those are the days of the previous and next month.
As it is now, the days that appear before the first day of the month appear as negative numbers(-1,-2,-3, and so on) and the days that appear after the last day of the month just continue on, so if a month ends on the 31st, then it would read 32, 33, 34, and so on.
I'm trying to figure out a conditional statement with some sort of loop where I could see if it is greater than the total days and then do something else. The problem I see is that the table cell that is being created is being looped, so if I do just $day+1, then instead of 32, it will just read 33.
Here's my code:
for($i=0; $i< $total_rows; $i++)
{
for($j=0; $j<7;$j++)
{
$day++;
//if the current day is less or equal to the total days in the month
if($day>0 && $day<=$total_days_of_current_month)
{
$date_form = "$current_year/$current_month/$day";
echo '<div class="date_has_event" href="#"><td';
//If the date is today then give the td cell the 'today' class
if($date_form == $today)
{
echo ' class="today"';
}
//check if any event stored for the date
if(array_key_exists($day,$events))
{
//adding the date_has_event class to the <td> and close it
echo ' class="date_has_event">'.$day;
//adding the eventTitle and eventContent wrapped inside <span> & <li> to <ul>
echo '<div class="events"><ul>'.$events[$day].'</ul></div>';
}
}
else //if the current day is less or more than the total days in the month
{
//then create a table cell with the current day of the mont
echo '<td class="padding">' . $day . ' </td>'; h
}
}
}
just subtract the number of days in the current month of the day is positive:
else //if the current day is less or more than the total days in the month
{
if($day > 1){
echo '<td class="padding">' . ($day - $total_days_of_current_month) . ' </td>'; // the next month
} else {
echo '<td class="padding">' . $day . ' </td>'; //then create a table cell with the current day of the month
}
}
Here's part of a calendar function I recently wrote, you can hopefully get some ideas from it.
// $month is a UNIX timestamp
// resetting to 1st of the month
$date = getdate(mktime(0, 0, 0, date('n', $month), 1, date('Y', $month)));
// resetting to first day in grid
$date = getdate(strtotime("-$date[wday] days", $date[0]));
$out = array();
$lastDay = mktime(0, 0, 0, date('n', $month), date('t', $month), date('Y', $month));
while ($date[0] <= $lastDay) {
$row = array();
for ($x = 0; $x <= 6; $x++) {
$attr = array('class' => 'weekday '.low(date('D', $date[0])));
if (date('n', $month) != $date['mon']) {
$attr['class'].= ' prevNextMonth';
}
if (date('Y-m-d') == date('Y-m-d', $date[0])) {
$attr['class'].= ' today';
}
$row[] = array($date['mday'], $attr);
$date = getdate(strtotime("+1 day", $date[0]));
}
$out[] = $row;
}
// makes table rows out of the array, considers the $attr array as well
$out = $this->Html->tableCells($out);
$out = sprintf('<table><tbody>%s</tbody></table>', $out);
You don't need Steve's conditional: instead use
echo '<td class="padding">' . date("j",mktime(12,0,0,$current_month,$day,$current_year)) . ' </td>';
mktime handles out-of-range dates my moving them into the next or previous month, which is exactly what you want.