PHP convert date interval diff to decimal - php

I'm trying to convert the difference between two dates into a total year count, right now I'm using this:
$datetime1 = new DateTime('2009-10-11');
$datetime2 = new DateTime('2010-10-10');
$interval = $datetime1->diff($datetime2);
return $interval->format('%y');
This returns me an int (Like 0 for < than a year, 2 for two years, etc.)
I need the result to be decimal as following:
0.9 - 9 months
1.2 - 1 year and two months
3.5 - 3 years and five months
and so on..
Thanks!

If you don't care about perfect accuracy:
return $interval->days / 365;
You could also do something like return $interval->y + $interval->m / 12 + $interval->d / 365.
Didn't even notice your weird decimal convention until I saw #2unco's comment. That would look like: return $interval->y . '.' . $interval->m.

Here you can see a function that does exactly that and with many options:
http://php.net/manual/es/function.date-diff.php#98615
<?php
/*
* A mathematical decimal difference between two informed dates
*
* Author: Sergio Abreu
* Website: http://sites.sitesbr.net
*
* Features:
* Automatic conversion on dates informed as string.
* Possibility of absolute values (always +) or relative (-/+)
*/
function s_datediff( $str_interval, $dt_menor, $dt_maior, $relative=false){
if( is_string( $dt_menor)) $dt_menor = date_create( $dt_menor);
if( is_string( $dt_maior)) $dt_maior = date_create( $dt_maior);
$diff = date_diff( $dt_menor, $dt_maior, ! $relative);
switch( $str_interval){
case "y":
$total = $diff->y + $diff->m / 12 + $diff->d / 365.25; break;
case "m":
$total= $diff->y * 12 + $diff->m + $diff->d/30 + $diff->h / 24;
break;
case "d":
$total = $diff->y * 365.25 + $diff->m * 30 + $diff->d + $diff->h/24 + $diff->i / 60;
break;
case "h":
$total = ($diff->y * 365.25 + $diff->m * 30 + $diff->d) * 24 + $diff->h + $diff->i/60;
break;
case "i":
$total = (($diff->y * 365.25 + $diff->m * 30 + $diff->d) * 24 + $diff->h) * 60 + $diff->i + $diff->s/60;
break;
case "s":
$total = ((($diff->y * 365.25 + $diff->m * 30 + $diff->d) * 24 + $diff->h) * 60 + $diff->i)*60 + $diff->s;
break;
}
if( $diff->invert)
return -1 * $total;
else return $total;
}
/* Enjoy and feedback me ;-) */
?>

Simpler and more accurate interval converter to days/hours/minutes/seconds:
function DateDiffInterval($sDate1, $sDate2, $sUnit='H') {
//subtract $sDate2-$sDate1 and return the difference in $sUnit (Days,Hours,Minutes,Seconds)
$nInterval = strtotime($sDate2) - strtotime($sDate1);
if ($sUnit=='D') { // days
$nInterval = $nInterval/60/60/24;
} else if ($sUnit=='H') { // hours
$nInterval = $nInterval/60/60;
} else if ($sUnit=='M') { // minutes
$nInterval = $nInterval/60;
} else if ($sUnit=='S') { // seconds
}
return $nInterval;
} //DateDiffInterval

Related

Calculation of Sunrise and Sunset time in PHP

