Get missing date values from array in php dynamically - php

We are creating a system where employees need to update their daily status report. The fundamental purpose of the system is to note the missing dates on which they did not update the status report.
I have found a way to do that by checking the day difference between the 2 array values and then counting & displaying the days. However, I am not sure how to do this dynamically between the 2 array values.
Here's the code I have used along with the output:
//id of the person updating the DSR
$userid = $_id;
// Array to fetch all the DSR by specific user
$fine = getDSRbyUserIdOrderDate($userid);
$today = date('d-m-Y');
$tomorrow = date("d-m-Y", strtotime($today . " +1 day"));
$ok = count($fine) - 1;
//Array to get dates
$d1 = $fine[0]['date'];
$d2 = $fine[1]['date'];
$d3 = $fine[2]['date'];
// Function call to find date difference
$dateDiff = dateDiffInDays($d1, $d2);
$dateDiff1 = dateDiffInDays($d2, $d3);
echo "<h4 style='color:red'>You have missed the DSR on the following dates.</h4>";
for($p = 1; $p < $dateDiff; $p++){
$missingdate = date("d-m-Y", strtotime($d1 . " +$p day"));
echo "<span style='color:red'>$missingdate</span>";
echo "<br />";
}
for($p = 1; $p < $dateDiff1; $p++){
$missingdate = date("d-m-Y", strtotime($d2 . " +$p day"));
echo "<span style='color:red'>$missingdate</span>";
echo "<br />";
}
if($d2 != $today){
echo "<span style='color:red'>$today <i>- Kindly update DSR before midnight</i></span> ";
echo "<br />";
}
Output:

I would create first a list of entries by date and then "paint" it accordingly.
$starting_date = new DateTime('2019-11-23');
$num_days = 10
$from_db_by_date = [];
foreach ($fine as $entry) {
$from_db_by_date[$entry['date']] = $entry;
}
$all_by_date = [];
for ($i = 0; $i < $num_days; $i++) {
$date_str = $starting_date->format('d-m-Y');
$all_by_date[$date_str] = $from_db_by_date[$date_str] ?: null;
$starting_date->modify('+1 day');
}
Now you can loop through $all_by_date, check if the entry is null and act accordingly.

Related

Get week number for given month of year for presentation on calendar

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...

How can I add days to a certain date and skip Sunday and continue on other days?

