PHP How do I calculate relative time? [duplicate] - php

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
PHP: producing relative date/time from timestamps
Given a specific DateTime value, how do I display relative time, like
35 minutes ago
2 hours ago
3 days ago
1 month ago
etc, etc...?
mysql_query("UPDATE users SET lastlogin = ".time()." WHERE id = ".$userID);

this may help you
function time_ago_en($time)
{
if(!is_numeric($time))
$time = strtotime($time);
$periods = array("second", "minute", "hour", "day", "week", "month", "year", "age");
$lengths = array("60","60","24","7","4.35","12","100");
$now = time();
$difference = $now - $time;
if ($difference <= 10 && $difference >= 0)
return $tense = 'just now';
elseif($difference > 0)
$tense = 'ago';
elseif($difference < 0)
$tense = 'later';
for($j = 0; $difference >= $lengths[$j] && $j < count($lengths)-1; $j++) {
$difference /= $lengths[$j];
}
$difference = round($difference);
$period = $periods[$j] . ($difference >1 ? 's' :'');
return "{$difference} {$period} {$tense} ";
}
Usage:
<?php
echo time_ago_en(time() - 300); // 5 minutes ago
?>

strtotime is a nice function
let me be more specific
strtotime(-5 days);
or
strtotime(-1 month);
There is an optional 2nd argument which is another time stamp of the time you want to start at, giving your relative time. Why the downvote?

<?php
function relativeTime($time = false, $limit = 86400, $format = 'g:i A M jS') {
if (empty($time) || (!is_string($time) && !is_numeric($time))) $time = time();
elseif (is_string($time)) $time = strtotime($time);
$now = time();
$relative = '';
if ($time === $now) $relative = 'now';
elseif ($time > $now) $relative = 'in the future';
else {
$diff = $now - $time;
if ($diff >= $limit) $relative = date($format, $time);
elseif ($diff < 60) {
$relative = 'less than one minute ago';
} elseif (($minutes = ceil($diff/60)) < 60) {
$relative = $minutes.' minute'.(((int)$minutes === 1) ? '' : 's').' ago';
} else {
$hours = ceil($diff/3600);
$relative = 'about '.$hours.' hour'.(((int)$hours === 1) ? '' : 's').' ago';
}
}
return $relative;
}
?>
Source

Related

logic behind displaying time values with seconds and minutes range

i want to know the logic used behind displaying the time stamp like x minutes ago or x hours ago and after few hours showing the exact time like posted at 7:57 pm like they do it in mail sites, and also twitter etc.
how do i know when to show the seconds/minutes/hours range and when to show the actual time in am/pm format? please suggest the business logic used to achieve this.
From the php manual:
<?php
function nicetime($date)
{
if(empty($date)) {
return "No date provided";
}
$periods = array("second", "minute", "hour", "day", "week", "month", "year", "decade");
$lengths = array("60","60","24","7","4.35","12","10");
$now = time();
$unix_date = strtotime($date);
// check validity of date
if(empty($unix_date)) {
return "Bad date";
}
// is it future date or past date
if($now > $unix_date) {
$difference = $now - $unix_date;
$tense = "ago";
} else {
$difference = $unix_date - $now;
$tense = "from now";
}
for($j = 0; $difference >= $lengths[$j] && $j < count($lengths)-1; $j++) {
$difference /= $lengths[$j];
}
$difference = round($difference);
if($difference != 1) {
$periods[$j].= "s";
}
return "$difference $periods[$j] {$tense}";
}
$date = "2009-03-04 17:45";
$result = nicetime($date); // 2 days ago
?>
http://www.php.net/manual/de/function.time.php#89415
Print the timestamp in the regular way using PHP and use the timeago plugin for jQuery to do the fancy stuff.
You can use something like this
$time = $now - $time;
if ($time < 60) {
$name = "second";
}
elseif ($time < 3600)
{
$time /= 60;
$name = "minute";
}
elseif ($time < 86400)
{
$time /= 3600; //86400;
$name = "hour";
}
elseif ($time < 604800)
{
$time /= 86400; //604800;
$name = "day";
}
elseif ($time < 31536000)
{
$time /= 604800; //31536000;
$name = "week";
}
else
{
$time /= 31536000;
$name = "year";
}