Note: this is a exercise for my curiosity and there are existing functions / code that solve this problem (see comments too)
An algorithm for calculation of sunrise and sunset times can be found here and implementations at 1 in Tcl and 2 in javascript.
I am trying to convert the algorithm to PHP, but it's slightly over my head and takes too much time. This is my result so far:
<?php
$sunrise = sunriseSunsetTimeTest(9, 4, 2015, 46.929512, 7.565272);
$sunset = sunriseSunsetTimeTest(9, 4, 20, 46.929512, 7.565272, 'sunset');
echo $sunrise . '/' . $sunset;
/* output is: 12.314714533758/12.612340511889 (?) */
function sunriseSunsetTimeTest($day, $month, $year, $latitude, $longitude,
$which='sunrise', $localTimeOffset=1, $zenith=96){
/*
* Output:
* sunrise or sunset time depending on parameter $which
*
* Input:
* (int) day
* (int) month
* (int) year
* (float) latitude_degree
* (float) longitude_degree
* (string) which -> "sunrise" or "sunset (resp. not 'sunrise')"
* (int) localTimeOffset (0 for GMT, 1 for CET, etc.)
* (float) zenith_degree
* offical = 90 degrees 50'
* civil = 96 degrees
* nautical = 102 degrees
* astronomical = 108 degrees
*/
$dayOfYear = dayOfYear($day, $month, $year);
// convert the longitude to hour value and calculate an approximate time
$lngHour = $longitude / 15;
$approximateTime = ($which=='sunrise')
? $dayOfYear + ((6 - $lngHour) / 24)
: $dayOfYear + ((18 - $lngHour) / 24);
// calculate the Sun's mean anomaly
$sunMeanAnomaly = (0.9856 * $approximateTime) - 3.289;
// calculate the Sun's true longitude
$sunTrueLongitude = $sunMeanAnomaly + (1.916 * sin($sunMeanAnomaly)) + (0.020 * sin(2 * $sunMeanAnomaly)) + 282.634;
while ($sunTrueLongitude>360)
$sunTrueLongitude -= 360;
while ($sunTrueLongitude<0)
$sunTrueLongitude += 360;
// calculate the Sun's right ascension
$sunRightAscension = rad2deg(atan(0.91764 * tan(deg2rad($sunTrueLongitude))));
while ($sunRightAscension>360)
$sunRightAscension -= 360;
while ($sunRightAscension<0)
$sunRightAscension += 360;
// right ascension value needs to be in the same quadrant as true longitude
$sunTrueLongitudeQuadrant = (floor($sunTrueLongitude/90)) * 90;
$sunRightAscensionQuadrant = (floor($sunRightAscension/90)) * 90;
$sunRightAscension = $sunRightAscension + ($sunTrueLongitudeQuadrant - $sunRightAscensionQuadrant);
// right ascension value needs to be converted into hours
$sunRightAscension = $sunRightAscension / 15;
// calculate the Sun's declination
$sunSinDec = 0.39782 * sin(deg2rad($sunTrueLongitude));
$sunCosDec = cos(asin($sunSinDec));
// calculate the Sun's local hour angle
$cosH = (cos(deg2rad($zenith)) - ($sunSinDec * sin(deg2rad($latitude)))) / ($sunCosDec * cos(deg2rad($latitude)));
// finish calculating H and convert into hours
if ($which=='sunrise'){
if ($cosH > 1) //sun never rises on this location (on the specified date)
return false;
$H = 360 - acos($cosH);
}
else{
if ($cosH < -1) // sun never sets on this location (on the specified date)
return false;
$H = acos($cosH);
}
$H = $H / 15;
// calculate local mean time of rising/setting
$T = $H + $sunRightAscension - (0.06571 * $approximateTime) - 6.622;
// adjust back to UTC
$UT = $T - $lngHour;
while ($UT>24)
$UT -= 24;
while ($UT<0)
$UT += 24;
// convert UT value to local time zone of latitude/longitude
$localT = $UT + $localTimeOffset;
return $localT;
}
function dayOfYear($day,$month,$year){
$N1 = floor(275 * $month / 9);
$N2 = floor(($month + 9) / 12);
$N3 = (1 + floor(($year - 4 * floor($year / 4) + 2) / 3));
return $N1 - ($N2 * $N3) + $day - 30;
}
...the Input of date 09-04-2015, latitude 46.929512, longitude 7.565272 results in the outputs 12.314714533758 for sunrise and 12.612340511889 for sunset.
I would like to understand what is wrong in the code, maybe somebody can help. Thanks!

Date Difference in days in php

I have a function to calculate the difference between two dates.
function getDateDifference($to, $from, $in) {
$diff = abs($to - $from);
$years = floor($diff / (365 * 60 * 60 * 24));
$months = floor(($diff - $years * 365 * 60 * 60 * 24) / (30 * 60 * 60 * 24));
$days = floor(($diff - $years * 365 * 60 * 60 * 24 - $months * 30 * 60 * 60 * 24) / (60 * 60 * 24));
if ($in == "days") {
return $days;
} else if ($in == "months") {
return $months;
} else if ($in == "years") {
return $years;
}
}
For the parameters i first convert the two dates into seconds like this,
checkin = '2012-07-26';
checkout = '2012-07-27';
check_in_date = strtotime(checkin);
check_out_date = strtotime(checkout);
im getting the correct difference when it comes to difference less than one month. But if the difference is more than one month, im always getting the difference as 1. Can someone tell me wat the problem is.
Currently, a month is always 30 * 60 * 60 * 24 sec, aka 30 days.
Your problem is that we're in July, and there are 31 days, not 30. You must take care of number of days per month.
You can make use of the DateTime class.
http://php.net/manual/en/datetime.diff.php
$checkin = new DateTime("2012-07-23");
$checkout = new DateTime("2012-07-27");
$difference = $checkin->diff($checkout);
echo "differrence = " . $difference->format('%R%a days');

