Adding to date in a while loop - php

I have a date that goes into a loop that the user specifies. The date will always come from the database formatted as a 'Y-m-d' string. I am aware that I can compare the strings directly as long as they are in that format, however, I have also tried using strtotime to convert the dates to compare them with no luck. I am trying to determine how many paycheck a user has before a payment is due
Here is what I have
$due_date = '2016-12-13';
//count paychecks set to zero and added to by loop
$paychecks = 0;
//users next paycheck ('Y-m-d' ALWAYS)
$next_payday = $user['next_payday']; //equal to '2016-12-02'
//how often they get paid (int)
$frequency = 14;
while(strtotime($next_payday) <= strtotime($due_date)){
//next_payday equals 1480654800 when coming into the loop
//due_date equals 1481605200 when coming into the loop
//add 14 days to the date
$next_payday = date('Y-m-d', strtotime("+" .$frequency." days"));;
//add to paychecks
$paychecks++;
}
The problem is that the loop never stops. It keeps going and going.
Thanks for any help anyone can give me.

Ah, be sure to use strtotime to get integers (representing number of seconds since the epoch) for comparison and multiply your frequency of days by the number of seconds in a day (86400):
$due_date = strtotime('2016-12-25');
//count paychecks set to zero and added to by loop
$paychecks = 0;
//users next paycheck (unixtime for comparison)
$next_payday = strtotime($user['next_payday']);
//how often they get paid (int)
$frequency = 14;
while($next_payday <= $due_date){
//add 14 days to the date
$next_payday += ($frequency * 86400);
//add to paychecks
$paychecks++;
}

Related

php - how to increment a user's known earning every day for 4 months

I want to display to a user an amount per day and increment it until the next 124 days assumed to be four months.
I have a system where a user invest and a total ernable profit is calculated with the percentage ROI for such stock. Assuming someone invested in a stockA that has 20% ROI and matures in 4 months; assuming a user purchased that stockA that is sold $100 and he bought 4 units meaning he spent $400 and will earn
as follows:
$units = 4;
$cost = 100;
$roi = 20/100;
$total_invested = $units * $cost;
$profit = $total_invest * $roi;
// $profit will be $80
My problem is I want to display value of $profit/124 that is the displaying a fraction of total earning to the user daily until maturity of 4 months. I can't figure out how to do that daily not just with loop of 124 iterations.
that is if the user total earning is $80/124 giving 0.65 on the first day and increment it with same value the next day until it reached the end date which is 4 months from now
/**
*
* display and increment earning every day for 4 months or 124 days
*
*/
function display_earning() {
$profit = $profit_roi;
$dateBegin = now();
$dateEnd = "date of 4 month from now";
$earning = 0;
for ($i = 0; $i < 124; $i++) {
$earning += $profit / 124;
return $earning;
}
}
I think your problem is to update and save the updated earning of user for 4 months. To do that you need to write a server level cron-job that run on every day and a script in which you update and save the earning of user and check it has reached 4 months for that user since you started or not.
I hope you want this and that will help you. Happy Learning.
It's not clear what you want your code to do. Do you want it to give the total earned cumulatively by day x or give the total earned on any one day? If it is any one day and you don't want to take compound interest into account the earning will be the same every single day. In which case all your function has to do is return
function return_earnings($profit, $totalDays) {
return $profit / $totalDays;
}
as the amount earned each day will be the same as any other day. If you do want compound interest then you'll need to code that it. I assume you don't as there is no sign of it in the code you supplied.
I get the feeling what you are looking for instead is a list of how much was earned each day cumulatively. If that's the case, the code you've written is more appropriate but needs some modification. At the moment your code is returning $earning after the first iteration of the loop. Moving return to the end of the function should fix that.
function display_earning() {
$profit = $profit_roi;
$dateBegin = now();
$dateEnd = "date of 4 month from now";
$earning = 0;
$totalDays = 124; // You might want to change '124' in future
// and having $totalDays in the for loop makes it more
// obvious what your code is trying to do.
for ($i = 0; $i < $totalDays; $i++) {
$earning += $profit / $totalDays;
}
return $earning;
}
However now because of the line $earning += you will return the sum of earning at the end of $totalDays, ie the $profit, which you already know! You may want the cumulative earnings by a given day to be an item in an array, in which case:
function display_earning() {
$profit = $profit_roi;
$dateBegin = now();
$dateEnd = "date of 4 month from now";
$totalEarning = 0; //renamed to $totalEarning
$earningsByDay = array();
$totalDays = 124;
for ($i = 0; $i < $totalDays; $i++) {
$totalEarning += $profit / $totalDays;
$earningsByDay[$i] = $totalEarning;
}
return $earningsByDay;
}
This will now return an array with each element of the array amounting to the sum earned by that day. For example, $earningsByDay[0] will be the first day, $earningsByDay[11] will be the 10th day etc. If this is what you are looking for, you can use php's native range() function to make your life easier:
function display_earning() {
$profit = $profit_roi;
$dateBegin = now();
$dateEnd = "date of 4 month from now";
$totalEarning = 0; //renamed to $totalEarning
$earningsByDay = array();
$totalDays = 124;
return range(0, $profit, $profit/$totalDays)
}
A few final thoughts:
You say you want to display the amount earned each day. You function does not display anything it just calculates a value and returns it. That's good practise. Have your functions do one thing. Some other function can display the data from this one, or perhaps multiple functions can, each formatting it in a way that is appropriate for your current need. I can't help you with the display as I have no way of knowing what format you want. $dateEnd probably doesn't need to be in the function.
On a related note, another function name might lead to less confusion about what the function does.
I'm not sure what $dateBegin = now(); adds, unless as Moeez Saiyam suggests, you are trying to automate this somehow.
You've defined $profit = $profit_roi; without declaring what $profit_roi is in the scope of your function. I know it was in your introductory notes, but the function won't know that.
Is the function the right place to define $profit and $totalDays? They are probably passed to the function form elsewhere.
Combining these thoughts, this gives us:
function getIncrementalEarnings($profit, $totalDays) { //function renamed to clarify its purpose
return range(0, $profit, $profit/$totalDays)
}