Getting exact time difference from MYSQL datetime field

I want to do what StackOverflow is doing which is saying exactly how long it's been since the last post. There is a catch though, SO displays certain information based on how long the ago the last post was - for example, if the post was less than a day ago, they post how many hours ago the last post was; if the post was less than an hour ago they post how many minutes ago it was, etc.
I'm working with a MYSQL DateTime field in the following format:
2012-09-19 13:28:45
I want to compare the above to the time NOW and so I converted that time using PHP's strtotime function and tried comparing the two dates through a function I put together (below). Granted, this is probably the WORST possible way of doing this but after reading about PHP's Date and DateTime functions I'm starting to become very, very confused.
function get_date_format($strToTimeString){
$minute = 60;
$hour = $minutes * 60;
$day = $hour * 24;
$week = $day * 7;
$month = $week * 4;
$year = $month * 12;
$timeNow = strtotime("now");
$timeDiff = $timeNow - $strToTimeString;
if($timeDiff > $minute){
if($timeDiff > $hour){
if($timeDiff > $day){
if($timeDiff > $week){
if($timeDiff > $month){
if($timeDiff > $year){
// Years ago
}
else{
// Months ago
}
}
else{
// Weeks ago
}
}
else{
// Days ago
}
}
else
{
// Hours ago
}
}
else{
// Minutes ago
}
}
else{
// Seconds ago
}
}
Is there a better way to do this? As I mentioned above, I had no luck when trying to use DateTime->diff
I really appreciate any help.
Use DateTime. Here's sample:
$now = new DateTime('now');
$posted = new DateTime($postDateFromDBHere);
$interval = $posted->diff($now);
var_dump($interval);
echo $interval->format('%y-%m-%d %h:%m:%s'); //You can do similar to format your output as you wish.
Use DateTime and DateTime:diff then check each value:
function returnInterval($date){
$datetime1 = new DateTime($date);
$datetime2 = new DateTime();
$diff = $datetime1->diff($datetime2);
$string = '';
$pass = '';
if($diff->y){
$string .= ($diff->y == 1) ? $diff->y." year" : $diff->y." years";
$pass = ', ';
}
if($diff->m){
$string .= $pass;
$string .= ($diff->m == 1) ? $diff->m." month" : $diff->m." months";
$pass = ', ';
}
if($diff->d){
$string .= $pass;
$string .= ($diff->d == 1) ? $diff->d." day" : $diff->d." days";
$pass = ', ';
}
if($diff->h){
$string .= $pass;
$string .= ($diff->h == 1) ? $diff->h." hour" : $diff->h." hours";
$pass = ', ';
}
if($diff->i){
$string .= $pass;
$string .= ($diff->i == 1) ? $diff->i." minute" : $diff->i." minutes";
$pass = ', ';
}
if($diff->s){
$string .= $pass;
$string .= ($diff->s == 1) ? $diff->s." second" : $diff->s." seconds";
}
$pos = strrpos($string, ',');
$string = substr_replace($string, ' and ', $pos, 2);
return $string;
}
echo returnInterval('2012-09-19 13:28:45');
// 8 days, 13 hours, 47 minutes and 44 seconds
After long searching, I got something close to what rottentomatoes used on their forum:
function realTimeSince($time){
define(MINUTE, 60);
define(HOUR, 60*60);
define(DAY, 60*60*24);
define(MONTH, 60*60*24*30);
$delta = strtotime(gmdate("Y-m-d H:i:s", time())) - strtotime($time);
if ($delta < 1 * MINUTE) {
return $delta == 1 ? "one second ago" : $delta . " seconds ago";
}
if ($delta < 2 * MINUTE) {
return "a minute ago";
}
if ($delta < 45 * MINUTE) {
return floor($delta / MINUTE) . " minutes ago";
}
if ($delta < 90 * MINUTE) {
return "an hour ago";
}
if ($delta < 24 * HOUR) {
return floor($delta / HOUR) . " hours ago";
}
if ($delta < 48 * HOUR) {
return "yesterday";
}
if ($delta < 30 * DAY) {
return floor($delta / DAY) . " days ago";
}
if ($delta < 12 * MONTH) {
$months = floor($delta / DAY / 30);
return $months <= 1 ? "one month ago" : $months . " months ago";
} else {
$years = floor($delta / DAY / 365);
return $years <= 1 ? "one year ago" : $years . " years ago";
}
}
so you can use it like this:
realTimeSince('2012-11-12 00:09:54'); //which can be got from a MySQL TIMESTAMP field
modified a little based on http://www.ferdychristant.com/blog//archive/DOMM-7QEFK4
Try the following function
function time_ago($date)
{
//echo "ss";
if (empty($date)) {
return "No date provided";
}
$periods = array("sec", "min", "hr", "day", "week", "month", "year", "decade");
$lengths = array("60","60","24","7","4.35","12","10");
$now = time();
$unix_date = strtotime($date);
// check validity of date
if (empty($unix_date)) {
return "Bad date";
}
// is it future date or past date
if ($now >= $unix_date) {
$difference= $now - $unix_date;
$tense = "ago";
} else {
$difference = $unix_date - $now;
$tense = "from now";
}
for ($j = 0; $difference >= $lengths[$j] && $j < count($lengths)-1; $j++) {
$difference /= $lengths[$j];
}
$difference = round($difference);
if ($difference != 1 && $j != 0) {
$periods[$j].= "s";
}
if($difference!=0)
return "$difference $periods[$j] {$tense}";
else
return "a few seconds ago";
}
or
function time_elapsed_since ($postedDateTime){
$time = time() - $postedDateTime; // to get the time since that moment
$tokens = array (
31536000 => 'year',
2592000 => 'month',
604800 => 'week',
86400 => 'day',
3600 => 'hour',
60 => 'minute',
1 => 'second'
);
foreach ($tokens as $unit => $text) {
if ($time < $unit) continue;
$numberOfUnits = floor($time / $unit);
return $numberOfUnits.' '.$text.(($numberOfUnits>1)?'s':'');
}
}
time_elapsed_since($postedDateTime).' ago';