PHP Last log in script [closed]

It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 10 years ago.
I wanted to know a good and efficient way to be able to tell how long ago my users last logged in.
On the users profile I want it for say how long ago their last log in was.
Eg:
User 1
Last login: 2 hours ago
User 2
Last login: 3 minutes ago
User 3
Last login: 2 months ago
I will keep their last login information in a MySQL database but want to know how to do the script.
I just realized that Stackoverflow uses this feature, so that can help you understand what I want.
mysql_query("UPDATE users SET lastactivity = ".time()." WHERE id = ".$userID);
This is how I will update the DB.
Each page request just update their last activity.
<?php
mysql_query("UPDATE users SET lastactivity = ".time()." WHERE id = ".$userID);
to show when they were last online, just select their lastactivity field from database and show it
<?php
$activity = mysql_result(mysql_query("SELECT lastactivity FROM users WHERE id = ".$userID), 0);
echo "Last activity: ".relativeTime($active);
where relativeTime() is function I've been using:
function relativeTime($time, $short = false){
$SECOND = 1;
$MINUTE = 60 * $SECOND;
$HOUR = 60 * $MINUTE;
$DAY = 24 * $HOUR;
$MONTH = 30 * $DAY;
$before = time() - $time;
if ($before < 0)
{
return "not yet";
}
if ($short){
if ($before < 1 * $MINUTE)
{
return ($before <5) ? "just now" : $before . " ago";
}
if ($before < 2 * $MINUTE)
{
return "1m ago";
}
if ($before < 45 * $MINUTE)
{
return floor($before / 60) . "m ago";
}
if ($before < 90 * $MINUTE)
{
return "1h ago";
}
if ($before < 24 * $HOUR)
{
return floor($before / 60 / 60). "h ago";
}
if ($before < 48 * $HOUR)
{
return "1d ago";
}
if ($before < 30 * $DAY)
{
return floor($before / 60 / 60 / 24) . "d ago";
}
if ($before < 12 * $MONTH)
{
$months = floor($before / 60 / 60 / 24 / 30);
return $months <= 1 ? "1mo ago" : $months . "mo ago";
}
else
{
$years = floor ($before / 60 / 60 / 24 / 30 / 12);
return $years <= 1 ? "1y ago" : $years."y ago";
}
}
if ($before < 1 * $MINUTE)
{
return ($before <= 1) ? "just now" : $before . " seconds ago";
}
if ($before < 2 * $MINUTE)
{
return "a minute ago";
}
if ($before < 45 * $MINUTE)
{
return floor($before / 60) . " minutes ago";
}
if ($before < 90 * $MINUTE)
{
return "an hour ago";
}
if ($before < 24 * $HOUR)
{
return (floor($before / 60 / 60) == 1 ? 'about an hour' : floor($before / 60 / 60).' hours'). " ago";
}
if ($before < 48 * $HOUR)
{
return "yesterday";
}
if ($before < 30 * $DAY)
{
return floor($before / 60 / 60 / 24) . " days ago";
}
if ($before < 12 * $MONTH)
{
$months = floor($before / 60 / 60 / 24 / 30);
return $months <= 1 ? "one month ago" : $months . " months ago";
}
else
{
$years = floor ($before / 60 / 60 / 24 / 30 / 12);
return $years <= 1 ? "one year ago" : $years." years ago";
}
return "$time";
}
In addition to what #Martin. said, you can get the current timestamp using time(), and then retrieve the last login timestamp from the database, and subtract it from the current timestamp.
<?php
$date = strtotime("2012-03-08 16:02:35");
$now = time();
$diff = $now - $date;
?>
...then $diff is the time difference in seconds. Then you can calculate whatever you want.

Convert x hours x minutes ago back into unix timestamp