I'm trying to create an array of dates. The idea is that I add a number x days and the code, when adding the days skip only Sunday.
This is for laravel and I'm using carbon.
$date = Carbon::now();
$dates = [];
for($i = 1 ; $i < 20; $i++){
if($date->dayOfWeek === Carbon::SATURDAY){
echo $dates[$i] = $date->addDay(1)->format('d/m/Y') . " - Sunday <br> ";
} else {
echo $dates[$i] = $date->addDay(1)->format('d/m/Y') . "<br>";
}
When i use the constant SUNDAY to skip this date, its not working.
It goes on to consider Sunday as Monday
The problem is that you are checking if it's Saturday, and after that you're adding a day to it.
You need to echo the date before you add a day to it.
Try this:
if($date->dayOfWeek === Carbon::SUNDAY){ // checking if the current date is a sunday
echo $dates[$i] = $date->format('d/m/Y') . " - Sunday <br> "; // echo and add the current date to the array
$date->addDay(1);
} else {
echo $dates[$i] = $date->format('d/m/Y') . "<br>"; // echo and add the current date to the array
$date->addDay(1);
}
I got it with this code:
$inicialDate = Carbon::now();
$newDate = [];
for($i = 1; $i < 30; $i++)
{
$newDate[$i] = $inicialDate->addDay(1);
if($newDate[$i]->format('l') == "Sunday")
{
$newDate[$i] = $inicialDate->addDay(1);
}
echo $newDate[$i]->format('d/m/Y') . " - " . $newDate[$i]->format('l') . "<br>";
}

Error in comparison in php, to solve question with dates

i'm trying to do a contract management app using php and mysql and i'm having some questions regarding the dates.
I need to know the time that there is between today and specific dates in the contract, or if there is less than a month it should display days left..
the problem is that the comparison to know if the end of contract is in the past or in the future, does'n seems to work!
link to check the code: link to project
$hoje = date_create();
$fim = '2022-11-11';
$fim_data = date_create($fim);
$diff = date_diff( $hoje, $fim_data );
$meses = (($diff->format('%y')*12)+$diff->format('%m'));
$dias = $diff->days;
var_dump($fim < $hoje);
if($fim < $hoje) {
$result = "Contract has ended";
} elseif($meses >=1 ) {
$result = $meses . " months";
echo '<br>';
} else {
$result = $dias . " days";
};
echo '<br>';
echo $result;
You are comparing string with date object
Replace
if($fim < $hoje) {
With
if($fim_data < $hoje) {
Corrected code with solution by Felippe Duarte
$hoje = date_create();
$fim = '2018-11-11';
$fim_data = date_create($fim);
$diff = date_diff( $hoje, $fim_data );
$meses = (($diff->format('%y')*12)+$diff->format('%m'));
$dias = $diff->days;
var_dump($fim_data < $hoje);
if($fim_data < $hoje){$result = "não aplicavel";}
elseif($meses >=1 ){
$result = $meses . " meses";
echo '<br>';}
else{
$result = $dias . " dias";};
echo '<br>';
echo $result;

Amortization Script

I am trying to create an amortization calculator that calculates the declining principal
$x = 1;
$starting_pmt = 26;
$ending_pmt = 36;
$i = 0.0010316264327892;
$p = 410000;
$pmt = 916.84;
$num_pmts = $ending_pmt - $starting_pmt;
echo "<table border=\"1\" align=\"center\">";
echo "<tr><th>PMT Num</th>";
echo "<th>Balance</th>";
echo "<th>Principle</th>";
echo "<th>TTL Principle</th>";
echo "<th>Interest</th>";
echo "<th>Payment</th>";
echo "</tr>";
while ( $starting_pmt <= $ending_pmt ) {
echo "<tr><td>";
echo $starting_pmt;
echo "</td><td>";
echo $p;
echo "</td>";
echo "<td>$prin</td>";
echo "<td>$TTLprin</td>";
echo "<td>$interest</td>";
echo "<td>$TTLPmt</td> </tr>";
$starting_pmt = $starting_pmt + 1;
$p = $p -($p*$i);
$prin = $pmt - ($p * $i);
$interest = $pmt - $prin;
$TTLPmt = $prin + $interest;
//$cumTTL = $$pmt - ($p * $i);
$TTLprin = $prin + $prin;
}
echo "</table>";
?>
balance for each payment and the total principle paid between two values. I also want to calculate the interested paid for each payment and the accumulative interest paid between the two values.
This is what I am starting with.
I cannot figure out how to get the loop to do the math during each iteration............... I have been working my original code and I am getting closer. I cannot get the loop to calculate the cumulative total for principal and interest paid.
<?php
$starting_pmt = 1;
$ending_pmt = 10;
$i = 0.0010316264327892;
$p = 410000;
$pmt = 916.84;
$num_pmts = $ending_pmt - $starting_pmt;
while($x < $num_pmts) {
echo "<tr>";
echo "<td>$x</td>";
echo "<td>".$p - ($p*$i)."</td>";
echo "<td></td>";
echo "<td></td>";
echo "<tr>";
$x++;
I get the math. It's getting the while loop to do what I need. It's not calculating the cumulative total for the principle paid.
Here is a way to make an amortization script, you need to pass back what you want your rate, payment date, and all that good stuff. then I am returning an associative array with all the values for each month.
public static function amortizeLoan($principal, $rate, $term, $extra_days, $payment_date){
$payment = self::getPayment($principal,($rate*100),$term,$extra_days);
$MonthlyInterestRate = $rate / 12;
$Multiplier = 1 + $MonthlyInterestRate;
$TermRate = 1;
for($x=0;$x<$term;$x++){
$TermRate = $TermRate * $Multiplier;
}
$Days = $extra_days - 30;
$oddDayInt = $Days > 0 ? round($principal * ($rate / 365.25) * $Days,2) : 0;
$amortization = [];
$total_interest = 0;
$total_principal = 0;
$remaining_principal = $principal;
$compareDay = date('d', strtotime($payment_date));
for($x=0;$x<$term;$x++){
$this_int_paid = round((($rate)/12) * $remaining_principal,2);
if($x==0){$this_int_paid += $oddDayInt;}
$this_princ_paid = round($payment - $this_int_paid,2);
$this_rem_princ = round($remaining_principal - $this_princ_paid,2);
if($x == ($term-1)){
if($this_rem_princ < 0){
$this_princ_paid-=abs($this_rem_princ);
$payment=round($this_int_paid+$this_princ_paid,2);
}else{
$this_princ_paid+=$this_rem_princ;
$payment=round($this_int_paid+$this_princ_paid,2);
}
}
$remaining_principal -= $this_princ_paid;
$total_interest += $this_int_paid;
$total_principal += $this_princ_paid;
// *** If month days < payment date, payment date falls on the last day of that month.***
$nextMonth = strtotime("last day of next month", strtotime($payment_date));
$lastDayNextMonth = date('d', $nextMonth);
if ($compareDay >= $lastDayNextMonth) {
$payment_date_time = $x ? $nextMonth : strtotime($payment_date);
} else {
$payment_date_time = $x ? strtotime("+1 month", strtotime($payment_date)) : strtotime($payment_date);
}
if ($lastDayNextMonth > date('d', strtotime($payment_date)) && date('t', strtotime($payment_date)) < $compareDay) {
$date = date('Y-m-d', $nextMonth);
$newDate = date_create($date);
$newDate->format('Y-m-d');
$finalDate = date_date_set(
$newDate,
date_format($newDate, 'Y'),
date_format($newDate, 'm'),
$compareDay
);
$formatedDate = $finalDate->format('m/d/y');
$payment_date_time = strtotime($formatedDate);
}
$payment_date = gmdate("Y-m-d", $payment_date_time);
$amortization[] = [
"payment"=>($x+1),
"amount"=>$payment,
"principal"=>$this_princ_paid,
"interest"=>$this_int_paid,
"total_principal"=>$total_principal,
"total_interest"=>$total_interest,
"remaining_balance"=>round($remaining_principal,2),
"payment_date"=>$payment_date
];
}
return $amortization;
}

php holidays in calendar error undefined variable

i found some random code on the net and tried using it for my calendar but i keep getting this error:
Notice: Undefined variable: nextHoliday
this error is referring to the code at the end "RETURN $nextHoliday; "
I believe nextHoliday is defined tho so i tried a few things but nothing makes it work.. can someone please help?
Here's the code:
FUNCTION GetTimeStamp($MySqlDate)
{
$date_array = EXPLODE("-",$MySqlDate); // split the array
$var_year = $date_array[0];
$var_month = $date_array[1];
$var_day = $date_array[2];
$var_timestamp = MKTIME(0,0,0,$var_month,$var_day,$var_year);
RETURN($var_timestamp); // return it to the user
} // End function GetTimeStamp()
FUNCTION ordinalDay($ord, $day, $month, $year)
// ordinalDay returns date of the $ord $day of $month.
// For example ordinalDay(3, 'Sun', 5, 2001) returns the
// date of the 3rd Sunday of May (ie. Mother's Day).
//
// Note: $day must be the 3 char abbr. for the day, as
// given by date("D");
//
{
$firstOfMonth = GetTimeStamp("$year-$month-01");
$lastOfMonth = $firstOfMonth + DATE("t", $firstOfMonth) * 86400;
$dayOccurs = 0;
FOR ($i = $firstOfMonth; $i < $lastOfMonth ; $i += 86400)
{
IF (DATE("D", $i) == $day)
{
$dayOccurs++;
IF ($dayOccurs == $ord)
{ $ordDay = $i; }
}
}
RETURN $ordDay;
} // End function ordinalDay()
FUNCTION getNextHoliday()
// Looks through a lists of defined holidays and tells you which
// one is coming up next.
//
{
$year = DATE("Y");
CLASS holiday
{
VAR $name;
VAR $date;
VAR $catNum;
FUNCTION holiday($name, $date, $catNum)
// Contructor to define the details of each holiday as it is created.
{
$this->name = $name; // Official name of holiday
$this->date = $date; // UNIX timestamp of date
$this->catNum = $catNum; // category, we used for databases access
}
} // end class holiday
$holidays[] = NEW holiday("Groundhog Day", GetTimeStamp("$year-2-2"), "20");
$holidays[] = NEW holiday("Valentine's Day", GetTimeStamp("$year-2-14"), "14");
$holidays[] = NEW holiday("St. Patrick's Day", GetTimeStamp("$year-3-17"), "15");
$holidays[] = NEW holiday("Easter", EASTER_DATE($year), "16");
$holidays[] = NEW holiday("Mother's Day", ordinalDay(2, 'Sun', 5, $year), "3");
$holidays[] = NEW holiday("Father's Day", ordinalDay(3, 'Sun', 6, $year), "4");
$holidays[] = NEW holiday("Independence Day", GetTimeStamp("$year-7-4"), "17");
$holidays[] = NEW holiday("Christmas", GetTimeStamp("$year-12-25"), "13");
$numHolidays = COUNT($holidays);
FOR ($i = 0; $i < $numHolidays; $i++)
{
IF ( DATE("z") > DATE("z", $holidays[$i]->date) && DATE("z") <= DATE("z",
$holidays[$i+1]->date) )
{
$nextHoliday["name"] = $holidays[$i+1]->name;
$nextHoliday["dateStamp"] = $holidays[$i+1]->date;
$nextHoliday["dateText"] = DATE("F j, Y", $nextHoliday["dateStamp"]);
$nextHoliday["num"] = $holidays[$i+1]->catNum;
}
}
RETURN $nextHoliday;
} // end function GetNextHoliday
$nextHoliday = getNextHoliday();
ECHO $nextHoliday["name"]." (".$nextHoliday["dateText"].")";
You have one of two options. Either instantiate empty keys for your array values:
$nextHoliday = array();
$nextHoliday['name'] = '';
$nextHoliday['dateStamp'] = '';
$nextHoliday['dateText'] = '';
$nextHoliday['num'] = '';
$numHolidays = COUNT($holidays);
for ($i = 0; $i < $numHolidays; $i++) {
// ... Blah
}
Or use isset before each array lookup:
echo (isset($nextHoliday['name'] ? $nextHoliday['name'] : '') .
" (" .
(isset($nextHoliday) ? $nextHoliday["dateText"] : '' ) .
")";
Nothing better than the ternary operator for inline conditionals.
It's actually good that we're testing this in January, because otherwise this bug would have bitten you later on. The problem is that you are using less than/greater than to determine what the next holiday is. This fails to take into account the last holiday of the last year.
To fix this, the variable $lastHoliday needs to be a negative representation of the last holiday:
$numHolidays = COUNT($holidays);
$nextHoliday = array('name' => '', 'dateStamp' => '', 'dateText' => '', 'num' => '');
for ($i = 0; $i < $numHolidays - 1; $i++) {
$today = DATE("z");
if ($i == 0) {
$lastHoliday = (365 - DATE("z", $holidays[$numHolidays - 1]->date)) * -1;
} else {
$lastHoliday = DATE("z", $holidays[$i]->date);
}
$futureHoliday = DATE("z", $holidays[$i+1]->date);
//print_r($today); echo "<br />";
//print_r($lastHoliday); echo "<br />";
//print_r($futureHoliday); echo "<br />";
if ($today > $lastHoliday && $today <= $futureHoliday ) {
$nextHoliday["name"] = $holidays[$i+1]->name;
$nextHoliday["dateStamp"] = $holidays[$i+1]->date;
$nextHoliday["dateText"] = DATE("F j, Y", $nextHoliday["dateStamp"]);
$nextHoliday["num"] = $holidays[$i+1]->catNum;
}
}
Also consider typing PHP in lowercase, not uppercase, as it is an almost universal standard in PHP. One true brace style wouldn't hurt either.
$nextHoliday is used in a if but is not declared
Declare the variable before the for:
[...]
$nextHoliday = array();
FOR ($i = 0; $i < $numHolidays; $i++)
[...]

Categories