Show x time ago if time is less than 24 hour ago

I use Codeigniter and it has the timespan() function that returns the time as 1 Year, 10 Months, 2 Weeks, 5 Days, 10 Hours, 16 Minutes.
What I'd like to do is only show the time formatted in x hours ago if the time is within the last 24 hours, otherwise just show a normal datetime.
I feel like there's got to be a function already made to do this but I haven't had any luck finding it.
This is the timespan function included with Codeigniter, how can I alter it?
/**
* Timespan
*
* Returns a span of seconds in this format:
* 10 days 14 hours 36 minutes 47 seconds
*
* #access public
* #param integer a number of seconds
* #param integer Unix timestamp
* #return integer
*/
if ( ! function_exists('timespan'))
{
function timespan($seconds = 1, $time = '')
{
$CI =& get_instance();
$CI->lang->load('date');
if ( ! is_numeric($seconds))
{
$seconds = 1;
}
if ( ! is_numeric($time))
{
$time = time();
}
if ($time <= $seconds)
{
$seconds = 1;
}
else
{
$seconds = $time - $seconds;
}
$str = '';
$years = floor($seconds / 31536000);
if ($years > 0)
{
$str .= $years.' '.$CI->lang->line((($years > 1) ? 'date_years' : 'date_year')).', ';
}
$seconds -= $years * 31536000;
$months = floor($seconds / 2628000);
if ($years > 0 OR $months > 0)
{
if ($months > 0)
{
$str .= $months.' '.$CI->lang->line((($months > 1) ? 'date_months' : 'date_month')).', ';
}
$seconds -= $months * 2628000;
}
$weeks = floor($seconds / 604800);
if ($years > 0 OR $months > 0 OR $weeks > 0)
{
if ($weeks > 0)
{
$str .= $weeks.' '.$CI->lang->line((($weeks > 1) ? 'date_weeks' : 'date_week')).', ';
}
$seconds -= $weeks * 604800;
}
$days = floor($seconds / 86400);
if ($months > 0 OR $weeks > 0 OR $days > 0)
{
if ($days > 0)
{
$str .= $days.' '.$CI->lang->line((($days > 1) ? 'date_days' : 'date_day')).', ';
}
$seconds -= $days * 86400;
}
$hours = floor($seconds / 3600);
if ($days > 0 OR $hours > 0)
{
if ($hours > 0)
{
$str .= $hours.' '.$CI->lang->line((($hours > 1) ? 'date_hours' : 'date_hour')).', ';
}
$seconds -= $hours * 3600;
}
$minutes = floor($seconds / 60);
if ($days > 0 OR $hours > 0 OR $minutes > 0)
{
if ($minutes > 0)
{
$str .= $minutes.' '.$CI->lang->line((($minutes > 1) ? 'date_minutes' : 'date_minute')).', ';
}
$seconds -= $minutes * 60;
}
if ($str == '')
{
$str .= $seconds.' '.$CI->lang->line((($seconds > 1) ? 'date_seconds' : 'date_second')).', ';
}
return substr(trim($str), 0, -1);
}
}
This function will accept a string, a numeric (unix) timestamp, or a DateTime object. It also accepts jQuery.now(). Time may be in the future or past.
function time_ago($time=false, $just_now=false) {
if ($time instanceOf DateTime)
$time = $time->getTimestamp();
elseif (is_numeric($time))
$time = date('m/d/y h:i A', $time);
if (strtotime($time) === false)
$time = date('m/d/y h:i A', time());
$interval = date_create($time)->diff(date_create('now'));
$adjective = strtotime($time) > time() ? 'from now' : 'ago';
return (
$interval->days > 0 ?
$time : (
$interval->h < 1 && $interval->i < 1 && $just_now ?
'just now' :
(
$interval->h > 1 ?
$interval->h.' hour'.(
$interval->h > 1 ?
's' :
''
).' ago' :
$interval->i.' minutes'.' '.$adjective
)
)
);
}
echo time_ago('8/22/2012 5:00 PM'); // 3 hours ago
echo time_ago('8/21/2012 5:00 PM'); // 8/21/2012 5:00 PM
echo time_ago(time()); // 0 hours ago
echo time_ago(time(), true); // just now
echo time_ago(strtotime('5 days ago')); // 08/17/12 08:18 PM
echo time_ago(strtotime('5 hours ago')); // 5 hours ago
echo time_ago(strtotime('5 minutes ago')); // 5 minutes ago
echo time_ago(strtotime('+5 minutes')); // 5 minutes from now
echo time_ago('jQuery.now()', true); // just now
echo time_ago('sweet explosions, bro!', true); // just now
Documentation
date - http://php.net/manual/en/function.date.php
DateTime object - http://www.php.net/manual/en/book.datetime.php
DateInterval object - http://www.php.net/manual/en/class.dateinterval.php
is_numeric - http://php.net/manual/en/function.is-numeric.php
if( time() - $yourTime <= 86400 ) { // 86400 seconds in a day
echo timespan($yourTime);
} else {
echo date('m/d/Y \a\t H:i:s', $yourTime);
}
Don't rely on a framework, especially a bad one, for everything!
Fiddle with $format to suit your needs. Will accept almost anything as input.
<?php
/**
* RelativeTime - pretty printed
* #author Dejan Marjanovic
*/
class Site5_RelativeTime
{
private $interval = '';
public function __construct()
{
call_user_func_array(array($this, 'calculate'), func_get_args());
}
public function calculate($start, $end = NULL)
{
if ( empty($start))
return false;
if (empty($end))
$end = time();
if ( ! is_numeric($start))
$start = strtotime($start);
if ( ! is_numeric($end))
$end = strtotime($end);
if($start > $end)
$future = TRUE;
$start = '#' . $start;
$end = '#' . $end;
if ( ! ($start instanceof DateTime))
$start = new DateTime($start);
if ($end === null)
$end = new DateTime();
if ( ! ($end instanceof DateTime))
$end = new DateTime($end);
$interval = $end->diff($start);
$get_plural = function($int, $str)
{
return $int > 1? $str.'s': $str;
};
$format = array();
if ($interval->y !== 0)
$format[] = "%y " . $get_plural($interval->y, "year");
if ($interval->m !== 0)
$format[] = "%m " . $get_plural($interval->m, "month");
if ($interval->d !== 0)
$format[] = "%d " . $get_plural($interval->d, "day");
if ($interval->h !== 0)
$format[] = "%h " . $get_plural($interval->h, "hour");
if ($interval->i !== 0)
$format[] = "%i " . $get_plural($interval->i, "minute");
if ($interval->s !== 0)
{
if ( ! count($format))
{
$this->interval = "less than a minute";
return;
}
else
{
$format[] = "%s " . $get_plural($interval->s, "second");
}
}
if (count($format) > 1)
{
$format = array_shift($format) . " and " . array_shift($format);
}
else
{
$format = array_pop($format);
}
$tense = ($future === TRUE)? 'from now': 'ago';
$this->interval = $interval->format($format) . ' ' . $tense;
}
public function __toString()
{
return $this->interval;
}
}

