how to use function for array data [duplicate] - php

This question already has answers here:
Converting timestamp to time ago in PHP e.g 1 day ago, 2 days ago...
(32 answers)
Closed 8 years ago.
i have a span tag which has array data like
<?php echo " <span >".$comments_array[$j]['posted_time']."</span> "; ?>
and it echo's time of the comment as 2014-04-11 05:07:52
now i have a function that display the time in the format of x hrs ago,
below is the function
define("SECOND", 1);
define("MINUTE", 60 * SECOND);
define("HOUR", 60 * MINUTE);
define("DAY", 24 * HOUR);
define("MONTH", 30 * DAY);
function relTime($time)
{
$now = new DateTime;
$dateObj = new DateTime($dt);
$diff = (array) $now->diff($dateObj);
$diff['w'] = floor($diff['d'] / 7);
$diff['d'] -= $diff['w'] * 7;
$tokens = array(
'y' => 'year',
'm' => 'month',
'w' => 'week',
'd' => 'day',
'h' => 'hour',
'i' => 'minute',
's' => 'second'
);
foreach ($tokens as $unit => &$text)
{
if ($diff[$unit])
{
$text = sprintf(
'%s %s%s',
$diff[$unit], $text, ($diff[$unit] > 1 ? 's' : '')
);
}
else
{
unset($tokens[$unit]);
}
}
return array_shift($tokens);
}
now how can i call that function and echo that time in desired format
help me please

There's a better and cleaner way to achieve this. Here's a function, which, given a date/time string and a format string, will return the difference from now in the desired format.
function getDatetimeDifference($datetime, $format) {
$datetime_obj = new DateTime($datetime);
$now = new DateTime();
$difference = date_diff($now, $datetime_obj);
$result = $difference->format($format);
return $result;
}
Here's a use case:
echo getDatetimeDifference(
'2013-04-11 10:35:33',
'%R%a days, %h hours, %i minutes, %s seconds ago'
);
// Outputs "-364 days, 23 hours, 55 minutes, 10 seconds ago"
If you want to work with the total amount of hours since that time, you will fare better if you work with timestamps, since you can easily substract the difference and then divide it by 3600 to get the time difference in hours.
Keep in mind that the DateTime objects will overflow if you don't pass the appropriate format - for example, if you use the above function to get only the hours between now and the last year, you will get 23 as result. My advice - use a similar function, pass a suitable format that you can parse later in tokens, and eliminate left to right tokens until you reach a non-negative value.
Cheers.

Related

In PHP, how do I get the accurate (not approximate) total individual number of weeks, months and years between two timestamps?

I can do it for days like this:
$d1 = new DateTime('2000-01-01 12:00:00');
$d2 = new DateTime('2020-01-01 12:00:00');
$diff = $d2->diff($d1);
echo $diff->days;
In other words, it works for days. However, the DateTime/DateInterval class has only a $days variable -- these are expected but don't exist:
$diff->weeks;
$diff->months;
$diff->years;
Reading the manual, you might at first glance be deceived into thinking that it does have these attributes: https://www.php.net/manual/en/class.dateinterval.php
public integer $y ;
public integer $m ;
public integer $d ;
public integer $h ;
public integer $i ;
public integer $s ;
public float $f ;
public integer $invert ;
public mixed $days ;
The y, m, d, h, i, s there are not "individual totals", but depend on each other. For example, if the time span is exactly one year, the $y will be 1, but all of the other ones will be 0, instead of their respective representations (12 months, 52 weeks, etc.).
They treat days specially for some reason by including the $days variable, which does show the actual total number of days. I want that for weeks, months and years too.
I already know how to "estimate" the number of weeks/months/years between two timestamps, by using simple math and fixed variables representing the average number of seconds in each time unit. Since this doesn't take into consideration all the complexities of "traversing" the calendar format(s), such as leap years, varying days in different months, and many other small/complex details, you don't get the exact number that way.
I want to know the exact total number of weeks between two timestamps, and the same thing for years and months, independent of each other.
This will return the exact difference between two days hope this will help you.
$time_diffrence=getDiffrenceBetweenTwoDays($date1,$date2);
function getDiffrenceBetweenTwoDays($date1,$date2){
$etime = strtotime($date1) - strtotime($date2;
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) .'' ;
}
}
}
Replace %a with any of the following at this link:
FORMATS
$d1 = date_create('2000-01-01 12:00:00');
$d2 = date_create('2020-01-01 12:00:00');
$diff = date_diff($d1, $d2);
$days = $diff->format('%a');
echo $days; // 7305

Format datetime interval with a minimum difference

