I'm currently trying to generate a table with every weekday of a month filled with data from a database.
That all works fine, but I want to show the empty dates as well. So:
for (/*each weekday of the month*/) {
if ($row['date'] == /*that day of the month*/)
echo /*the data for that day*/;
else
echo /*empty row*/;
}
That's how I suppose it would look like, but I have no clue on how to do this in a decent fashion.
I hope someone can give me a hand in this.
Final code:
$data = array();
$numofdays = date(t, $monthstamp);
while ($row = $res->fetch_assoc()) {
$monthstamp = mktime(0, 0, 0, $month, 1, $year);
for ($i=1; $i<$numofdays; $i++) {
$monthstamp = mktime(0, 0, 0, $month, $i, $year);
if (strtotime($row['datum']) == $monthstamp) {
echo 'Entry added for day '.$i.'<br>';
$data[] = $i;
}
}
}
for ($i=1; $i<$numofdays; $i++) {
if (in_array($i, $data))
echo 'date ' . $i . ' is full<br>';
else
echo 'date ' . $i . ' is empty<br>';
}
Exactly what you suggested works. Something like this (pseudocode)
// create a date
$year = 2013;
for$month=1; $month<13;$month++;)
{
// create date for each day of each month, or just use an array with number of days in each month, which is easier imho
$MonthStamp = mktime(1, 1, 1, $month, 1, $year);
// get number of days
$NumOfDays = date(t, $MonthStamp);
for($i=1; $i=<$NumOfDays; $i++)
{
if ($row['date'] == // Not sure how your date is formatted. create same date format
echo /*the data for that day*/;
else
echo /*empty row*/;
}
}
You will need to format into table / divs and change format of $row to match your DB row but this should work.
// You would get your dates from DB here
$row = array
(
"01-01-2013" => "New Years Day",
"31-01-2013" => "Holiday",
);
$year = 2013;
for ($month = 1; $month <= 12; $month++)
{
$monthStamp = mktime(1, 1, 1, $month, 1, $year);
$daysInMonth = date('t', $monthStamp);
for($i = 1; $i <= $daysInMonth; $i++)
{
$date = date("d-m-Y", mktime(1,1,1, $month, $i, $year) );
echo $date;
// Check to see if any events in $row and echo result is true
if ( isset($row[$date]) )
{
echo " : " . $row[$date];
}
echo "<br>";
}
}
Related
I'm creating a calendar with Sunday being the start of each week and I want to present the week number of the year before each row of dates.
This is my calendar
my calendar
How can I add week numbers like this:
This is what I need
My code:
<?php
function generate_calendar($month, $year) {
$calendar = array();
$days_in_month = cal_days_in_month(CAL_GREGORIAN, $month, $year);
$first_day_of_month = date('w', strtotime("$year-$month-01"));
$week_number = 1;
$week = array();
// Determine the week number offset
$days_from_january_1st = strtotime("$year-01-01");
$days_to_first_day_of_month = strtotime("$year-$month-01");
$week_number_offset = floor(($days_to_first_day_of_month - $days_from_january_1st) / 604800);
// Check if the last week of the previous month is full (7 days)
$last_week_of_previous_month = $week_number_offset;
if ($month > 1) {
$previous_month = $month - 1;
$previous_month_year = $year;
$previous_month_year = date("Y", strtotime("-1 month" , strtotime("$year-$month-01")));
$previous_month = date("n", strtotime("-1 month" , strtotime("$year-$month-01")));
if ($previous_month == 0) {
$previous_month = 12;
$previous_month_year = $year - 1;
}
$days_in_previous_month = cal_days_in_month(CAL_GREGORIAN, $previous_month, $previous_month_year);
$last_day_of_previous_month = date('w', strtotime("$previous_month_year-$previous_month-$days_in_previous_month"));
if ($last_day_of_previous_month == 6) {
$last_week_of_previous_month=$last_week_of_previous_month + 1;
} else {
// Check if the last week of the previous month only has a few days
$last_week_of_previous_month = $last_week_of_previous_month;
}
}
// Generate the previous month's days
for ($i = 1; $i <= $first_day_of_month; $i++) {
array_unshift($week, "");
}
// Generate the current month's days
for ($i = 1; $i <= $days_in_month; $i++) {
$week[] = $i;
if (count($week) == 7) {
$calendar[$week_number + $last_week_of_previous_month] = $week;
$week_number++;
$week = array();
}
}
// Generate the next month's days
$remaining_days = 7 - count($week);
for ($i = 1; $i <= $remaining_days; $i++) {
$week[] = '';
}
if (!empty($week)) {
$calendar[$week_number + $last_week_of_previous_month] = $week;
}
return $calendar;
}
$year = 2022;
echo "<table>\n";
echo " <tr>\n";
echo " <th colspan='3'>$year</th>\n";
echo " </tr>\n";
echo " <tr>\n";
for($i=1; $i<=12; $i++){
$month_name = date('F Y', strtotime("$year-$i-01"));
$calendar = generate_calendar($i, $year);
echo "<td>\n";
echo "<table>\n";
echo " <tr>\n";
echo " <th colspan='8'>$month_name</th>\n";
echo " </tr>\n";
echo " <tr>\n";
echo " <th>Week</th>\n";
echo " <th>Sun</th>\n";
echo " <th>Mon</th>\n";
echo " <th>Tue</th>\n";
echo " <th>Wed</th>\n";
echo " <th>Thu</th>\n";
echo " <th>Fri</th>\n";
echo " <th>Sat</th>\n";
echo " </tr>\n";
foreach ($calendar as $week_number => $week) {
echo " <tr>\n";
echo " <td>$week_number</td>\n";
foreach ($week as $day) {
if (empty($day)) {
echo " <td></td>\n";
} else {
echo " <td>$day</td>\n";
}
}
echo " </tr>\n";
}
echo "</table>\n";
echo "</td>\n";
if($i==3 || $i==6 || $i==9){
echo " </tr>\n";
echo " <tr>\n";
}
}
echo " </tr>\n";
echo "</table>\n";
?>
Trying to add week number which counts from first week of January (if last week of previous month is not full 7 days then first week of current month start from last week of previous month), but my code only count from first week of current month.
I managed to get the right result (as far as I tested) with IntlCalendar and its FIELD_WEEK_OF_YEAR constant instead of counting Sundays.
I did some refactoring of your function, but ran out of time to do a full reduction of the script (there may still be lines that can be simplified/condensed).
Code: (Demo)
function generate_calendar(int $month, int $year) {
$calendar = [];
$week_number = (IntlCalendar::fromDateTime ("$year-$month-01"))->get(IntlCalendar::FIELD_WEEK_OF_YEAR);
$month_start = new DateTime("$year-$month-01");
// Generate the previous month's days
if ($first_day = $month_start->format('w')) {
$week = array_fill(1, $first_day, '');
}
// Generate the current month's days
$days_in_month = $month_start->format('t');
for ($i = 1; $i <= $days_in_month; $i++) {
$week[] = $i;
if (count($week) == 7) {
$calendar[$week_number] = $week;
$week_number++;
$week = [];
}
}
if ($week) {
// Generate empty days for the next month
$calendar[$week_number] = array_pad($week, 7, '');
}
return $calendar;
}
I don't believe there is any way to set the start day of the week in the standard library of PHP without manual calculation, but you can do it easily with the intl library (make sure the intl PHP extension is enabled):
$cal = IntlGregorianCalendar::createInstance();
// Set start of week to Sunday
$cal->setFirstDayOfWeek(IntlGregorianCalendar::DOW_SUNDAY);
// Get week number of the year for the current date
$weekOfYear = intval(IntlDateFormatter::formatObject($cal, 'w'));
// Advance to the next week
$cal->add(IntlGregorianCalendar::FIELD_WEEK_OF_YEAR, 1);
// ect...
the code snippet below shows a simulation of installments, with fixed expiration dates, divided every 30 days!
I would like to include a periodic expiration date, for example, every 20 days, or 10 every 10, depending on the variable $periodicity;
I have no idea how to do it?
<?php
function calculate_due($num_installment, $first_due_date = null){
if($first_due_date != null)
{
$first_due_date = explode('/',$first_due_date);
$day = $first_due_date[0];
$month = $first_due_date[1];
$year = $first_due_date[2];
}
else
{
$day = date('d');
$month = date('m');
$year = date('Y');
}
$periodicity = 20;
for($installment = 0; $installment < $num_installment; $installment++)
{
if ($periodicity == 30)
echo date('d/m/Y', strtotime('+'.$installment. " month", mktime(0, 0, 0, $month, $day, $year))),'<br/>';
else
echo date('d/m/Y', strtotime('+'.$installment. " month", mktime(0, 0, 0, $month, $periodicity, $year))),'<br/>';
}
}
echo 'Calculates installments from an informed date<br/>';
calculate_due(5, '10/10/2020');
Try this,
<?php
function calculate_due($num_installment, $first_due_date = null, $days = 1){
$start = DateTime::createFromFormat('d/m/Y', $first_due_date);
$end = DateTime::createFromFormat('d/m/Y', $first_due_date);
$end->add(new DateInterval('P'.($num_installment * $days).'D'));
$period = new DatePeriod(
$start,
new DateInterval('P'.$days.'D'),
$end
);
$return = [];
foreach ($period as $date) {
$return[] = $date->format('d/m/Y');
}
return $return;
}
echo 'Calculates installments from an informed date<br/>'.PHP_EOL;
echo implode("\n", calculate_due(5, '10/10/2020', 20));
https://3v4l.org/TLR8a
Change 20 (the last function parameter) to suit the number of days between.
Result:
Calculates installments from an informed date<br/>
10/10/2020<br/>
30/10/2020<br/>
19/11/2020<br/>
09/12/2020<br/>
29/12/2020<br/>
I have project built using laravel and a I have to build a function that counts all the complete quarters that are in the selected date range - the dates used are inserted via input.
Here are the quarters(i used numerical representations for the months)
01 - 03 first quarter
04 - 06 second quarter
07 - 09 third quarter
10 - 12 forth quarter
I would really appreciate your help,because I've been at it for an entire day now and basically have nothing to show for it,i thing I've been trying so hard i'm actually at the point where i'm so tired, i can t think straight.
I do have some code but it;s worthless, because it doesn't work, and any kind of idea or snippet of code is welcomed.
Thanks for your help in advance.
I managed to do this using multiple functions; basically, if this is needed for chart statistics, then a more specific approach might be the case.
I have done this in Laravel with timestamp dates as input (this code can be adapted for getting semesters also :) , it works and is already tested):
public static function getQuartersBetween($start_ts, $end_ts)
{
$quarters = [];
$months_per_year = [];
$years = self::getYearsBetween($start_ts, $end_ts);
$months = self::getMonthsBetween($start_ts, $end_ts);
foreach ($years as $year) {
foreach ($months as $month) {
if ($year->format('Y') == $month->format('Y')) {
$months_per_year[$year->format('Y')][] = $month;
}
}
}
foreach ($months_per_year as $year => $months) {
$january = new Date('01-01-' . $year);
$march = new Date('01-03-' . $year);
$april = new Date('01-04-' . $year);
$june = new Date('01-06-' . $year);
$july = new Date('01-07-' . $year);
$september = new Date('01-09-' . $year);
$october = new Date('01-10-' . $year);
$december = new Date('01-12-' . $year);
if (in_array($january, $months) && in_array($march, $months)) {
$quarter_per_year['label'] = 'T1 / ' . $year;
$quarter_per_year['start_day'] = $january->startOfMonth();
$quarter_per_year['end_day'] = $march->endOfMonth()->endOfDay();
array_push($quarters, $quarter_per_year);
}
if (in_array($april, $months) && in_array($june, $months)) {
$quarter_per_year['label'] = 'T2 / ' . $year;
$quarter_per_year['start_day'] = $april->startOfMonth();
$quarter_per_year['end_day'] = $june->endOfMonth()->endOfDay();
array_push($quarters, $quarter_per_year);
}
if (in_array($july, $months) && in_array($september, $months)) {
$quarter_per_year['label'] = 'T3 / ' . $year;
$quarter_per_year['start_day'] = $july->startOfMonth();
$quarter_per_year['end_day'] = $september->endOfMonth()->endOfDay();
array_push($quarters, $quarter_per_year);
}
if (in_array($october, $months) && in_array($december, $months)) {
$quarter_per_year['label'] = 'T4 / ' . $year;
$quarter_per_year['start_day'] = $october->startOfMonth();
$quarter_per_year['end_day'] = $december->endOfMonth()->endOfDay();
array_push($quarters, $quarter_per_year);
}
}
return $quarters;
}
and getting the years between:
public static function getYearsBetween($start_ts, $end_ts, $full_period = false)
{
$return_data = [];
$current = mktime(0, 0, 0, date('m', $start_ts), date('d', $start_ts), date('Y', $start_ts));
while ($current < $end_ts) {
$temp_date = $current;
$year = new Date($temp_date);
$return_data[] = $year;
$current = strtotime("+1 year", $current); // add a year
}
if ($full_period) {
$return_data[] = $end_ts;
}
return $return_data;
}
, also getting the months needed
public static function getMonthsBetween($start_ts, $end_ts, $full_period = false)
{
$return_data = $month_list = [];
$current = mktime(0, 0, 0, date('m', $start_ts), date('d', $start_ts), date('Y', $start_ts));
while ($current <= $end_ts) {
$temp_date = $current;
$date = new Date($temp_date);
$month_list[] = $date;
$current = strtotime("+1 month", $current); // add a month
}
$start_date_last_month = new Date(array_first($month_list));
$start_date_last_month = $start_date_last_month->startOfMonth()->format('m-d');
$temp_end_date = new Date($start_ts);
$temp_end_date = $temp_end_date->format('m-d');
if ($start_date_last_month < $temp_end_date) {
array_shift($month_list);
}
$end_date_last_month = new Date(end($month_list));
$current_day_month = $end_date_last_month->endOfMonth()->format('m-d');
$temp_end_date = new Date($end_ts);
$end_day_of_month = $temp_end_date->format('m-d');
if ($end_day_of_month < $current_day_month) {
array_pop($month_list);
}
if (count($month_list) == 0) {
$month_list[] = $end_date_last_month->subMonth();
}
$return_data = $month_list;
if ($full_period) {
$return_data[] = $end_ts;
}
return $return_data;
}
You can do something like in this example:
$February = 2;
$October = 10;
$completedQuarters = ceil($October/3) - ceil($February/3); // = 3
What about the quarter in which the date range starts, should it also count? If it should only count if it begins in the first month of a quarter you can check for it like this:
$completedQuarters = ceil($October/3) - ceil($February/3) -1; // = 2
if($February-1%3 == 0) $completedQuarters += 1;
You´re description is not very clear, let me know if that´s what you had in mind.
Not sure if the following is what you are meaning but might be useful
$date_start='2015/03/12';
$date_end='2017/11/14';
$timezone=new DateTimeZone('Europe/London');
$start=new DateTime( $date_start, $timezone );
$end=new DateTime( $date_end, $timezone );
$difference = $end->diff( $start );
$months = ( ( $difference->format('%y') * 12 ) + $difference->format('%m') );
$quarters = intval( $months / 3 );
printf( 'Quarters between %s and %s is %d covering %d months', $start->format('l, jS F Y'), $end->format('l, jS F Y'), $quarters, $months );
/*
This will output
----------------
Quarters between Thursday, 12th March 2015 and Tuesday, 14th November 2017 is 10 covering 32 months
*/
Something like this in the function and you should be set.
use Carbon\Carbon;
$first = Carbon::parse('2012-1-1'); //first param
$second = Carbon::parse('2014-9-15'); //second param
$fY = $first->year; //2012
$fQ = $first->quarter; //1
$sY = $second->year; //2014
$sQ = $second->quarter; //3
$n = 0; //the number of quarters we have counted
$i = 0; //an iterator we will use to determine if we are in the first year
for ($y=$fY; $y < $sY; $y++, $i++) { //for each year less than the second year (if any)
$s = ($i > 0) ? 1 : $fQ; //determine the starting quarter
for ($q=$s; $q <= 4; $q++) { //for each quarter
$n++; //count it
}
}
if ($sY > $fY) { //if both dates are not in the same year
$n = $n + $sQ; //total is the number of quarters we've counted plus the second quarter value
} else {
for ($q=$fQ; $q <= $sQ; $q++) { //for each quarter between the first quarter and second
$n++; //count it
}
}
print $n; //the value to return (11)
I am working on a "cut-off" date and I need to set it on every month. Say, I set the cut-off date to August 25 for this year, then it should be September 25, October 25 and so on till the year ends.
Here's the code I have:
$now = "2015-08-25";
$nextDate = getCutoffDate($now);
echo $nextDate;
function getCutoffDate($start_date)
{
$date_array = explode("-",$start_date); // split the array
// var_dump($date_array);
$year = $date_array[0];
$month = $date_array[1];
$day = $date_array[2];
/*if (date('n', $now)==12)
{
return date("Y-m-d",strtotime(date("Y-m-d", $start_date) . "+1 month"));
}*/
if (date("d") <= $day) {
$billMonth = date_format(date_create(), 'm');
}
else{
$billMonth = date_format(date_modify(date_create(), 'first day of next month'), 'm');
}
// echo date("d").' '. $billMonth.'<br>';
$billMonthDays = cal_days_in_month(CAL_GREGORIAN, ($billMonth), date("Y"));
// echo $billMonthDays.'<br>';
if ($billMonthDays > $day) {
$billDay = $day;
} else {
$billDay = $billMonthDays;
}
}
I got this from here: http://www.midwesternmac.com/blogs/jeff-geerling/php-calculating-monthly
It returns the same date for the next month only, but how do I get the specific date of EACH month of the current year? Kindly leave your thoughts. Still a newbie here, sorry.
In that case, this should be enough:
<?php
for($i=8; $i<=12; $i++) {
echo sprintf('25-%02d-2015', $i) . '<br>';
}
but if you need more flexible way:
<?php
$date = new DateTime('25-08-2015');
function getCutoffDate($date) {
$days = cal_days_in_month(CAL_GREGORIAN, $date->format('n'), $date->format('Y'));
$date->add(new DateInterval('P' . $days .'D'));
return $date;
}
for($i = 0; $i < 5; $i++) {
$date = getCutoffDate($date);
echo $date->format('d-m-Y') . '<br>';
}
This should print:
25-09-2015
25-10-2015
25-11-2015
25-12-2015
25-01-2016
Lets assume I have the following:
$times = array();
for($month = $current_month; $month <= $end_month; $month++) {
$first_minute = mktime(0, 0, 0, $month, 1);
$last_minute = mktime(23, 59, 0, $month, date('t', $first_minute));
$times[$month] = array($first_minute, $last_minute);
}
I now need to loop through all the $months but I am not sure how I can achieve this.
I have tried foreach() but that requires I enter a value for $month. We are assuming the value is not clear.
Do you mean you need to loop through $times?
A simple foreach will do...
foreach ($times as $month => $mins) {
// $month = the month
// $mins[0] = first minute
// $mins[1] = last minute
}
Can try using foreach() like this
foreach($times as $month=>$val){
echo 'Month: ' . $month . ' ';
echo 'First Minute: ' . $val[0] . ' ';
echo 'last Minute: ' . $val[1];
echo '<br />';
}
Perhaps you should use Datetime instead?
$end_month = 12;
$times = [];
$oneMonth = new DateInterval('P1M');
$dt = new Datetime('midnight first day of'); // 2014-12-01T00:00:00+00:00
while($dt->format('m') <= $end_month) {
$firstSecond = $dt->getTimestamp();
$dt->add($oneMonth); // 2015-01-01T00:00:00+00:00
$lastSecond = $dt->getTimestamp() -1;
$times[$dt->format('m')] = [$firstSecond, $lastSecond];
}
foreach ($times as $month => $seconds) {
// ...
}
But you could only work with Datetime object:
while($dt->format('m') <= $end_month) {
$times[] = clone $dt;
$dt->add($oneMonth);
}
foreach ($times as $month) {
echo $month->format('m'), // 12
$month->getTimestamp();
}