Calculate future date using interval (in number of weeks) and a starting date

I'm trying to write a function to calculate the next date that a piece of equipment needs to be checked. I'm using the code below (it's incomplete.)
function get_next_check(){
$today = date(get_option('date_format'));
$first_check = types_get_field_meta_value( 'first_check', $post_id );
// Interval is a number of weeks- ie. month = 4, year = 52
$interval = types_get_field_meta_value( 'interval', $post_id );
// Calculate the next date after today that the check needs to be performed
$next_check = ;
return $next_check;
}
add_shortcode( 'next_check', 'get_next_check' );
I'm guessing I need to create an array of all possible dates, and compare each to today's date, only returning the next one?
Assuming that $first_check is a string with the date in it, and you want the function to return the same, something like this might work:
$week = 60 * 60 * 24 * 7; // number of seconds in a week
$next_check = strtotime($first_check);
while ($next_check < time()) {
$next_check += $week * $interval; // advance the check time by the desired interval
}
return date(get_option('date_format'), $next_check);
You can eliminate your initialization of the $today variable with this.
You can achieve this on the proposed by Greg Schmidt , or alternatively by doing:
// Calculate the next date after today that the check needs to be performed
$next_check = date(get_option('date_format'), strtotime($today." ".$interval." weeks"));

Calculating frequency interval for tasks

I have a cron job that gets results from the DB to check it the interval set by user falls on today's date. I am currently thinking of doing it as below :
Get the time column for the row. Ex:2017-05-25 00:00:00
Get the frequency set. Ex:Every 2 weeks.
Get the current date in above format. Ex:2017-05-31 00:00:00
Get the difference in days. Ex:6 days.
Convert the frequency set to days. Ex:2 weeks = 14 days;
Divide (difference in time(days)) by (frequency in days). Ex:6/14
This way I will only get the result to be true when 2 weeks have passed since the time set. I.e., 14/14, 28/14, 42/14,...
If the frequency is in months, I can start dividing by 30. But somehow this feels like a hacky way of doing it. So my question is if there is better way of doing this calculation to check the difference.
This is what I have done as explained by above example.
` $frequency = ; // Get the relevant fields from db
$today = date(Y-m-d H:i:s);
foreach ($frequency as $key => $value) {
$frequency_in_days;
$frequency_type = $value->type;
$frequency_repeat = $value->repeat;
if($frequency_type == 1){
$frequency_in_days = $frequency_repeat;
} elseif($frequency_type == 2) {
$frequency_in_days = $frequency_repeat * 7;
} elseif($frequency_type == 3) {
$frequency_in_days = $frequency_repeat * 30;
} elseif($frequency_type == 4) {
$frequency_in_days = $frequency_repeat * 365;
}
// Get number of days spent between start_date and today in days.
$interval = date_diff($value->start_date, $today)->format('%a');
$result = $interval % $frequency_in_days;
if ($result == 0) {
// Frequency falls today! Do the job.
}
}`
Note: The cron job runs this script. The script again needs to check if the today falls under the frequency set.
Also for argument's sake, is this the best logic to calculate the difference?
Thank you.
This will work
Table "schedule"
`last_run` timestamp,
`frequency_seconds` int
example query for tasks that should go every two weeks:
SELECT *
FROM schedule
WHERE TIMESTAMPDIFF(last_run, NOW()) >= frequency_seconds
after fetching rows update last_run to NOW()

Calculating different bands of overtime in php

This is my first time posting here so I'm sorry if I get something wrong. I'm trying to calculate how many hours overtime a worker has worked based on when they signed in. The problem is that we have different bands of overtime:
If the worker works between 5 and 7 then it's 25% extra per hour
If they worked between 7pm and 10pm then its 50% extran for each hour
If the worker works between 10 and 12 then it's 75% extra
If the worker works between 12am and 7am is 100% more
I need to count how many hours they worked at each of the overtime bands
$number_of_25_percent_hours=0;
$number_of_50_percent_hours=0;
$number_of_75_percent_hours=0;
$number_of_100_percent_hours=0;
$clockInTime=$arr['4'];
$clockOutTime=$arr['5'];
$startingPieces=explode(':',$clockInTime);
$startingHour=$startingPieces[0];
$finishingPieces=explode(':',$clockInTime);
$finishingHour=$finishingPieces[0];
//Regular hours are between 7am and and 5pm
//If the worker works between 5 and 7 then it's 25% extra per hour
if(($startingHour<=5)&&($finishingHour>=6)){$number_of_25_percent_hours++;}
if(($startingHour<=6)&&($finishingHour>=7)){$number_of_25_percent_hours++;}
The problem with using the lines above is that it does not work if for example they worked an hour from 6:30 to 7:30.
I'm interested in finding other ways to do this.
you need to store the data more exactly. From your script it looks as if you were only saving the starting hour - which propably is a full number (1,2,3,4 whatsoever)
You script however needs a exact time representation. There are surely many ways to do this but for the sake of a better Script (and as you will propably be able to use some of these more exact values later on) I'd recommend you to store it as a UNIX Timestamp, then get the hour of the Timestamp :
$startingHour = date('H' $timeStampStored)
and check if it's in any of your "bonus" segments. If the user started working at 6:30, the value will hold 6.
This code is completely off the top of my head, untested etc. It's intended as a suggestion of one method you might use to solve the problem, not as a robust example of working code. It uses integers instead of dates, relies on array data being entered in order etc, and probably wouldn't even run.
The basic idea is to set up the scales for each level of overtime multiplier, as well as the hours for non-overtime pay in an array, then loop through that array checking how many hours of each level of overtime have been worked between the inputted times, meanwhile keeping track of a total billable hours value.
$PayMultipliers = array();
$PayMultipliers[0] = array(17,19,1.25);
$PayMultipliers[1] = array(19,22,1.5);
$PayMultipliers[2] = array(22,24,1.75);
$PayMultipliers[3] = array(0,7,1.5);
$PayMultipliers[4] = array(7, 17, 1);
$Start = 3;
$End = 11;
$TotalHours = 0;
for($i = 0; $i <= count($PayMultipliers); $i++)
{
if($Start > $PayMultipliers[$i][0] && $Start < $PayMultipliers[$i][1])
{
$TotalHours += ($PayMultipliers[$i][1] - $Start) * $PayMultipliers[$i][2];
$Start = $PayMultipliers[$i][1];
}
}
echo $TotalHours;
If you want to calculate from 6:30 to 7:30 you'll have to caclulate in minutes, not hours. You can convert the hours and minutes to timestamps, check each time period, and then convert the seconds back to hours.
<?php
$number_of_overtime_hours = array();
$clockInTime = "18:30:00";
$clockOutTime = "19:30:00";
$startingPieces = explode(':',$clockInTime);
$finishingPieces = explode(':',$clockOutTime);
//Timestamps
$startTimestamp = mktime($startingPieces[0],$startingPieces[1],$startingPieces[2]);
$finishTimestamp = mktime($finishingPieces[0],$finishingPieces[1],$finishingPieces[2]);
//finish after 0h
if ($finishTimestamp < $startTimestamp){
$finishTimestamp += 3600 * 24;
}
//set starting and ending points
$overtimePeriods = array(
25 => array (17,19),
50 => array (19,22),
75 => array (22,24),
100 => array (24,31)
);
$overtimeWork = array();
foreach ($overtimePeriods as $key => $val){
//create Timestamps for overtime periods
$beginTimestamp = mktime($val[0],0,0);
$endTimestamp = mktime($val[1],0,0);
//calculate hours inside the given period
$overtimeWork[$key] = (min($finishTimestamp,$endTimestamp) - max($startTimestamp,$beginTimestamp)) / 3600;
//negative values mean zero work in this period
if ($overtimeWork[$key] < 0) $overtimeWork[$key] = 0;
}
var_dump($overtimeWork);

Adding a number to a value every week

I need to add +1 to a value every week at Thursday for example..
Let's assume the value is 5.
Its the 1st of the month and its Thursday.
I want 5 to change to 6 by the 8th of the month.
How do I do that?
I started to come up with something, but since I've never really learned PHP properly I didn't really know what I was doing.
$value = 5;
$num = $value + 1;
BUT, then the $value stays the same and the $num won't change.
Thanks!
Easiest would be to store an initial date and a starting value. "On July 14th, the value is 5":
$initial_date = strtotime('2011-07-14');
$initial_value = 5;
$new_value = $initial_value + floor($initial_date / 86400 / 7);
This will dynamically caculate how many weeks have elapsed since the intial date, and add it to the initial value, giving you your new value.
yes, value stays the same.
If you want to change value, just do it like this
$value = 5;
$value += 1; //or $value++;
Without storing the updated value weekly (in a file or database), you'll have to hardcode the starting timestamp and calculate how many weeks (1 week = 604800 seconds) have passed since then every to determine what to add to $value = 5.

Categories