I found this really nice PHP script that converts any datetime into a relative string, for example:
'2013-05-01 00:22:35' -> '3 months ago'
It's really cool, but I would like to "trick" the function so that even if the date is, let's say, 20 minutes before, the function returns 1 hour ago instead of 20 minutes ago. Thus, I want to enforce a minimum difference of 1 hour, even when the difference is less than that.
For reference, here is the function.
function time_elapsed_string($datetime, $full = false) {
$now = new DateTime;
$ago = new DateTime($datetime);
$diff = $now->diff($ago);
$diff->w = floor($diff->d / 7);
$diff->d -= $diff->w * 7;
$string = array(
'y' => 'year',
'm' => 'month',
'w' => 'week',
'd' => 'day',
'h' => 'hour',
'i' => 'minute',
's' => 'second',
);
foreach ($string as $k => &$v) {
if ($diff->$k) {
$v = $diff->$k . ' ' . $v . ($diff->$k > 1 ? 's' : '');
} else {
unset($string[$k]);
}
}
if (!$full) $string = array_slice($string, 0, 1);
return $string ? implode(', ', $string) . ' ago' : 'just now';
}
I tried a lot of different things, but nothing really worked.
How can I enforce a minimum difference of 1 hour?
After you have figured out the difference, simply check if the largest difference is only minutes or seconds. If so, return the minimum of 1 hour that you require.
// here is your foreach loop
// check if less than 1 hour, if so, return that
$keys = array_keys($string);
if ($keys[0] === 'i' || $keys[0] === 's') {
return 'less than 1 hour ago';
}
Try it online!
I put the time of posting the question in this example. When you look at it more than 1 hour after that, you'll have to modify the test case to a DateTime that is less than 1 hour ago in UTC time.
Test cases. It is now 2017-06-10 12:45:00 in UTC.
time_elapsed_string("2017-06-10 12:11:19"); // less than 1 hour ago
time_elapsed_string("2017-06-10 11:44:00"); // 1 hour ago
time_elapsed_string("2017-06-10 11:44:00", true); // 1 hour, 1 minute ago
time_elapsed_string("2017-06-09 11:45:00", true); // 1 day, 1 hour ago
time_elapsed_string("2017-06-09 11:45:00"); // 1 day ago
days : If the DateInterval object was created by DateTime::diff(), then this is the total number of days between the start and end dates. Otherwise, days will be FALSE. http://php.net/manual/en/class.dateinterval.php
Since we know it won't be false, it will evaluate to false only when 0.
if($diff->days) {
$diff->w = floor($diff->d / 7);
$diff->d -= $diff->w * 7;
} else /* less than a day's difference */ if(!$diff->h && ($diff->i || $diff->s)) /* less than an hour's difference */ {
$diff->h = 1;
$diff->i = 0;
$diff->s = 0;
}
I've added some refinements to your original code. I've also removed the full option from your function as I don't think you intend to use it for your case. If my inline comments fail to explain my process, just ask.
Code: (Demo)
function time_elapsed_string($datetime){
$now=new DateTime; // current datetime
$ago=new DateTime($datetime); // user datetime
if($now<$ago){return "Unexpected future datetime value";}
$diff=$now->diff($ago); // datetime difference
$diff->w=intval(floor($diff->d/7)); // add weeks to diff output
$diff->d-=$diff->w*7; // reduce days based on weeks calculation
$units=[
'y'=>'year',
'm'=>'month',
'w'=>'week',
'd'=>'day',
'h'=>'hour'
];
$kept_diff=array_intersect_key((array)$diff,$units); // omit unwanted elements of diff()'s output
if(!max($kept_diff)){ // if y, m, w, d, & h all = 0, show default
return 'default: 1 hour ago'; // inserted "default: " for demo. Remove in production.
}else{
$diffs=array_filter(array_merge($units,$kept_diff)); // sort by $units order, then omit elements with 0 value
return current($diffs).' '.$units[key($diffs)].(current($diffs)>1?'s':'').' ago'; // return highest unit data in plain English
}
}
echo time_elapsed_string('2017-06-30 02:22:35'); // output: 3 weeks ago

Should I store the result of an function into an array?