I'm looking for a function to convert dates presented in "X Hours ago" and "X minutes ago" back into a timestamp in php, anyone have a soulution to this?
strtotime already does this:
$timestamp = strtotime("8 hours ago");
See relative time format specifications for more info.
I helped someone on stackoverflow to write a function that does the reverse of this, here is the code, i'm sure if you deconstruct and reverse it, you will have your answer:
<?
$unix_time = 6734;
echo howLongAgo($unix_time);
function howLongAgo($time_difference){
// Swtich logic based on the time difference passed to this function, sets the english string and what number the difference needs to be divided by
switch($time_difference){
case ($time_difference < 60):
$string = " second";
break;
case ($time_difference >= 60 && $time_difference < 3600):
$string = " minute";
$divider = 60;
break;
case ($time_difference >= 3600 && $time_difference < 86400):
$string = " hour";
$divider = 3600;
break;
case ($time_difference >= 86400 && $time_difference < 2629743):
$string = " day";
$divider = 86400;
break;
case ($time_difference >= 2629743 && $time_difference < 31556926):
$string = " month";
$divider = 2629743;
break;
case ($time_difference >= 31556926):
$string = " year";
$divider = 31556926;
break;
}
// If a divider value is set during the switch, use it to get the actual difference
if($divider){$diff = round($time_difference / $divider);}else{$diff = round($time_difference);}
// If the difference does not equal 1, pluralize the final result EG: hours, minutes, seconds
if($diff != 1){$pluralize="s";}
// Concatenate all variables together and return them
$final = $diff . $string . $pluralize . " ago";
return $final;
}
?>
$hourago= "-1 hour";
$minago = "-2 minute";
$timestamp = strtotime($hourago.' '.$minago);
echo $timestamp;
or
$hourago= "-1";
$minago = "-2";
$timestamp = strtotime($hourago.' hour '.$minago.' minute');
echo $timestamp;

Calculate total seconds in PHP DateInterval

What is the best way to calculate the total number of seconds between two dates? So far, I've tried something along the lines of:
$delta = $date->diff(new DateTime('now'));
$seconds = $delta->days * 60 * 60 * 24;
However, the days property of the DateInterval object seems to be broken in the current PHP5.3 build (at least on Windows, it always returns the same 6015 value). I also attempted to do it in a way which would fail to preserve number of days in each month (rounds to 30), leap years, etc:
$seconds = ($delta->s)
+ ($delta->i * 60)
+ ($delta->h * 60 * 60)
+ ($delta->d * 60 * 60 * 24)
+ ($delta->m * 60 * 60 * 24 * 30)
+ ($delta->y * 60 * 60 * 24 * 365);
But I'm really not happy with using this half-assed solution.
Could you not compare the time stamps instead?
$now = new DateTime('now');
$diff = $date->getTimestamp() - $now->getTimestamp()
This function allows you to get the total duration in seconds from a DateInterval object
/**
* #param DateInterval $dateInterval
* #return int seconds
*/
function dateIntervalToSeconds($dateInterval)
{
$reference = new DateTimeImmutable;
$endTime = $reference->add($dateInterval);
return $endTime->getTimestamp() - $reference->getTimestamp();
}
DateTime::diff returns a DateInterval object between 2 dates.
The DateInterval object gives all the informations (the number of days, hours, minutes, seconds).
Here's a sample code:
/**
* intervalToSeconds
*
* #param DateInterval $interval
* #return int
*/
function intervalToSeconds(\DateInterval $interval) {
return $interval->days * 86400 + $interval->h * 3600 + $interval->i * 60 + $interval->s;
}
$date_1 = new \DateTime('2021-03-03 05:59:19');
$date_2 = new \DateTime('now');
$interval = $date_1->diff($date_2);
echo intervalToSeconds($interval);
You could do it like this:
$currentTime = time();
$timeInPast = strtotime("2009-01-01 00:00:00");
$differenceInSeconds = $currentTime - $timeInPast;
time() returns the current time in seconds since the epoch time (1970-01-01T00:00:00), and strtotime does the same, but based on a specific date/time you give.
static function getIntervalUnits($interval, $unit)
{
// Day
$total = $interval->format('%a');
if ($unit == TimeZoneCalc::Days)
return $total;
//hour
$total = ($total * 24) + ($interval->h );
if ($unit == TimeZoneCalc::Hours)
return $total;
//min
$total = ($total * 60) + ($interval->i );
if ($unit == TimeZoneCalc::Minutes)
return $total;
//sec
$total = ($total * 60) + ($interval->s );
if ($unit == TimeZoneCalc::Seconds)
return $total;
return false;
}

Categories