Calculating the number of Saturdays and Sundays

How can I calculate the number of Saturdays and Sundays between two dates in php?
Is there any inbuilt function for that purpose?
There is a related question here already, Calculate business days
You can use this to subtract from 7 to get the weekend days, or similar.
I don't think there is a built in for that, but this should do the job :
$startTime = START_TIMESTAMP;
$endTime = END_TIMESTAMP;
$time = $startTime;
$count = 0;
while(date('w', $time) != 0) { // 0 (for Sunday) through 6 (for Saturday)
$time += 86400;
}
while($time < $endTime) {
$count++;
$time += 7 * 86400;
}
Let us all KISS (Keep It Simple Stupid). Why make it so complicated?
function countWeekendDays($start, $end)
{
// $start in timestamp
// $end in timestamp
$iter = 24*60*60; // whole day in seconds
$count = 0; // keep a count of Sats & Suns
for($i = $start; $i <= $end; $i=$i+$iter)
{
if(Date('D',$i) == 'Sat' || Date('D',$i) == 'Sun')
{
$count++;
}
}
return $count;
}
You can calculate it mathematically like this - Based on Roland's Answer
private function getNumberOfWeekendDays(\DateTimeInterface $startDate, \DateTimeInterface $endDate): int
{
$startNumber = (int) $startDate->format('N');
$endNumber = (int) $endDate->format('N');
$daysBetweenStartAndEnd = $endDate->diff($startDate)->d;
$weekendDays = (int) (2 * ($daysBetweenStartAndEnd + $startNumber) / 7);
$weekendDays = $weekendDays - ($startNumber == 7 ? 1 : 0) - ($endNumber == 7 ? 1 : 0);
return $weekendDays;
}
<?php
date_default_timezone_set("Europe/Lisbon");
$d1 = new DateTime("2009-06-01"); /* inclusive */
$d2 = new DateTime("2009-07-01"); /* exclusive */
$interval = $d2->diff($d1);
$number_of_days = $interval->format("%d");
$number_of_weekends = $number_of_days / 7;
$remainder = $number_of_days % 7;
if ($remainder >=2 && $d1->format("D") == "Sat")
$number_of_weekends++;
elseif ($d1->format("w") + $remainder >= 8)
$number_of_weekends++;
I may have missed by one in the last condition, be sure to check it with different starting dates. (Feel free to edit this answer if you spot an error).
there's definitely no built in function for that but you can use strtotime to loop days
$start = strtotime('2010-01-01');
$end = strtotime('2010-01-09');
function numWeekdays( $start_ts, $end_ts, $day, $include_start_end = false ) {
$day = strtolower( $day );
$current_ts = $start_ts;
// loop next $day until timestamp past $end_ts
while( $current_ts < $end_ts ) {
if( ( $current_ts = strtotime( 'next '.$day, $current_ts ) ) < $end_ts) {
$days++;
}
}
// include start/end days
if ( $include_start_end ) {
if ( strtolower( date( 'l', $start_ts ) ) == $day ) {
$days++;
}
if ( strtolower( date( 'l', $end_ts ) ) == $day ) {
$days++;
}
}
return (int)$days;
}
echo numWeekDays( $start, $end, 'saturday', false );
I searched for awhile for a simple solution that worked and decided to write my own and came up with this
$start = date('Y-m-d');
$end = date('Y-m-d', strtotime($start.' +1 year'));
$current = $start;
$count = 0;
while($current != $end){
if(date('l', strtotime($current)) == 'Saturday'){
$count++;
}
$current = date('Y-m-d', strtotime($current.' +1 day'));
};
echo $count;

