PHP: producing relative date/time from timestamps
This function gives you "1 hour ago" or "Tomorrow" like results between 'now' and 'specific timestamp'.
function time2str($ts)
{
if(!ctype_digit($ts))
$ts = strtotime($ts);
$diff = time() - $ts;
if($diff == 0)
return 'now';
elseif($diff > 0)
{
$day_diff = floor($diff / 86400);
if($day_diff == 0)
{
if($diff < 60) return 'just now';
if($diff < 120) return '1 minute ago';
if($diff < 3600) return floor($diff / 60) . ' minutes ago';
if($diff < 7200) return '1 hour ago';
if($diff < 86400) return floor($diff / 3600) . ' hours ago';
}
if($day_diff == 1) return 'Yesterday';
if($day_diff < 7) return $day_diff . ' days ago';
if($day_diff < 31) return ceil($day_diff / 7) . ' weeks ago';
if($day_diff < 60) return 'last month';
return date('F Y', $ts);
}
else
{
$diff = abs($diff);
$day_diff = floor($diff / 86400);
if($day_diff == 0)
{
if($diff < 120) return 'in a minute';
if($diff < 3600) return 'in ' . floor($diff / 60) . ' minutes';
if($diff < 7200) return 'in an hour';
if($diff < 86400) return 'in ' . floor($diff / 3600) . ' hours';
}
if($day_diff == 1) return 'Tomorrow';
if($day_diff < 4) return date('l', $ts);
if($day_diff < 7 + (7 - date('w'))) return 'next week';
if(ceil($day_diff / 7) < 4) return 'in ' . ceil($day_diff / 7) . ' weeks';
if(date('n', $ts) == date('n') + 1) return 'next month';
return date('F Y', $ts);
}
}
Get relative date from the NOW() function
Use TIMESTAMPDIFF()
function. See example:
SELECT
TIMESTAMPDIFF(SECOND, `stamp_column`, NOW()) as `seconds`
FROM
`YourTable`
Or use this stored function:
CREATE FUNCTION `PassedSince`(`stamp` TIMESTAMP)
RETURNS VARCHAR(100)
DETERMINISTIC
BEGIN
DECLARE `result` VARCHAR(100) DEFAULT '';
DECLARE `seconds`, `minutes`, `hours`, `days` INT;
SET `seconds` = TIMESTAMPDIFF(SECOND, `stamp`, NOW());
SET `days` = `seconds` DIV (24 * 60 * 60);
SET `seconds` = `seconds` MOD (24 * 60 * 60);
IF `days` > 0
THEN SET `result` = CONCAT(`result`, `days`, ' Days ');
END IF;
SET `hours` = `seconds` DIV (60 * 60);
SET `seconds` = `seconds` MOD (60 * 60);
IF `hours` > 0
THEN SET `result` = CONCAT(`result`, `hours`, ' Hours ');
END IF;
SET `minutes` = `seconds` DIV 60;
SET `seconds` = `seconds` MOD 60;
IF `minutes` > 0
THEN SET `result` = CONCAT(`result`, `minutes`, ' Minutes ');
END IF;
IF `seconds` > 0
THEN SET `result` = CONCAT(`result`, `seconds`, ' Seconds ');
END IF;
RETURN TRIM(`result`);
END
For query:
SELECT
`PassedSince`('2013-06-19 08:00') as `result`
UNION ALL
SELECT
`PassedSince`('2013-01-01 00:00')
Shows:
result
--------------------------------------
1 Hours 20 Minutes 55 Seconds
169 Days 9 Hours 20 Minutes 55 Seconds
Print out Relative Date / Time from SQL / PHP Datestamp
Found this after two seconds of Google http://www.mdj.us/web-development/php-programming/another-variation-on-the-time-ago-php-function-use-mysqls-datetime-field-type
In general you chose a unit of time like seconds, test if the time-difference is smaller then the max-value for this unit (60s) and if so, print out "$timeDifference $unit". If not you divide the difference by the units max-value and start over with the next higher unit (minutes).
Example:
$timeDif = 60*60*5 + 45; // == 5 hours 45 seconds
// 60 seconds in a minute
if ($timeDif < 60) // false
return "$timeDif second(s) ago";
// convert seconds to minutes
$timeDif = floor($timeDif / 60); // == 300 = 5 * 60
// 60 minutes in an hour
if ($timeDif < 60) // false
return "$timeDif minute(s) ago";
// convert minutes to hours
$timeDif = floor($timeDif / 60); // == 5
// 24 hours in a day
if ($timeDif < 24)
return "$timeDif hour(s) ago";
// ...
Event Relative Time
First of all, let's summarise the expected local values for 1477762205
Unix timestamp:
- UTC: 17:30:05 (UTC, +0000)
- London: 18:30:05 (BST, +0100 aka 3600, DST=1)
- Madrid: 19:30:05 (CEST, +0200 aka 7200, DST=1)
Stuff seems to work as expected as long as you use city-based time zone identifiers:
foreach (['UTC', 'Europe/London', 'Europe/Madrid'] as $time_zone_id) {
$dt = new DateTime('@1477762205');
$tz = new DateTimeZone($time_zone_id);
$dt->setTimezone($tz);
echo $time_zone_id . ': ' . $dt->format('H:i:s [e=T, O]') . PHP_EOL;
}
UTC: 17:30:05 [UTC=UTC, +0000]
Europe/London: 18:30:05 [Europe/London=BST, +0100]
Europe/Madrid: 19:30:05 [Europe/Madrid=CEST, +0200]
As soon as we use named zones acronyms, strange things happen:
foreach (['UTC', 'BST', 'GMT', 'CEST', 'CET'] as $time_zone_id) {
$dt = new DateTime('@1477762205');
$tz = new DateTimeZone($time_zone_id);
$dt->setTimezone($tz);
echo $time_zone_id . ': ' . $dt->format('H:i:s [e=T, O]') . PHP_EOL;
}
UTC: 17:30:05 [UTC=UTC, +0000]
BST: 17:30:05 [BST=BST, +0000]
GMT: 17:30:05 [GMT=GMT, +0000]
CEST: 18:30:05 [CEST=CEST, +0100]
CET: 18:30:05 [CET=CET, +0100]
There's probably some relation with the information (or lack of it) about time zone transitions available in the underlying database:
$dt = new DateTime('@1477762205');
foreach (['UTC', 'BST', 'Europe/London', 'CEST', 'Europe/Madrid'] as $time_zone_id) {
$tz = new DateTimeZone($time_zone_id);
$dt->setTimezone($tz);
echo $time_zone_id . PHP_EOL;
echo '- Time zone offset: ' . $tz->getOffset($dt) . ' seconds' . PHP_EOL;
$transitions = $tz->getTransitions(mktime(0, 0, 0, 1, 1, 2016), mktime(0, 0, 0, 12, 31, 2016));
if ($transitions===false) {
echo '- Error fetching transitions' . PHP_EOL;
} else {
echo '- ' . count($transitions) . ' transitions found' . PHP_EOL;
}
}
UTC
- Time zone offset: 0 seconds
- 1 transitions found
BST
- Time zone offset: 0 seconds
- Error fetching transitions
Europe/London
- Time zone offset: 3600 seconds
- 3 transitions found
CEST
- Time zone offset: 3600 seconds
- Error fetching transitions
Europe/Madrid
- Time zone offset: 7200 seconds
- 3 transitions found
It's really hard to say how much of this is a plain bug and how much is counter-intuitive but documented; the PHP bug database is crowded with not a bug entries which are indeed a misunderstanding but I've personally found weird but actual bugs in date calculations involving DST boundaries.
Relative Date from Unix Timestamp with PHP
There's probably a better way to do it, but here's a rough function I wrote ages ago for this:
function time_ago($datetime)
{
if (is_numeric($datetime)) {
$timestamp = $datetime;
} else {
$timestamp = strtotime($datetime);
}
$diff=time()-$timestamp;
$min=60;
$hour=60*60;
$day=60*60*24;
$month=$day*30;
if($diff<60) //Under a min
{
$timeago = $diff . " seconds";
}elseif ($diff<$hour) //Under an hour
{
$timeago = round($diff/$min) . " mins";
}elseif ($diff<$day) //Under a day
{
$timeago = round($diff/$hour) . " hours";
}elseif ($diff<$month) //Under a day
{
$timeago = round($diff/$day) . " days";
}else
{
$timeago = round($diff/$month) ." months";
}
return $timeago;
}
PHP Function to Calculate Relative Time (Human Readable / Facebook Style)
The problem is that the second array $lengths
contains 7 elements so when executing the last iteration of the loop (after deviding by 10 - for the decades) $j = 7
, $lengths[7]
is undefined, so converted to 0 and therefore the test $difference >= $lengths[$j]
returns true
. Then the code enters an infinite loop. To overcome this problem, just add one more element to the $lengths
array, say "100", so the for loop to terminate after processing the decades. Note that dates can be represented in UNIX timestamp if they are before January 19, 2038. Therefore you cannot calculate dates in more than 4 decates so 100 is sufficiant to break from the loop.
PHP library to generate user friendly relative timestamps
Since there didn't seem to be any library, I've made one myself and got it included in PEAR:
Date_HumanDiff, http://pear.php.net/package/Date_HumanDiff
Code is at http://github.com/pear/Date_HumanDiff
Relative date formatting always outputs 3 hours ago
result of date() depends on your timezone. You can change this behavior by setting timezone manually by date_default_timezone_set()
Microtime to Relative Date Conversion
You may do the following:
$input = 1369057622.4679;
$diff = floor(($input-time())/86400); // calculating the difference
$result = abs($diff) . (abs($diff)==1 ? ' day ':' days ') . ($diff<=0 ? 'ago':'ahead'); // making the result.
echo $result; // output: 1 day ago
Related Topics
Declaration of Methods Should Be Compatible With Parent Methods in PHP
Remove Excess Whitespace from Within a String
How to Increase Maximum Execution Time in PHP
PHP Simplexml How to Save the File in a Formatted Way
PHP.Ini & Smtp= - How to Pass Username & Password
How to Properly Url Encode a String in PHP
How to Run a .Bat File from PHP
Fatal Error: Call to Undefined Function MySQL_Connect()
Preserving Session Variables Across Different Domains
Strict Standards: MySQLi_Next_Result() Error With MySQLi_Multi_Query
Print Numeric Values to Two Decimal Places
PHPdoc Type Hinting For Array of Objects
How to Post Pictures to Instagram Using API
How Do PHP Sessions Work? (Not "How Are They Used")