I have a function to get the Time-ago from a Timestamp, I grabbed it somewhere from the internet and developed and optimized it. It's fully functioning. The problem here is that it ONLY gets time-ago (from a past Timestamp), it didn't process future Timestamps (It returns 0 seconds ago).
Is anybody able to help me add this functionality to the function?
<?php
function time_ago( $ts, $format ) {
// $format = 'l, F d, Y H:i';
$granularity = 1;
$dif = time() - $ts;
if ( $dif < 0 )
return '0 Seconds ago';
elseif ( $dif < 604800 ) { // 604800 7 days / 864000 10 days
$periods = array(
'Week' => 604800,
'Day' => 86400,
'Hour' => 3600,
'Minute' => 60,
'Second' => 1
);
$output = '';
foreach ( $periods as $key => $value ) {
if ( $dif >= $value ) {
$time = round( $dif / $value );
$dif %= $value;
$output .= ( $output ? ' ' : '' ) . $time . ' ';
$output .= ( ( $time > 1 ) ? $key . 's' : $key );
$granularity --;
}
if ( $granularity == 0 )
break;
} // foreach( $periods as $key => $value )
return ($output ? $output : '0 seconds') . ' ago';
} else
return date( $format, $ts );
}
?>
I've edited your function. Now it displays a time in the future as In 10 Hours.
Code:
function time_ago( $ts, $format ) {
// $format = 'l, F d, Y H:i';
$granularity = 1;
$dif = time() - $ts;
$future = $dif < 0 ? true : false;
$dif = abs($dif);
if ( $dif < 604800 ) { // 604800 7 days / 864000 10 days
$periods = array(
'Week' => 604800,
'Day' => 86400,
'Hour' => 3600,
'Minute' => 60,
'Second' => 1
);
$output = '';
foreach ( $periods as $key => $value ) {
if ( $dif >= $value ) {
$time = round( $dif / $value );
$dif %= $value;
$output .= ( $output ? ' ' : '' ) . $time . ' ';
$output .= ( ( $time > 1 ) ? $key . 's' : $key );
$granularity --;
}
if ( $granularity == 0 )
break;
} // foreach( $periods as $key => $value )
if($future) {
return "In " . ($output ? $output : '0 seconds');
} else {
return ($output ? $output : '0 seconds') . ' ago';
}
} else
return date( $format, $ts );
}
This should work
<?php
function diffPeriods($diff)
{
$periods = array(
'Week' => 604800,
'Day' => 86400,
'Hour' => 3600,
'Minute' => 60,
'Second' => 1
);
$granularity = 1;
$output = '';
foreach ($periods as $key => $value) {
if ($diff >= $value) {
$time = round($diff / $value);
$diff %= $value;
$output .= ($output ? ' ' : '') . $time . ' ';
$output .= (($time > 1) ? $key . 's' : $key);
$granularity --;
}
if ($granularity == 0) {
break;
}
}
return $output;
}
function time_ago($ts, $format)
{
$diff = time() - $ts;
if ($diff == 0) {
return 'Now';
}
if ($diff < 604800 && $diff > 0) {
// 604800 7 days / 864000 10 days
$periods = array(
'Week' => 604800,
'Day' => 86400,
'Hour' => 3600,
'Minute' => 60,
'Second' => 1
);
$output = diffPeriods($diff);
return ($output ? $output : '0 seconds') . ' ago';
} elseif ($diff < 0 && $diff > - 604800) {
$output = diffPeriods($diff * - 1);
return 'in ' . ($output ? $output : '0 seconds');
}
// too old/new...display the date
return date($format, $ts);
}
var_dump(time_ago(time(), 'l, F d, Y H:i')); // now
var_dump(time_ago(time() + 3600, 'l, F d, Y H:i')); // 1 hour in the future
var_dump(time_ago(time() + (3600 * 50), 'l, F d, Y H:i')); // 2 daysin the future
var_dump(time_ago(time() + (3600 * 24 * 11), 'l, F d, Y H:i')); // 11 days in the future
var_dump(time_ago(time() - 3600, 'l, F d, Y H:i')); // 1 hour ago
var_dump(time_ago(time() - (3600 * 50), 'l, F d, Y H:i')); // 2 days ago
var_dump(time_ago(time() - (3600 * 24 * 11), 'l, F d, Y H:i')); // 11 days ago
Related
I have a msg system in which the format is (Sent: 08:23:38 pm) and i want it like 1 min ago etc...
this is what i got from here but its not helping me i m not able to fetch the timestamp from the db instead tried coping one of the value from column(timestamp) i.e 1467993620 so basically i want this to work in while loop and when i keep this in while loop i get error
plz help me for this
$time = strtotime(date('h:i:s a','1467993620'));
echo 'event happened '.humanTiming($time).' ago';
function humanTiming ($time)
{
$time = time() - $time; // to get the time since that moment
$time = ($time<1)? 1 : $time;
$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':'');
}
}
i just posted query with while loop and the echo timestamp hope it helps you
<?php
$req2 = mysql_query('select pm.timestamp, pm.message, user.userID as userid, user.userName, user.userAddress from pm, user where pm.userID="'.$userID.'" and user.userID=pm.user1 order by pm.id2');
while($dn2 = mysql_fetch_array($req2))
{
?>
Sent: <?php date_default_timezone_set('Asia/Kolkata'); echo date('h:i:s a',$dn2['timestamp']); ?> </small> </div>
<br />
<p> <?php echo $dn2['message']; ?> </p>
<?php
}
?>
function time_elapsed_string($ptime)
{
$etime = time() - $ptime;
if ($etime < 1)
{
return '0 seconds';
}
$a = array( 365 * 24 * 60 * 60 => 'year',
30 * 24 * 60 * 60 => 'month',
24 * 60 * 60 => 'day',
60 * 60 => 'hour',
60 => 'minute',
1 => 'second'
);
$a_plural = array( 'year' => 'years',
'month' => 'months',
'day' => 'days',
'hour' => 'hours',
'minute' => 'minutes',
'second' => 'seconds'
);
foreach ($a as $secs => $str)
{
$d = $etime / $secs;
if ($d >= 1)
{
$r = round($d);
return $r . ' ' . ($r > 1 ? $a_plural[$str] : $str) . ' ago';
}
}
}
Try this format :
<?php
$time = strtotime(date('h:i:s a','1467993620'));
$time = $time - (1 * 60); // MINUS 60 SECONDS.
$date = date("h:i:s A", $time); // NOTICE THE "A".
echo "Sent: $date";
?>
Edit : calling humanTiming with your new code :
<?php
date_default_timezone_set('Asia/Kolkata');
echo "Sent: " . humanTiming( $dn2['timestamp'] ) . " ago.";
?>
So I have this function, which displays how long it's been since a timestamp.
Right now if it's been let's say 60 minutes, it will go over and show "1 hour ago". If it's been 24 hours it goes over to "1 day ago" and so on. How could I do so that if it's been for example 1 hour, show minutes also?
Like
Event occured 58 minutes ago
3 minutes later
Event occured 1 hour 1 minute ago
26 hours later
Event occured 1 day 2 hour ago
function humanTiming($time)
{
$time = time() - $time; // 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.' ago';
}
}
You need to modify your function like this:
function humanTiming($time)
{
$time = time() - $time; // to get the time since that moment
$tokens = array (
31536000 => 'year',
2592000 => 'month',
604800 => 'week',
86400 => 'day',
3600 => 'hour',
60 => 'minute',
1 => 'second'
);
$result = '';
$counter = 1;
foreach ($tokens as $unit => $text) {
if ($time < $unit) continue;
if ($counter > 2) break;
$numberOfUnits = floor($time / $unit);
$result .= "$numberOfUnits $text ";
$time -= $numberOfUnits * $unit;
++$counter;
}
return "{$result}ago";
}
Check result on codepad.org.
PHP 5.2.0 introduced DateTime object, which will provide a better solution for the problem.
I am going to use my answer on another question to show how easy it is, though will slightly edit the code:
$create_time = "2016-08-02 12:35:04";
$current_time="2016-08-02 16:16:02";
$dtCurrent = DateTime::createFromFormat('Y-m-d H:i:s', $current_time);
// to use current timestamp, use the following:
//$dtCurrent = new DateTime();
$dtCreate = DateTime::createFromFormat('Y-m-d H:i:s', $create_time);
$diff = $dtCurrent->diff($dtCreate);
$interval = $diff->format("%y years %m months %d days %h hours %i minutes %s seconds");
$interval will return 0 years 0 months 0 days 3 hours 40 minutes 58 seconds
Let's get rid of those zero values now. Good old regex is pretty much useful here:
$interval = preg_replace('/(^0| 0) (years|months|days|hours|minutes|seconds)/', '', $interval);
In the end we get exactly what we need: 3 hours 40 minutes 58 seconds
You can use a progressive calculation method such as:
$tokens = array (
31536000 => 'year',
2592000 => 'month',
604800 => 'week',
86400 => 'day',
3600 => 'hour',
60 => 'minute',
1 => 'second'
);
$tokenValues = array();
foreach($tokens as $tokenValue => $tokenName)
{
if($time > $tokenValue)
{
$tokenValues[$tokenName] = floor($time \ $tokenValue);
$time -= $tikenValue;
}
if(count($tokenValues) == 2)
{
break;
}
}
You should then have only 2 items in tokenValues, adapt as you see fit!
You can find Event occurred time and current time difference using diff. For example see the following code
$time1 = new DateTime('2013-11-21 12:59:00'); // Event occurred time
$time2 = new DateTime(date('Y-m-d H:i:s')); // Current time
$interval = $time1->diff($time2);
echo $interval->y . " Year " .$interval->m . " Month " .$interval->d ." Days ". $interval->h . " Hours, " . $interval->i." Mintues, ".$interval->s." seconds <br/>";
I don't have time to explain, but this function works as I tested it. In addition, I add a feature to handle time from the current time and future. If you supply this function with exact current time, it will return 'just now'. If you supply it with time from the past, it will return a string ended with 'ago'. If you supply it with time from the future, it will return a string ended with 'later'. Another feature is automatic singular/plural form for the time unit. Try it yourself!
function timeEllapsedFrom($from) {
$time = time() - $from;
$diff = abs($time);
$tokens = array (
'year' => 31536000,
'month' => 2592000,
'week' => 604800,
'day' => 86400,
'hour' => 3600,
'minute' => 60,
'second' => 1
);
$result = array();
foreach ($tokens as $id => $length) {
$value = floor($diff/$length);
if ($value) $result[] = "$value $id" . ($value > 1 ? 's' : '');
$diff -= $length*$value;
}
if (!count($result)) return 'just now';
return join(', ', $result) . ($time < 0 ? ' later' : ' ago');
}
You can test it with this code:
echo timeEllapsedFrom(time() - 604800 - 7200 - 480 - 24);
and it will output:
1 week, 2 hours, 8 minutes, 24 seconds ago
Hope it helps!
Using DateTime class. Works with both past and future timestamps, and does correct pluralization when needed:
function elapsedTime($time)
{
date_default_timezone_set('UTC');
$given_time = new DateTime("#$time");
$current_time = new DateTime();
$diff = $given_time->diff($current_time);
$timemap = array('y' => 'year',
'm' => 'month',
'd' => 'day',
'h' => 'hour',
'i' => 'minute',
's' => 'second');
$timefmt = array();
foreach ($timemap as $prop => $desc) {
if ($diff->$prop > 0) {
$timefmt[] = ($diff->$prop > 1)
? "{$diff->$prop} {$desc}s"
: "{$diff->$prop} $desc";
}
}
return (!$timefmt)
? 'just now'
: ((count($timefmt) > 1)
? $diff->format(sprintf('%s and %s',
implode(', ', array_slice($timefmt, 0, -1)), end($timefmt)))
: end($timefmt))
. (($given_time < $current_time) ? ' ago' : ' later');
}
Testing:
var_dump(elapsedTime(strtotime('1987-11-25 11:40')));
# string(69) "25 years, 11 months, 29 days, 17 hours, 50 minutes and 42 seconds ago"
var_dump(elapsedTime(time()));
# string(8) "just now"
var_dump(elapsedTime(strtotime('2013-11-25')));
# string(41) "18 hours, 29 minutes and 18 seconds later"
What is the most efficient way to get an array of months, from a specified date, up until the present day, grouped by year.
Eg getMonths("August 2012") would output
array(
array("Year"=>"2013", "months" = array(
"February", "January")
),
array("Year"=>"2012", "months" = array(
"December", "November","October", "September", "August")
)
)
So far I've got:
$start = strtotime('2012-08-01');
$end = time();
$month = $start;
$months[] = date('F', $start);
while($month <= $end) {
$month = strtotime("+1 month", $month);
$months[] = date('F', $month);
}
This is outputting the correct months, but not grouping them into years.
Thanks
You can try
function getMonths($month,$count = 1) {
$now = new DateTime();
$start = DateTime::createFromFormat("F Y", $month);
$list = array();
$interval = new DateInterval(sprintf("P%dM",$count));
while ( $start <= $now ) {
$list[$start->format("Y")][] = $start->format("F");
$start->add($interval);
}
return $list;
}
print_r(getMonths("August 2012"));
Output
Array
(
[2012] => Array
(
[0] => August
[1] => September
[2] => October
[3] => November
[4] => December
)
[2013] => Array
(
[0] => January
[1] => February
)
)
Since the answer posted here did not work for me (also tried online sandbox to be sure) i wrote a method that works with the very most versions of PHP:
function getMonths($monat, $year) {
$list = array();
for(;$monat <= 12;$monat++) {
if($year == date("Y") && $monat == date("m")) { // exit on current month+year
break;
}
if(!isset($list[ $year ])) {
$list[ $year ] = array();
}
$list[ $year ][ str_pad($monat, 2, '0', STR_PAD_LEFT) ] = date("F", strtotime('01.' . $monat . '.' . $year));
if($monat == 12) {
$monat = 0;
$year++;
}
}
return $list;
}
I tried calling up: echo PrettyTime( time() - 70 * 60 ), expecting it would say 1 hour ago, but it instead says 70 minutes ago, and I can't seem to figure out why... I think it may be a rounding issue that I'm too dumb to find, but here is the code that I'm using:
function PrettyTime( $time )
{
$current = time();
if ( $time == $current )
return 'just now';
if ( $time == 0 )
return 'a long time ago';
$time = $current - $time;
$intervals = array
(
'year' => 29030400,
'month' => 2592000,
'week' => 604800,
'day' => 86400,
'hour' => 3600,
'minute' => 60,
'second' => 1
);
foreach( $intervals as $word => $interval )
{
$works = intval( $time / $interval );
$future = $works < 0;
if ( !$works )
continue; /* keep going through, silly! */
else
{
if ( !$future && $works == 1 )
{
switch( $word )
{
case 'year': return 'last year';
case 'month': return 'last month';
case 'week': return 'last week';
case 'day': return 'yesterday';
default: break;
}
}
else
break;
}
}
return abs($works) . ' ' . $word . ( $works ? 's' : '') . ($future ? ' in the future' : ' ago');
}
Actually running the code: - it's the break; in the default: clause. You must use break 2; there to break out of the switch and the foreach.
You don't always break out of the outer foreach loop when you seem to want to. Try removing the final else line and dropping the indent on the break statement under it.
How might I code a function in PHP (with CodeIgniter) to merge days with similar opening hours of a store together. For example, if we have:
Mon 9am-5pm
Tue 9am-5pm
Wed 9am-5pm
Thu 9am-5pm
Fri 9am-5pm
Sat 9am-7pm
Sun 9am-7pm
I want the code to simplify it to:
Mon-Fri 9am-5pm
Sat-Sun 9am-7pm
How do I do this without a long list of if/else or case ifs? I'm using CodeIgniter..
<?php
$openHours = array(
'Mon' => '9am-5pm',
'Tue' => '9am-5pm',
'Wed' => '9am-9pm',
'Thu' => '9am-5pm',
'Fri' => '9am-5pm',
'Sat' => '9am-7pm',
'Sun' => '9am-7pm'
);
$summaries = array();
foreach ($openHours as $day => $hours) {
if (count($summaries) === 0) {
$current = false;
} else {
$current = &$summaries[count($summaries) - 1];
}
if ($current === false || $current['hours'] !== $hours) {
$summaries[] = array('hours' => $hours, 'days' => array($day));
} else {
$current['days'][] = $day;
}
}
foreach ($summaries as $summary) {
if (count($summary['days']) === 1) {
echo reset($summary['days']) . ' ' . $summary['hours'] . PHP_EOL;
} else {
echo reset($summary['days']) . '-' . end($summary['days']) . ' ' . $summary['hours'] . PHP_EOL;
}
}
codepad sample
If you want it in the following format:
Sun-Tue, Fri-Sat: 11am-12am; Wed: 10am-12am; Thu: 9am-12am
Which will group days and handle different times within the week:
<?php
$open_hours = array (
"Sun" => "11am-12am",
"Mon" => "11am-12am",
"Tue" => "11am-12am",
"Wed" => "10am-12am",
"Thu" => "9am-12am",
"Fri" => "11am-12am",
"Sat" => "11am-12am"
);
$result = [];
foreach ($open_hours as $day => $hours) {
if (empty($result) || $previous !== $hours) {
$result[$hours][] = $day;
} elseif ($previous === $hours) {
$key = array_key_last($result[$hours]);
$current = strtok($result[$hours][$key], '-');
$result[$hours][$key] = $current.'-'.$day;
}
$previous = $hours;
}
// build output (joining days with ,)
$output = [];
foreach ($result as $hours => $days) {
$output[] = implode(', ', $days).': '.$hours;
}
// join with ;'s and output
echo implode('; ', $output);
https://3v4l.org/tKOlI