I'd like to have a php function which will deduct a value, say, 50 from an initial integer of say, 500 at a set interval.
For example: Every 30 days, deduct 50 from 500. So after 90 days, you are left with 350, etc.
I can do subtractions, it's the interval routine that I can't figure out.
If not PHP, JS is great too. This is used to count down a value from the beginning of the year, to the end.
You have a starting number, and you trying to figure out what your current value is. Its a basic total - (time pass * decrement) problem.
So example, You have your original time.
$originalDate = '2011-01-01';
$now = '2011-03-01';
//it will count no. of days
$dateDiff=(strtotime($now) - strtotime($originalDate))/ (60 * 60 * 24);
$startingValue = 500;
$descrement = 50;
$currentValue = $startingValue - ($dateDiff/30*$descrement);
if you want this in a function:
/* deduct()
*
* #param $start - the starting amount to subtract from
* #param $amount - the amount to subtract by
* #param $interval - the interval between deductions
* #param $current_time - the current time to measure against the interval
*
* #return the amount after deduction $amount
* every $interval from $start until $current_time
*/
function deduct($start, $amount, $interval, $current_time) {
return $start - ($amount * floor($current_time / $interval));
}
You can easily pass in a time value using time(), or something like that, formatted into your unit of time.
Related
i am writing a script that checks for increase in date to know whether or not to add a value to an existing variable.
Though i have been able to get some help here, it still appears i'm stuck with checking if the day has increased.
PHP CODE
<?php
$now = time(); // or your date as well
$your_date = strtotime("2018-09-05");
$datediff = $now - $your_date;
$alreadySpentDays = round($datediff / (60 * 60 * 24));
$userEarnings = 0;
// i want to be able to check if the day has increased and if it has i want to be able to add $10 to userEarning variable daily
?>
<p><?=$userEarnings?></p>
There is no point in calculating it each day, just do the calculation when needed.
$start_date is the date you want to start counting from, where the earning is 0.
Then just calculate the number of days that has passed by and multiply with 10.
$now = time(); // or your date as well
$start_date = strtotime("2018-09-04");
$datediff = $now - $start_date;
$alreadySpentDays = round($datediff / (60 * 60 * 24));
echo $alreadySpentDays * 10; // 20, since it's two days of earnings (september 4 and 5)
Use DateTime::diff (http://php.net/manual/en/datetime.diff.php)
$userEarnings = 0;
$now = new DateTime(); //now
$your_date = new DateTime("2010-09-05");
$diff = $now->diff($your_date);
if ($diff->days > 0) {
$userEarnings += 10;
}
I'm totalling up time like so.
$totalTimeDiff = new DateTime("#0");
foreach($dbrecords as $row)
{
$timeDiff = date_diff( ... two datetimes from my database ... )
$totalTimeDiff->add($timeDiff);
}
So $totalTimeDiff is a DateTime object with the sum of all of the time differences added together (so a sum of all of the durations). How can I get the total time in seconds?
Why not keep it simple?
$totalseconds=0;
foreach($dbrecords as $row)
$totalseconds+=(UNIX_TIMESTAMP(second_datetime)-UNIX_TIMESTAMP(first_datetime));
use strtotime function
echo strtotime('01:00:00') - strtotime('TODAY');
$totalTimeDiff->format('U');
Taking moonwave99's advice, I used DateInterval (can't remember why I went with DateTime for that in the first place, possibly a workaround for something at another stage of the project) and computed the seconds by adding each value to the total after converting it to seconds (converting hours and minutes to seconds and summing them up). I did this by using the DateInterval class's seconds property as well as the following function to convert a DateInterval to seconds (Note: only accounted for days, hours, minutes, and seconds for my specific case as there's no chance the amount will exceed one month):
function convertDateIntervalToSeconds($dateInterval)
{
$days = $dateInterval->d * 24 * 60 * 60;
$hours = $dateInterval->h * 60 * 60;
$minutes = $dateInterval->i * 60;
$seconds = $dateInterval->s;
return $hours + $minutes + $seconds;
}
I have data for 2 profiles that I would like to compare.
Each profile has a 'total points' value and a 'points per day' value and I would like to calculate how many days it would take the hare to overtake the tortoise.
$hare_points = 10000;
$hare_ppd = 700;
$tortoise_points = 16000;
$tortoise_ppd = 550;
What would be the most efficient way to determine how many days it would take for the hare to catch up with the tortoise? My first through was to run a loop to just count through the days, but very quickly realised there must be an efficient algorithm out there that will not want to destroy the server that it is running on lol
Assuming ppd is points per day:
<?php
$hare_points = 10000;
$hare_ppd = 700;
$tortoise_points = 16000;
$tortoise_ppd = 550;
$hare_diff = $tortoise_points - $hare_points;
$hare_ppd_diff = abs($tortoise_ppd - $hare_ppd);
$days = $hare_diff/$hare_ppd_diff;
echo $days; // 40
/* Test:
* 40 * 700 = 28000; hare
* 40 * 550 = 22000; tortoise
*
* hare_p = 28000 + 10000 = 38 000
* toit_p = 22000 + 16000 = 38 000
*
* So the math is right. On 40th day, they are equal
*
*/
It's a simple set of equations to solve.
hare_total = hare_points + hare_ppd * days
tortoise_total = tortoise_points + tortoise_ppd * days
You're trying to find out the day the points are the same, so:
hare_total = tortoise_total
hare_points + hare_ppd * days = tortoise_points + tortoise_ppd * days
hare_points - tortoise_points = (tortoise_ppd - hare_ppd) * days
So there's your answer:
$days = ($hare_points - $tortoise_points) / ($tortoise_ppd - $hare_ppd)
Just plug that into your function and round up / down to an integer depending on how you want to interpret the answer.
I am trying to get the PHP "DateInterval" value in "total minutes" value. How to get it? Seems like simple format("%i minutes") not working?
Here is the sample code:
$test = new \DateTime("48 hours");
$interval = $test->diff(new \DateTime());
Now if I try to get the interval in total days, its fine:
echo $interval->format('%a total days');
It is showing 2 days as output, which is totally fine. What I am trying to get if to get the value in "total minutes", so I tried:
echo $interval->format('%i total minutes');
Which is not working. Any help appreciated to get my desired output.
abs((new \DateTime("48 hours"))->getTimestamp() - (new \DateTime)->getTimestamp()) / 60
That's the easiest way to get the difference in minutes between two DateTime instances.
If you are stuck in a position where all you have is the DateInterval, and you (like me) discover that there seems to be no way to get the total minutes, seconds or whatever of the interval, the solution is to create a DateTime at zero time, add the interval to it, and then get the resulting timestamp:
$timeInterval = //the DateInterval you have;
$intervalInSeconds = (new DateTime())->setTimeStamp(0)->add($timeInterval)->getTimeStamp();
$intervalInMinutes = $intervalInSeconds/60; // and so on
I wrote two functions that just calculates the totalTime from a DateInterval.
Accuracy can be increased by considering years and months.
function getTotalMinutes(DateInterval $int){
return ($int->d * 24 * 60) + ($int->h * 60) + $int->i;
}
function getTotalHours(DateInterval $int){
return ($int->d * 24) + $int->h + $int->i / 60;
}
Here is the excepted answer as a method in PHP7.2 style:
public static function getMinutesDifference(\DateTime $a, \DateTime $b): int
{
return abs($a->getTimestamp() - $b->getTimestamp()) / 60;
}
That works perfectly.
function calculateMinutes(DateInterval $int){
$days = $int->format('%a');
return ($days * 24 * 60) + ($int->h * 60) + $int->i;
}
This question is about minutes but if you want to recalculate every carry over points (like I needed to) you can use this solution suggested by #glavic in the comments on the php.net man page (simplified and turned into a function):
private function calculateCarryOverPoints(\DateInterval $dateInterval): \DateInterval
{
$from = new \DateTime;
$to = clone $from;
// Add time of dateInterval to empty DateTime object
$to = $to->add($dateInterval);
// Calculate difference between zero DateTime and DateTime with added DateInterval time
// Which returns a DateInterval object $diff with correct carry over points (days, hours, minutes, seconds etc.)
return $from->diff($to);
}
Ok so I am working on a calendar application within my CRM system and I need to find the upper and lower bounds of the half an hour surrorunding the timestamp at which somebody entered an event in the calendar in order to run some SQL on the DB to determine if they already have something booked in within that timeslot.
For example I have the timestamp of 1330518155 = 29 February 2012 16:22:35 GMT+4
so I need to get 1330516800 and 1330518600 which equal 16:00 and 16:30.
If anyone has any ideas or think I am approaching developing the calendar in a stupid way let me know! Its my first time on such a task involving so much work with times and dates so any advice appreciated!
Use modulo.
$prev = 1330518155 - (1330518155 % 1800);
$next = $prev + 1800;
The modulo operator gives the remainder part of division.
I didn't read the questions clearly, but this code will round to the nearest half hour, for those who don't need the range between the two. Uses some of SenorAmor's code. Props and his mad elegant solution to the correct question.
$time = 1330518155; //Or whatever your time is in unix timestamp
//Store how many seconds long our rounding interval is
//1800 equals one half hour
//Change this to whatever interval to round by
$INTERVAL_SECONDS = 1800; //30*60
//Find how far off the prior interval we are
$offset = ($time % $INTERVAL_SECONDS);
//Removing this offset takes us to the "round down" half hour
$rounded = $time - $offset;
//Now add the full interval if we should have rounded up
if($offset > ($INTERVAL_SECONDS/2)){
$nearestInterval = $rounded + $INTERVAL_SECONDS;
}
else{
$nearestInterval = $rounded
}
You could use the modulo operator.
$time -= $time % 3600; // nearest hour (always rounds down)
Hopefully this is enough to point you in the right direction, if not please add a comment and I'll try to craft a more specific example.
PHP does have a DateTime class and a whole slough of methods that it provides. You could use these if you like, but I find it easier to use the built-in date() and strtotime() functions.
Here's my solution:
// Assume $timestamp has the original timestamp, i.e. 2012-03-09 16:23:41
$day = date( 'Y-m-d', $timestamp ); // $day is now "2012-03-09"
$hour = (int)date( 'H', $timestamp ); // $hour is now (int)16
$minute = (int)date( 'i', $timestamp ); // $minute is now (int)23
if( $minute < 30 ){
$windowStart = strtotime( "$day $hour:00:00" );
$windowEnd = strtotime( "$day $hour:30:00" );
} else {
$windowStart = strtotime( "$day $hour:30:00" );
if( ++$hour > 23 ){
// if we crossed midnight, fix the date and set the hour to 00
$day = date( 'Y-m-d', $timestamp + (24*60*60) );
$hour = '00';
}
$windowEnd = strtotime( "$day $hour:00:00" );
}
// Now $windowStart and $windowEnd are the unix timestamps of your endpoints
There are a few improvements that can be made on this, but that's the basic core.
[Edit: corrected my variable names!]
[Edit: I've revisited this answer because, to my embarrassment, I realized that it didn't handle the last half-hour of a day correctly. I've fixed that issue. Note that $day is fixed by adding a day's worth of seconds to the timestamp -- doing it this way means we don't have to worry about crossing month boundaries, leap days, etc. because PHP will format it correctly for us regardless.]
If you need to get the current time and then apply the rounding (down) of the time, I would do the following:
$now = date('U');
$offset = ($now % 1800);
$now = $now-$offset;
for ($i = 0;$i < 24; $i++)
{
echo date('g:i',$now);
$now += 1800;
}
Or you could round up by adding the offset, and do something more than just echo the time. The for loop then displays the 12 hours of increments. I used the above in a recent project.
I'd use the localtime and the mktime function.
$localtime = localtime($time, true);
$localtime['tm_sec'] = 0;
$localtime['tm_min'] = 30;
$time = mktime($localtime);
Far from my best work... but here's some functions for working with string or unix time stamp.
/**
* Takes a timestamp like "2016-10-01 17:59:01" and returns "2016-10-01 18:00"
* Note: assumes timestamp is in UTC
*
* #param $timestampString - a valid string which will be converted to unix with time()
* #param int $mins - interval to round to (ex: 15, 30, 60);
* #param string $format - the format to return the timestamp default is Y-m-d H:i
* #return bool|string
*/
function roundTimeString( $timestampString, $mins = 30, $format="Y-m-d H:i") {
return gmdate( $format, roundTimeUnix( time($timestampString), $mins ));
}
/**
* Rounds the time to the nearest minute interval, example: 15 would round times to 0, 15, 30,45
* if $mins = 60, 1:00, 2:00
* #param $unixTimestamp
* #param int $mins
* #return mixed
*/
function roundTimeUnix( $unixTimestamp, $mins = 30 ) {
$roundSecs = $mins*60;
$offset = $unixTimestamp % $roundSecs;
$prev = $unixTimestamp - $offset;
if( $offset > $roundSecs/2 ) {
return $prev + $roundSecs;
}
return $prev;
}
This is a solution using DateTimeInterface and keeping timezone information etc. Will also handle timezones that are not a multiple of 30 minutes offset from GMT (e.g. Asia/Kathmandu).
/**
* Return a DateTimeInterface object that is rounded down to the nearest half hour.
* #param \DateTimeInterface $dateTime
* #return \DateTimeInterface
* #throws \UnexpectedValueException if the $dateTime object is an unknown type
*/
function roundToHalfHour(\DateTimeInterface $dateTime)
{
$hours = (int)$dateTime->format('H');
$minutes = $dateTime->format('i');
# Round down to the last half hour period
$minutes = $minutes >= 30 ? 30 : 0;
if ($dateTime instanceof \DateTimeImmutable) {
return $dateTime->setTime($hours, $minutes);
} elseif ($dateTime instanceof \DateTime) {
// Don't change the object that was passed in, but return a new object
$dateTime = clone $dateTime;
$dateTime->setTime($hours, $minutes);
return $dateTime;
}
throw new UnexpectedValueException('Unexpected DateTimeInterface object');
}
You'll need to have created the DateTime object first though - perhaps with something like $dateTime = new DateTimeImmutable('#' . $timestamp). You can also set the timezone in the constructor.
Math.round(timestamp/1800)*1800
As you probably know, a UNIX timestamp is a number of seconds, so substract/add 1800 (number of seconds in 30 minutes) and you will get the desired result.
Here's a more semantic method for those that have to make a few of these, perhaps at certain times of the day.
$time = strtotime(date('Y-m-d H:00:00'));
You can change that H to any 0-23 number, so you can round to that hour of that day.