I have look at 100 calendar code and thkink there is no good one. So i came up with my own code, but need som help to understans what i am missing. Thinking now that i mixed up the loops or somthing have try this for a while but cant get it right. The result i getting now is in a line from top to bottom. The dont seem to work. Can somone help me understand what i need to do?
<table border="1">
<?php
//counter array
$counter = 0;
//start days array
$list=array();
//current day
$curDay = date("28", $today);
// mktime(0, 0, 0, date("m"), date("d") , date("Y"));
$today = mktime(0, 0, 0, date("m"), '28', date("Y"));
// curent month
$curentmonth = '09';
// curent year
$year = 2018;
// curent month
$month = date('m');
//loop number of days in month and list them in the array
for($d=1; $d<=31; $d++)
{
$datetime=mktime(12, 0, 0, $curentmonth, $d, $year);
if (date('m', $datetime)==$curentmonth)
$list[]=date('d', $datetime);
//try to get the right 7 weeks in a month start monday
for ($day = 1; $day <=7; $day++) {
$datetime = strtotime($year.'W'.$month.$day);
echo "<tr>";
}
// make this day red
if ($curentmonth === $month && $list[$counter] === $curDay) {
echo "<td bgcolor='ff0000'>$list[$counter]</td>";
$counter++;
// all other days in the month
} elseif ($month === $curentmonth) {
echo "<td>$list[$counter]</td>";
$counter++;
// other month
} else {
echo "<td> </td>";
echo "</tr>";
}
}
?>
I've tried coercing your code into doing what you want, but I'm afraid there are so many logical problems that it's better to just go back to the drawing board entirely.
Looking at your code, it seems what you want to accomplish is a table that displays the weeks of the current month below each other, with each week starting on monday. For table cells that don't contain a date (e.g. the month starts or ends in the middle of a week) you want to display only a space in the cell so that it is empty.
Additionally, you want to highlight the current date.
So essentially, your intended end result is something like this for today (September 30th, 2018):
+----+----+----+----+----+----+------+
| | | | | | 1 | 2 |
+----+----+----+----+----+----+------+
| 3 | 4 | 5 | 6 | 7 | 8 | 9 |
+----+----+----+----+----+----+------+
| 10 | 11 | 12 | 13 | 14 | 15 | 16 |
+----+----+----+----+----+----+------+
| 17 | 18 | 19 | 20 | 21 | 22 | 23 |
+----+----+----+----+----+----+------+
| 24 | 25 | 26 | 27 | 28 | 29 | *30* |
+----+----+----+----+----+----+------+
There are many ways to accomplish this goal. Here's one way of doing it with simple date manipulation, so that there's no need for arrays and multiple loops:
// the month to render and day to highlight
$today = new DateTime();
// we'll need these to check if we're at the day we need to highlight
// or if we're rendering a date that's outside $today's month
$currentDay = $today->format('j');
$currentMonth = $today->format('n');
$daysInCurrentMonth = $today->format('t');
// figure out what Monday needs to kick off our table
$date = (clone $today)->modify('first day of this month');
if ($date->format('w') != 1) {
$date->modify('previous monday');
}
$shouldStopRendering = false;
echo '<table border="1">';
while (!$shouldStopRendering) {
$weekDay = $date->format('w');
$month = $date->format('n');
$day = $date->format('j');
// start a new table row every time we hit a Monday, note that
// since we forced $date to be a Monday above, our table should
// now always start with a <tr>
if ($weekDay == 1) {
echo '<tr>';
}
if ($month != $currentMonth) {
// we're either at the beginning or end of our table
echo '<td> </td>';
} else if ($day == $currentDay) {
// highlight the current date
echo '<td bgcolor="#ff0000">' . $day . '</td>';
} else {
echo '<td>' . $day . '</td>';
}
if ($weekDay == 0) {
// every time we hit a Sunday, close the current table row
echo '</tr>';
// on a Sunday, if we've gone outside the current month **or**
// this Sunday happens to be the last day we need to render,
// stop looping so we can close the table
if ($month != $currentMonth || $day == $daysInCurrentMonth) {
$shouldStopRendering = true;
}
}
// move on to the next day we need to display
$date->modify('+1 day');
}
echo '</table>';
Note this line:
$date = (clone $today)->modify('first day of this month');
The reason I'm cloning $today instead of just creating a new DateTime instance, is that you may wish to change $today to render a different month. Or maybe you're looping over a number of months to render a calendar for a whole year. I don't know which is the case, so I'm basing $date off of whatever $today happens to be.
Don't just do this:
$date = $today->modify('first day of this month');
That'll work, but it will also modify $today which may not be what you want if you want to re-use the current date after rendering the table.
If you're using an older version of PHP, you may not be allowed to do (clone $today)->modify in a single line. If that's the case, just split it up into two lines:
$date = clone $today;
$date->modify('first day of this month');
Here's a demo of this code in action (with some added whitespace for readability of the generated HTML): https://3v4l.org/Z89i8
Related
I'm struggling to formulate this question correctly.
I have a php time() entry in a mysql table column called renew. I have a second entry in the same row under the column type which decides when to update the row, namely: daily or weekly or monthly from the renew column value (date).
How this script works:
In this example on row id 1; the balance must be updated to reflect the budget monthly. The renew date must also be updated to reflect the next monthly incremented date after the update has taken place.
in row id 2; This will take place weekly. and so on.
for example:
| id | renew | type | budget | balance |
|----| ---------- | ---------| ------ | ------- |
| 1 | 1611214417 | monthly | 10,000.00 | 3,000.00 |
| 2 | 1643614417 | weekly | 4,000.00 | 600,00 |
id 1 = 2021-01-21 07:33:37;
id 2 = 2022-01-31 07:33:37;
in row id 1 how to get the next update date from today?
//the time entry
$now = time():
$today = 28/02/2022
$updatetime = $table['renew'];
$updatetype = $table['type'];
How i did the weekly:
from the $updatetime variable above, I incremented the variable with one week until it just passes the $now time.
// what I've done for weekly and seems to be working
for($i = 0; $i < 1000000000; $i++ ){ //random high number for incrementing
if($updatetime < $now){
$updatetime = $updatetime + (86400 * 7); //add one week
} else {
return;
}
}
// the next update will now be the new $updatetime for weekly
How can i do this for the monthly? there are no fixed days in a month, the renew date could fall on the 31 of the month or 29 of February and then the current month could only have 30 days or 28 days.
This is where my issue lies.
If you can assist me.
I would recommend to use PHP DateTime object that is much simpler to manipulate the date time using relative formats
<?php
$today = new DateTime();
$updatetime = '19/01/2021'; // $table['renew']; //19/01/2021
$updatetype = 'weekly'; //$table['type']; //daily || weekly || monthly
$updatetime = (new DateTime())->createFromFormat('d/m/Y', updatetime);
// what I've done for weekly and seems to be working
if($updatetime < $today){
// $updatetime = $today; // reset to today if needed
$updatetime->modify('next week'); // add one week
} else {
return;
}
echo 'Next time of weekly update '. $updatetime->format('Y-m-d') . PHP_EOL . PHP_EOL;
// Output: Next time of weekly update 2022-03-07
// without time reset: Next time of weekly update 2021-01-25
Other examples of date manipulation using relative formats:
<?php
$today = '2022-02-28';
$t = new DateTime($today);
// print the source date time
echo $t->format('Y-m-d') . PHP_EOL;
// examples of continuously manipulate the date time origin
echo $t->modify('next week')->format('Y-m-d') . PHP_EOL;
echo $t->modify('next month')->format('Y-m-d') . PHP_EOL;
echo $t->modify('next year')->format('Y-m-d') . PHP_EOL;
echo $t->modify('next sunday')->format('Y-m-d') . PHP_EOL;
/*
Output:
2022-02-28
2022-03-07
2022-04-07
2023-04-07
2023-04-09
*/
Live demo Live demo without time reset
TIP:
Convert your daily, weekly, monthly into infinitive day, week, month so you will be able to use its value directly using $table['type'] into the date time manipulation:
<?php
$updatetype = 'week'; //$table['type']; //day || week || month
$updatetime->modify('next ' . $table['type']); // add one xxx dynamically!
TIP2*
Use ISO date format Y-m-d to simplify your codding.
$updatetime = '2021-01-19'; //'19/01/2021'
$updatetime = new DateTime($updatetime); // That's it!
Thanks to Ino's answers i worked it out like this:
$today = time(); // can use DateTime() too.
$updatetime = '1611214417'; // $table['renew']; //19/01/2021
$updatetype = 'weekly'; //$table['type']; //daily || weekly || monthly
echo $updatetime.'<br>';
for($i = 0; $i < 100000; $i++){
if($updatetime < $today){
$updatetime = strtotime("+1 week", $updatetime); // can add week month day
} else {
break;
}
}
echo $updatetime.'<br>'; // just for comparison
echo date('Y-m-d', $updatetime); // 2022-03-03 works out perfectly
Please Help !!!
I want free date time slots(data) on new result page in table format associated with the "Search" button so that it outputs the details after the search button has been clicked. Result Image
I know the length of the needed time slot (eg. 1 hour) - Image
An available time slot cannot overlap.
How can this be achieved? What would you think is the best way to approach this?
Process Steps
https://i.stack.imgur.com/FrP09.png
After Hit Seach Button
My DB Structure
Event_ID | dt_start | dt_end
+----------+---------------------+---------------------+
| 3 | 2013-09-21 16:00:00 | 2013-09-21 16:30:00 |
| 21 | 2013-09-21 09:00:00 | 2013-09-21 09:15:00 |
| 5 | 2013-09-21 09:15:00 | 2013-09-21 10:15:00 |
| 64 | 2013-09-21 15:00:00 | 2013-09-21 15:45:00 |
| 32 | 2013-09-21 10:15:00 | 2013-09-21 11:30:00 |
| 6 | 2013-09-21 13:00:00 | 2013-09-21 14:45:00 |
+----------+---------------------+---------------------+
Already thanks for the help,
This answer was based on the ideas from here and here.
The idea of the algorithm is the following:
We create an array where the indexes are all the possible minutes for a date and the values are true.
We fill all the minutes which are included on the existing events to false.
Finally, we look for consecutive time intervals of size $length (in minutes) and once we can traverse the array without finding a false value for $length iterations, we found an empty timeslot for a new event.
<?php
require("database.php");
// Create an array with all the timeslots (in minutes) of a date
// Example: $date = '2018-03-21'
// $timeslots['2018-03-21 00:00:00'] = true;
// $timeslots['2018-03-21 00:01:00'] = true;
// $timeslots['2018-03-21 00:02:00'] = true;
// until
// $timeslots['2018-03-21 23:59:00'] = true;
function getAllTimeslots($date)
{
$currentDate = strtotime($date . " 00:00:00");
$endDate = strtotime($date . " 23:59:59");
$timeslots = [];
while ($currentDate <= $endDate) {
$index = date("Y-m-d H:i:s", $currentDate);
$timeslots[$index] = true;
$currentDate = strtotime("+1 minute", $currentDate);
}
return $timeslots;
}
// Based on the events table registers, fill the intervals of the timeslots array marking them as false, i.e., not available
// Therefore, it will result on an array with trues and falses marking if the specific minute is already filled by an event
function fillUsedTimeslots($date, $timeslots)
{
$queryDate = $date . "%";
$conn = openConnection();
$result = $conn->query("SELECT dt_start, dt_end
FROM events
WHERE dt_start LIKE '" . mysqli_real_escape_string($conn, $queryDate) . "'
OR dt_end LIKE '" . mysqli_real_escape_string($conn, $queryDate) . "'");
if ($result->num_rows > 0) {
while ($row = $result->fetch_assoc()) {
$start = strtotime($row['dt_start']);
$end = strtotime($row['dt_end']);
// update the timeslots data structure with the information of the events' time usage
while ($start < $end) {
$currentDatetime = date("Y-m-d H:i:s", $start);
$timeslots[$currentDatetime] = false;
$start = strtotime("+1 minute", $start);
}
}
}
return $timeslots;
}
// Finally, we need to find a free an interval of time ($length) where we can place an event
// In short words, it iterates over the array of $timeslots looking for $length consecutives trues, i.e.,
// if $length=60, we iterate over the array looking for 60 times of consecutives falses
function findFreeTimeslots($date, $length, $timeslots)
{
$currentDate = strtotime($date . " 00:00:00");
$endDate = strtotime($date . " 23:59:00");
$timeInterval = 0;
while ($currentDate <= $endDate) {
$index = date("Y-m-d H:i:s", $currentDate);
if ($timeslots[$index]) { // Timeslot is free for use
$timeInterval += 1;
} else { // Reset timeInterval
$timeInterval = 0;
}
// We have $length consecutives true, i.e., an interval of $length minutes available for another event
if ($timeInterval == $length + 1) {
echo "<br/>Timeslot found: " . date("Y-m-d H:i:s", strtotime("-" . $length . " minutes", $currentDate)) . " - " . $index;
$timeInterval = 1;
}
$currentDate = strtotime("+1 minute", $currentDate);
}
}
// Main
$timeslots = getAllTimeslots("2013-09-21");
$filledTimeslots = fillUsedTimeslots("2013-09-21", $timeslots);
findFreeTimeslots("2013-09-21", 180, $filledTimeslots);
I applied your example of 3 hours interval, and the result was:
Timeslot found: 2013-09-21 00:00:00 - 2013-09-21 03:00:00
Timeslot found: 2013-09-21 03:00:00 - 2013-09-21 06:00:00
Timeslot found: 2013-09-21 16:30:00 - 2013-09-21 19:30:00
Timeslot found: 2013-09-21 19:30:00 - 2013-09-21 22:30:00
You can restrict the timeslots data structure size to only working times, or a diferent criteria to adapt on your project. And also, refactor it, it's been a long time since I programmed vanilla PHP
I want to create a list of weekday dates with name of the weekday.
If today is monday - 2017-01-02 (Y-m-d), then I want the list to be something like this:
Mon-02 | Tue-03 | Wed-04 | Thu-05 | Fri-06 | Sat-07 | Sun-08
My code below will give such result, if today is monday.
This is what I have so far.
function NextDayDate($day) {
return new DateTime('next ' . $day);
}
$dt = new DateTime();
$today=date("l");
if ($today=="Monday") {
echo $dt->format('d'); // Todays date
echo '</br>';
}
elseif ($today!="Monday"){
echo '</br>';
$nextMonday = NextDayDate('Monday');
echo $nextMonday->format('d'); // Next date
echo '</br>';
}
if ($today=="Tuesday") {
echo $dt->format('d'); // Todays date
echo '</br>';
}
elseif ($today!="Tuesday"){
echo '</br>';
$nextMonday = NextDayDate('Tuesday');
echo $nextMonday->format('d'); // Next date
echo '</br>';
}
If today is Tuesday, then for monday I will have Mon-09 because that is the next date for monday.
Mon-09 | Tue-03 | Wed-04 | Thu-05 | Fri-06 | Sat-07 | Sun-08
I want to keep last days date so the list does not change.
Maybe there is a way to get current weeks day names with date?
It is much more easy:
$a = new DateTime();
$oneDay = new DateInterval("P1D");
// Here you add one day to your date until it will Monday
while ($a->format('D') != 'Mon') {
$a->add($oneDay);
}
// Here you print 7 days from your target Monday
for ($i = 0; $i < 7; $i++) {
echo $a->format("D-d");
$a->add($oneDay);
}
What I need is get listed next month days, every new day on new line.
Actually I want it look next:
date | username1 | username2
_________|___________|__________
| |
Mon - 01 | user5 | user2
| |
Tue - 02 | user3 | user2
....
and so on
Later i will be collect these dates and usernames to and update sql table (same type, like example here).
I have this code:
$workdays = array();
$type = CAL_GREGORIAN;
$month = date('n'); // Month ID, 1 through to 12.
$year = date('Y'); // Year in 4 digit 2009 format.
$day_count = cal_days_in_month($type, $month, $year); // Get the amount of days
//loop through all days
for ($i = 1; $i <= $day_count; $i++) {
$date = $year.'-'.$month.'-'.$i; //format date
$workdays[] = $i;
and with foreach echo i get days 1, 2, 3 ... and so on correctly, everyone on new line. But if i place inside foreach this:
<?php foreach($workdays as $value['date']): ?>
<tr>
<td><?php if ($value['date'] != 'dd'){
setlocale(LC_TIME, 'fi_FI.UTF-8');
echo ucfirst(strftime("%a - %d", strtotime($value['date'])));
} else {
echo 'wrong';
}?></td>
<td> </td>
</tr>
<?php endforeach ?>
I get on every new line Mon - 01.
What is wrong (after that, that i newbie on php)?
Try something like this.
<?php
$day_count = date('t',strtotime('+1 month'));
$month = date('m');
$year = date('Y');
if ($month == 12) { $month = 1; $year++; }
for($i = 1; $i<=$day_count; $i++) {
echo '<tr>';
echo '<td>'.date('D',strtotime("$month/$i/$year")).' '.$i."</td>";
echo '<td> </td>';
echo '</tr>';
}
I am using the following lines of code to get the dates I am trying to generate for some reports and it seems to work fine except in a few instances and I can't see why that would be.
// what week numbers belong to which period
$adminconfig_periods = array(
1=>array(1,2,3,4),
2=>array(5,6,7,8,9),
3=>array(10,11,12,13),
4=>array(14,15,16,17),
5=>array(18,19,20,21,22),
6=>array(23,24,25,26),
7=>array(27,28,29,30),
8=>array(31,32,33,34,35),
9=>array(36,37,38,39),
10=>array(40,41,42,43),
11=>array(44,45,46,47,48),
12=>array(49,50,51,52,53)
);
/**
* Get period no for week no
*
* #param string week the week
* #return int - the period no
*/
function getPeriodForWeek($week) {
global $adminconfig_periods;
$foundperiod = false;
$period = 1;
while(!$foundperiod) {
if(in_array($week, $adminconfig_periods[$period])) {
$foundperiod = true;
} else {
$period ++;
}
}
return $period;
}
$wA = $_GET['wA'];
$yA = $_GET['yA'];
$prev_period = '';
$next_period = '';
if (!isset($wA) || !isset($yA)) {
// period and year aren't set so do it for current period
// period starts on first Sunday of the first week in the period and ends on the last Saturday of the last week in the period
$week = date('W');
$period = getPeriodForWeek($week);
$wA = date('m');
$yA = date('Y');
}
else {
// period and year are set
// period starts on first Sunday of the first week in the period and ends on the last Saturday of the last week in the period
$period = $wA;
}
// get date of first Sunday of the first week in this period
$period_start_week = $adminconfig_periods[$period][0];
// get the Sunday of this week
$period_start = date('Y-m-d', strtotime($yA . 'W' . $period_start_week . '0'));
// get date of last Saturday of the last week in this period
$period_length = count($adminconfig_periods[$period]);
// array indexes start from 0 so we need to take one off this value
$last_element = $period_length - 1;
$period_end_week = $adminconfig_periods[$period][$last_element];
// get the Saturday of this week
$period_end = date('Y-m-d', strtotime($yA . 'W' . $period_end_week . '6'));
On this page I have some select menu controls for changing the period and year number and when it gets to certain periods I get some bizarre dates.
The periods are quite confusing but if anybody has any questions then feel free to ask.
Period | What it Should Be | Actual Result
11 | 28/10/2012 - 01/12/2012 | 28/10/2012 - 01/12/2012
10 | 30/09/2012 - 27/10/2012 | 30/09/2012 - 27/10/2012
09 | 02/09/2012 - 29/09/2012 | 02/09/2012 - 29/09/2012
08 | 29/07/2012 - 01/09/2012 | 29/07/2012 - 01/09/2012
07 | 01/07/2012 - 28/07/2012 | 01/07/2012 - 28/07/2012
06 | 03/06/2012 - 30/06/2012 | 03/06/2012 - 30/06/2012
05 | 29/04/2012 - 02/06/2012 | 29/04/2012 - 02/06/2012
04 | 01/04/2012 - 28/04/2012 | 01/04/2012 - 28/04/2012
03 | 04/03/2012 - 31/03/2012 | 04/03/2012 - 31/03/2012
02 | 29/01/2012 - 03/02/2012 | 10/12/2012 - 01/01/1970
01 | 01/01/2012 - 28/01/2012 | 05/03/2012 - 12/11/2012
As you can see, it seems to go insane for periods 1 and 2 for some reason and I don't understand why.
The parameters are passed in the following way: ?wA=1&yA=2012 and if those are not set it uses the current month and period.
If I was to guess then I'd say it might have something to do with leap years but I thought the code would be able to handle that automatically? Who knows, hopefully a few extra pairs of eyes will spot something stupid I've missed.
Code that echo's the dates
date("d/m/Y", strtotime($period_start)) . ' - ' . date("d/m/Y", strtotime($period_end)) .')';
The error is from those 2 lines
$period_start = date('Y-m-d', strtotime($yA . 'W' . $period_start_week . '0'));
$period_end = date('Y-m-d', strtotime($yA . 'W' . $period_end_week . '6'));
if the week number is 2 for example, adding a 6 to it, it would be 26 (week 26), so you have to add a zero to the left side for the single digit ones. Let's do that with str_pad():
$period_start = date('Y-m-d', strtotime($yA . 'W' . str_pad($period_start_week, 2, 0, STR_PAD_LEFT) . '0'));
$period_end = date('Y-m-d', strtotime($yA . 'W' . str_pad($period_end_week, 2, 0, STR_PAD_LEFT) . '6'));