I'm here trying to make a scenario, where I visit a juice shop to ask the juice seller to provide juice until a certain date, by providing him a certain amount he will provide me juice service until by balance will over.
$rate = 30; //rate of per juice glass
$total_amt = 200; //amt that provide to the seller at start of the service
$start_date = "19-08-2022"; //date of starting the service
$cost = $rate * 7; //rate * days
if($cost <= $total_amt){
echo "Remainder:".$total_amt - $cost; //Money that seller give back to buyer
} else {
echo "you need to pay extra:".$cost - $total_amt; //money need to pay exta for glass
}
Demo
I'm unable to figure out, how can I calculate the number of glass that comes inside $200 based upon the service start date and the next due date.
Example:
In $200 amount, the buyer will get 6 glass with returing balance $20, because If the buyer service start date is 19-08-2022 then the due date is 25-08-2022 (19 + 6 = 25)
So, the output needs to be like:
Number of glass in $200 is: 6
returning balance : $20
next due date: 25-08-2022
Calculation of the due date:
GIVEN a start date (as in your example)
GIVEN the interval (as in your example)
You can easily calculate the according target date via:
Initiate a DateTime object, with your given start date, according to your specified format:
DateTime::createFromFormat("d-m-Y", "19-08-2022")
Create your DateInterval. Given an amount of days, for example two days, the according string you need to pass would need to be: P2D:
new DateInterval('P2D')
Now you just need to add your DateInterval onto your DateTime via the add method, and you get your resulting DateTime object:
var_dump( DateTime::createFromFormat("d-m-Y", "19-08-2022")->add(new DateInterval('P2D')) );
Calculation of the amount of glasses that can be afforded:
If one class costs $glass_price, and you have a total amount of $money_available, you can simply calculate the amount of glasses you can afford via:
floor($money_available / $glass_price)
Calculation of the remaining amount:
And for the returning balance, you would do:
$money_available % $glass_price
Thanks, #DevelJoe for providing the way to calculate the next due date
$rate = 30;
$total_amt = 200;
$start_date = "19-08-2022";
$days = floor($total_amt / $rate); // provide number of days
$glasses = $days; //each day means 1 glass
$cost = $rate * $days; //calculating the per day cost with days
$due_date = DateTime::createFromFormat("d-m-Y", $start_date)->add(new DateInterval('P'.$days.'D'));
if($cost <= $total_amt){
$bal = $total_amt % $cost;
var_dump(array("glasses"=>$glasses, "buyer_bal"=> $bal, "due_date"=>$due_date->format('d-m-Y')));
} else {
$bal = $cost % $total_amt;
var_dump(array("glasses"=>$glasses, "buyer_bal"=> $bal, "due_date"=>$due_date->format('d-m-Y')));
}
Output
array(3) {
["glasses"]=>
float(6) //<-----------Glasses
["returing_bal"]=>
int(20) //<------------Return Balance
["due_date"]=>
object(DateTime)#1 (3) {
["date"]=>
string(26) "2022-08-25 14:09:02.000000" //<----Next due date
["timezone_type"]=>
int(3)
["timezone"]=>
string(16) "Europe/Amsterdam"
}
}
Related
I need to apply discounts to our billing services and am having a devil of a time trying to figure out how to determine the used percent of an applied discount. I have scrapped almost 10 versions of code and think I am just to close to the problem and am not able to see this clearly.
I am trying to make universal function that will use the first/last day of the billing cycle, plus the startDiscount and endDiscount dates to determine what percent to apply to the actual discount; regardless if the discount is a % discount or an actual $ value.
Example: Bill month March 2023 (31 day bill cycle), invoiced services from Mar 1st - Mar 31st. But a 50% discount was applied starting on March 10th - the discount is for 90 days.
This means that roughly 66% of the 50% discount (IE: 33%) needs to be applied to the march invoice, the full 50% of April and May...and then 34% of the 50% discount (IE: 17%) needs to be applied to Junes bill.
So for the applied discounts:
March = 66% of the 50% discount = 33% discount applied to charges
April = 100% of the 50% discount = 50% discount applied to the charges
May = = 100% of the 50% discount = 50% discount applied to the charges
June = 33% of the 50% discount = 17% discount applied to charges
So as each invoice is processed, the first/last day of the invoice range is passed in as well as the start/finish dates of the discount
$discPercent = applyDiscount("2023-03-01","2023-03-31","2023-03-10","2023-06-10") ;
$discPercent = applyDiscount("2023-04-01","2023-04-30","2023-03-10","2023-06-10") ;
$discPercent = applyDiscount("2023-05-01","2023-05-31","2023-03-10","2023-06-10") ;
$discPercent = applyDiscount("2023-06-01","2023-06-30","2023-03-10","2023-06-10") ;
function applyDiscount($firstDay,$lastDay,$startDisc,$endDisc) {
...
...
return $applyThisPercent ;
}
Then $discPercent can be applied an existing 90 day 50% discount OR or can be applied to $100 credit per invoice cycle for 90s
You need to calculate the number of days overlapping the billing period and the discount period and divide it by number of days in the billing period.
With the help of the overlap function in this answer, you get this:
function datesOverlap($start_one, $end_one, $start_two, $end_two) {
if($start_one <= $end_two && $end_one >= $start_two) { //If the dates overlap
return datesDays(min($end_one, $end_two), max($start_two, $start_one));
}
return 0; //Return 0 if there is no overlap
}
function datesDays($start, $end) {
return $start->diff($end)->days+1;
}
function applyDiscount($firstDay, $lastDay, $startDisc, $endDisc) {
$firstDay = new DateTime($firstDay);
$lastDay = new DateTime($lastDay);
$startDisc = new DateTime($startDisc);
$endDisc = new DateTime($endDisc);
$all_days = datesDays($firstDay, $lastDay);
$used_days = datesOverlap($firstDay, $lastDay, $startDisc, $endDisc);
return round(100*$used_days/$all_days);
}
echo applyDiscount("2023-03-01","2023-03-31","2023-03-10","2023-06-10")."\n";
echo applyDiscount("2023-04-01","2023-04-30","2023-03-10","2023-06-10")."\n";
echo applyDiscount("2023-05-01","2023-05-31","2023-03-10","2023-06-10")."\n";
echo applyDiscount("2023-06-01","2023-06-30","2023-03-10","2023-06-10")."\n";
This results in:
71
100
100
33
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)
}
I am trying to calculate a late daily fee of 0.02%, but when the second installment is reached the late fee adds the second installment plus total fee from first installment and now calculate daily fee with new accrued figure.
Example
First installment 5 days late before reaching second instalment:
fee=(arrears*5*0.002)
Second instalment is reached and loan overdue for another 5 days:
fee2=((instalment2+fee)*5*0.002))
Usually the interest use Compound Interest the formula (arrears*(1+0.002)^5), not Simple Interest formula (arrears*5*0.002).
Anyway, I made a piece of code to show how can you do it.
<?php
function CalculateLoan($Value,$Days,$Fee){
//Simple Interest
return $Value + $Value*$Days*$Fee;
//Compound interest
//return $Value * pow(1+$Fee,$Days);
}
// Assuming 6 Instalments of $1000 every 5 days.
$ArrayInstalments = array();
$ArrayInstalments[0]= array("Value"=>1000,"PayDay"=>0);
$ArrayInstalments[1]= array("Value"=>1000,"PayDay"=>5);
$ArrayInstalments[2]= array("Value"=>1000,"PayDay"=>10);
$ArrayInstalments[3]= array("Value"=>1000,"PayDay"=>15);
$ArrayInstalments[4]= array("Value"=>1000,"PayDay"=>20);
$ArrayInstalments[5]= array("Value"=>1000,"PayDay"=>25);
// 30 days passed
$CurrentDay = 30;
// 0.2% fee/day
$Fee = 0.002;
// Initial Debit
$Sum = 0;
foreach ($ArrayInstalments as $key=>$Instalment){
$ThisDebit = CalculateLoan($Instalment['Value'],max($CurrentDay-$Instalment['PayDay'],0),$Fee);
echo 'Instalment:'.$key.' Debit:' . $ThisDebit . '<br/>';
$Sum += $ThisDebit;
}
echo 'Total:' .$Sum. '<br/>';
?>
I have a booking system where users can book a room at any time, and for any number of continuous days. The booking is charged depending on the number of minutes the room is in use.
In the booking system, the start and end time is represented by two timestamps. e.g.
start_time = 1397124000
end_time = 1397129400
From this I can calculate the number of seconds booked, and therefore calculate a charge.
The problem I have is that I'd like to calculate a 50% discount on any bookings made out of peak times - before 8am, and after 6pm. Bookings can be made across these times (i.e. 7am-9am), and so the appropriate proportion should be discounted (50% discount on the 7-8am portion of the 7-9am booking).
My code for calculating this is getting extremely confusing and complicated, as there are several scenarios:
The booking starts and ends during a discount period (e.g. 3am-7am - 4 hours discounted)
The booking starts during a discount, but ends afterwards (e.g. 7am-9am - 1 hour discounted)
The booking starts and ends during a period of non-discount (10am-5pm - no discount)
The booking starts during a period of non-discount, but ends afterwards (5pm-10pm - 1 hour discounted)
The booking spans an entire before-during-after discount period (2am-10pm - 10 hours discounted) or even more complicated (2am on Day 1 to 10pm on Day 5 - 50 hours discounted).
At the moment trying to work out what proportion of a booking is during these pre-8am, post-6pm discount period when only provided with a start and end timestamp is very difficult.
My code is a very large series of if and else statements testing against start and end times, but it is not robust against bookings that span more than one day and is otherwise very messy.
I'm looking for a method that can easily calculate what proportion of a booking is within a discounted time, that accounts for all possible scenarios. A difficult problem!
After pondering many options, the following solution eventually occurred to me.
I wrote a function to move through the booking start and end times in 30 minute intervals, check to see if each time was within a discounted period:
function discount_period($timestamp) {
$lowerTime = mktime (8,0,0,date("n", $timestamp), date("j", $timestamp), date("Y", $timestamp));
$upperTime = mktime (18,0,0,date("n", $timestamp), date("j", $timestamp), date("Y", $timestamp));
if (($timestamp < $lowerTime) || ($timestamp >= $upperTime)) {
return true;
}
else {
return false;
}
}
$discountmins = 0;
$nondiscountmins = 0;
for ($i = strtotime($billingResult->start_time); $i < strtotime($billingResult->end_time); $i += 1800) {
if (discount_period($i)) {
// This is within a discount period of at least 30 minutes
$discountmins += 30;
}
else {
$nondiscountmins +=30;
}
}
$discountedcost = ((($discountmins / 60) * $billingResult->cost_per_hr) * 0.5) / 100;
$nondiscountcost = (($nondiscountmins / 60) * $billingResult->cost_per_hr) / 100;
So it essentially checks to see if the next 30 minute window is within a discount period - if it is, it increments the discounted minute counter, or the non-discounted minute counter if not. At the end it them merely calculates the costs based on the number of minutes.
I am creating an application that charges a client based on time usage of a service. The problem is that the services can have double charge for a pre-specified time period of the day.
So let's say we have a service for printing documents and the charge for using the printer is 5€ per hour and 10€ between 23:00 and 02:00 in the morning. Also a client can rent the printer for as much time as he likes. This can be from 1 minute to months or even years.
Now the specific problem:
Let's say a client comes in my office to rent the printer for 55 hours. Also the rent starts at 20:00 at night.
So the charge must be for 43 hours in single charge and for 12 hours in double charge. Here are two example images:
Now, let me give you some extra info about the hours. In programming, each hour has a timestamp that it is time passed from January 1, 1970 00:00:00 to the time in seconds.
So the date July 05 2012 11:15:40 has the timestamp 1373022940 and the date July 05 2012 11:15:50 has the timestamp 1373022950
In the above example lets say that the first example placed in the date May 1, 2013, so the timestamp for 23:00 will be 1367449200 and the time stamp for three days later at the 02:00 the morning is 1367546400
Now the question:
Is there a way to extract the time duration of the double charged hours from a time frame? If so, what is the process?
Of course there is. You just need to count the interval between dates.
Let's say someone started using service since 8:00 and ended in 16:00.
Price from 8:00 - 16:00 = 2$
Price from 16:00 - 8:00 = 1$
So you need to convert the start of usage time and end of usage time to timestamp
date_default_timezone_set('UTC');
$day_start = '2011-06-22';
$day_end = '2011-06-22';
$start_usage = strtotime($day_start.' 8:00');
$end_usage = strtotime($day_end.' 17:00');
$price_low_rate = 1; //price for using service 16-8
$price_high_rate = 2; // price for using service since 8-16
$fee_for_eight_sixteen = 0; // total price for using service since 8-16
$fee_for_sixteen_eight = 0; // total price for using service 16-8
if($end_usage >strtotime($day_start.' 16:01'))
{
$fee_for_sixteen_eight = ($end_usage - strtotime($day_end.' 16:00'))/3600 * $price_low_rate;
}
if($start_usage >= strtotime($day_start.' 8:00'))
{
$fee_for_eight_sixteen = (strtotime($day_end.' 16:00') - $start_usage)/3600 * $price_high_rate;
}
echo $fee_for_eight_sixteen.' - '.$fee_for_sixteen_eight;
I've tested it and it works. Hope it helps.
Haven't tested this, but I hope it gets you on the right track:
<?php
$price = 0;
$start_timestamp = 1367449200;
$end_timestamp = 1367546400;
$start_time_of_day = 1367449200 % (24*60*60); // Number of seconds from start of the day
$end_time_of_day = 1367546400 % (24*60*60); // Number of seconds from start of the day
// How much time the time period spends in the first day (in seconds)
$first_day_time = (24*60*60) - $start_time_of_day;
// How much time the time period spends in the last day (in seconds)
$last_day_time = (24*60*60) - $end_time_of_day;
$full_days_time = $end_timestamp + $last_day_time - ($start_timestamp + $first_day_time);
$full_days = round($full_days_time/(24*60*60));
// You can calculate by hand how much one full 24-hour day from 00:00 to 00:00 costs
$price += $full_days * (2*10 + 21*5 + 1*10);
// so now the difficulty is the pieces of time on the first day and the last day.
$expensive_time = 0; // Expensive time spent on the first and last day
$cheap_time = 0;
if ($start_time_of_day<2*60*60)
{
// Renting starts before 02:00
$expensive_time += 2*60*60 - $start_time_of_day;
$cheap_time += 21*60*60; // Full 21 hours of cheap time
$expensive_time += 1*60*60; // 1 hour of expensive time from 23:00 to midnight
}
elseif ($start_time_of_day<23*60*60)
{
// Renting starts after 02:00 and before 23:00
$cheap_time += 23*60*60 - $start_time_of_day;
$expensive_time += 1*60*60; // 1 hour of expensive time from 23:00 to midnight
}
else
{
// Renting starts after 23:00
$expensive_time += 24*60*60 - $start_time_of_day;
}
// !! Use a similar strategy for the $end_time_of_day here
$price += ceil($expensive_time/60/60) * 10;
$price += ceil($cheap_time/60/60) * 5;
echo $price." euro";
?>