I have a function like this:
function time_elapsed_string($ptime)
{
$date_time = strtotime("1348-10-10 04:30:01") + $ptime;
$year = date("Y",$date_time);
$month = date("m",$date_time);
$day = date("d",$date_time);
$time = date("H:i:s",$date_time);
$etime = time() - $ptime + 1;
$a = array( 31536000 => 'year',
2592000 => 'month',
86400 => 'day',
3600 => 'hour',
60 => 'minute',
1 => 'second'
);
foreach ($a as $secs => $str)
{
$d = $etime / $secs;
if ($d >= 1)
{
$r = round($d);
// EX:
return array('date' => $day.'-'.$month.'-'.$year, // 2016-02-20
'time' => $time, // 03:30:04
'difference' => $r . ' ' . $str . ' ago' // 2 month ago
);
}
}
}
And I use it like this:
$ptime = 1470692661;
$html = '<span title="date: '.time_elapsed_string($ptime)['date'].' time: '.time_elapsed_string($ptime)['time'].'">in '.time_elapsed_string($ptime)['difference'].'<span>';
As you see, I'm using of that function's result like this:
time_elapsed_string($ptime)['date']
ime_elapsed_string($ptime)['time']
time_elapsed_string($ptime)['difference']
In fact I'm calling that function every time I need one of its results. Is that right? Or should I call it once and store it into an array?
Note: My code works as well.
Counting time elapsed since some date/time like this is mauvais ton.
DateTime has been available since PHP 5.2.0 and tonns of people underestimate it. Why don't you use this instead of loops and ifs?
$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);
Now, you can format the result however you want:
$interval = $diff->format("%h hours %i minutes %s seconds");
This will give a clean 3 hours 40 minutes 58 seconds without any arrays, which is better.
UPDATE
There is a general solution to get hours / minutes / seconds via regex:
$interval = $diff->format("%y years %m months %d days %h hours %i minutes %s seconds");
// now remove zero values
$interval = preg_replace('/(^0| 0) (years|months|days|hours|minutes|seconds)/', '', $interval);
UPDATE 2
As of your comment:
Look, I want to use your approach .. but I really cannot implement it .. Actually I need three things: time, date, difference ..! But your approach doesn't give me them..
Well, we already know how to get the difference, it's the $interval variable described above.
To get time and date, you can get it from the $dtCreate variable by, again, using format:
$time = $dtCreate->format('H:i:s');
$date = $dtCreate->format('d-m-Y');
This is a no brainer.
Yes - store the function call result of time_elapsed_string($ptime) in an array, then use that to access your results. You're wasting CPU cycles otherwise!
// call it once
$result = time_elapsed_string($ptime);
// then use:
$result['date'];
$result['time'];
$result['difference'];

Subtracting time to post how many minutes ago [duplicate]

This question already has answers here:
Calculate relative time in C#
(41 answers)
How to display "12 minutes ago" etc in a PHP webpage? [closed]
(3 answers)
Closed 8 years ago.
So my current $item['date'] function gets the time and date of the post in this format Y-m-d H:i:s.
I want to display how many minutes was the post posted or if it is more than 24 hours, how many days ago was it posted OR like 0 days and 20 hours ago? something like that
Why doesn't the minus operator work here my code?
My current code:
<p><?php echo date('Y-m-d H:i:s') - $item['date'] ?> minutes ago</p>
I usually use this function. Use it like this time_ago('2014-12-03 16:25:26')
function time_ago($date){
$retval = NULL;
$granularity=2;
$date = strtotime($date);
$difference = time() - $date;
$periods = array('decade' => 315360000,
'year' => 31536000,
'month' => 2628000,
'week' => 604800,
'day' => 86400,
'hour' => 3600,
'minute' => 60,
'second' => 1);
foreach ($periods as $key => $value)
{
if ($difference >= $value)
{
$time = round($difference/$value);
$difference %= $value;
$retval .= ($retval ? ' ' : '').$time.' ';
$retval .= (($time > 1) ? $key.'s' : $key);
$granularity--;
}
if ($granularity == '0') { break; }
}
return $retval.' ago';
}
What you need to do is convert both dates to timestamp first and substract your original post date from current date and reconvert it back to your desired format. As an example see below.
$now = time();
$datePosted = strtotime($item['date']);
$timePassed = $now - $datePosted;
$agoMinutes = $timePassed/60; //this will give you how many minutes passed
$agoHours = $agoMinutes/60; //this will give you how many hours passed
$agoDays = $agoHours/24; // this will give you how many days passed
And so on ...
Php's timestamp gives date in seconds so it is easier to calculate and work on it if you need mathematical operations.

PHP - subtracting time return nothing

I found a function form SC to output human readable time. like `
5 hours, 1 hour, 5 years, etc
function human_time ($time)
{
$time = time() - strtotime($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.(($numberOfUnits>1)?'s':'');
}
}
And I have time as string: 2013-09-28 20:55:42
when I call this function human_time('2013-09-28 20:55:42')
then it return nothing, why ?
I have added strtotime in above function.
Please tell me what is wrong.
This is no ready-to-use code, but rather supposed to guide you the right way:
$then = new DateTime($time); // you might need to format $time using strtotime or other functions depending on the format provided
$now = new DateTime();
$diff = $then->diff($now, true);
echo $diff->format('Your style goes here');
See DateTime Manual for further documentation or feel free to ask here.
Edit: Link fixed.
Use example :
echo time_elapsed_string('2013-05-01 00:22:35');
echo time_elapsed_string('2013-05-01 00:22:35', true);
Output :
4 months ago
4 months, 2 weeks, 3 days, 1 hour, 49 minutes, 15 seconds ago
Link to the function.

Categories