Add working hours to timestamp

I need to add working hours to a timestamp. Working hours are from 8am to 6pm. Lets say we have 2pm and I have to add 6 hours. Result should be 10am... any guesses?
Thanks.
Try this bad boy.
You can specify whether to include weekends as working days, etc. Doesn't take into account holidays.
<?php
function addWorkingHours($timestamp, $hoursToAdd, $skipWeekends = false)
{
// Set constants
$dayStart = 8;
$dayEnd = 16;
// For every hour to add
for($i = 0; $i < $hoursToAdd; $i++)
{
// Add the hour
$timestamp += 3600;
// If the time is between 1800 and 0800
if ((date('G', $timestamp) >= $dayEnd && date('i', $timestamp) >= 0 && date('s', $timestamp) > 0) || (date('G', $timestamp) < $dayStart))
{
// If on an evening
if (date('G', $timestamp) >= $dayEnd)
{
// Skip to following morning at 08XX
$timestamp += 3600 * ((24 - date('G', $timestamp)) + $dayStart);
}
// If on a morning
else
{
// Skip forward to 08XX
$timestamp += 3600 * ($dayStart - date('G', $timestamp));
}
}
// If the time is on a weekend
if ($skipWeekends && (date('N', $timestamp) == 6 || date('N', $timestamp) == 7))
{
// Skip to Monday
$timestamp += 3600 * (24 * (8 - date('N', $timestamp)));
}
}
// Return
return $timestamp;
}
// Usage
$timestamp = time();
$timestamp = addWorkingHours($timestamp, 6);
A more compact version:
function addWhours($timestamp, $hours, $skipwe=false, $startDay='8', $endDay='18')
{
$notWorkingInterval = 3600 * (24 - ($endDay - $startDay));
$timestamp += 3600*$hours;
$our = date('H', $timestamp);
while ($our < $startDay && $our >= $endDay) {
$timestamp += $notWorkingInterval;
$our = date('H', $timestamp);
}
$day = date('N', $timestamp);
if ($skipwe && $day >5) {
$timestamp += (8-$day)*3600*24;
}
return $timestamp;
}
If it is a real timestamp, you just need to add the seconds equivelent to 6 hours.
$timestamp += 3600 * 6;
If not we need to know the real format of your "timestamp".

Categories