cannot get human readable text from various functions discovered - php

I am trying to transform a unix timestamp into a human readable string so i can show how long ago a user signed up.
Here is my data:
mysql> select createdate as unixtimestamp,date_format(from_unixtime(createdate),'%e %b %Y') as dateformatted from users where userid=40645;
+---------------+---------------+
| unixtimestamp | dateformatted |
+---------------+---------------+
| 1162642968 | 4 Nov 2006 |
+---------------+---------------+
1 row in set (0.00 sec)
mysql>
Ok so here is where the problem resides. I found 3 different functions on the internet that return a human readable string from a unix timestamp. All 3 failed to work.
I'd like someone to look at these functions and help me figure out how to fix one of them to return the correct human readable string.
On with the show!
Here is function #1:
function getElapstedTimeHumanReadable($time)
{
$names = array("seconds", "minutes", "hours", "days", "months", "years");
$values = array(1, 60, 3600, 24 * 3600, 30 * 24 * 3600, 365 * 24 * 3600);
$time = time()-$time;
for($i = count($values) - 1; $i > 0 && $time < $values[$i]; $i--);
if($i == 0) {
$timestamp = intval($time / $values[$i]) . " " . $names[$i];
} else {
$t1 = intval($time / $values[$i]);
$t2 = intval(($time - $t1 * $values[$i]) / $values[$i - 1]);
$timestamp= "$t1 " . $names[$i] . ", $t2 " . $names[$i - 1];
}
return $timestamp;
}
My return value for this function is "Joined 1 days, 17 hours ago"
Clearly this isn't correct.
Here is function #2:
function getElapsedTimeHumanReadable($time)
{
$time = time() - $time;
$points = array(
'year' => 31556926,
'month' => 2629743,
'week' => 604800,
'day' => 86400,
'hour' => 3600,
'minute' => 60,
'second' => 1
);
foreach($points as $point => $value)
{
if($elapsed = floor($time/$value) > 0)
{
$s = $elapsed>1?'s':'';
$timestamp = "$elapsed $point$s";
break;
}
}
return $timestamp;
}
My return value for this function is "Joined 1 day ago
And finally, here is function #3:
function getElapsedTimeHumanReadable($time)
{
$etime=time()-$time;
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';
}
}
}
So theres my code and my data. Not quite sure why none seem to work. I tried looking at the code but I cannot figure out how to solve it.
Whats interesting is they all say 2 days, but my timestamp appears to show 2006.
Thanks for the help.

$time = 1162642968 ;
$date = new DateTime( );
$date->setTimestamp( $time );
$today = new DateTime( 'now', new DateTimeZone( "Europe/Rome" ) );
$diff = $today->diff( $date);
echo "Year: " . $diff->y . " - Month: " . $diff->m . " - Days: " . $diff->d . " - Hours: " . $diff->h;
EXAMPLE
As suggested I'll add explanation, even if I think it is really self explain.
$date = new DateTime() create the object and $date->setTimestamp( $time ) is used to put that date at a value from the mysql timestamp.
$today is created pointing at the actual date.
$date->diff() create a DateInterval Object ( http://php.net/manual/en/class.dateinterval.php ) that contains all the necessary datas.

If you want to solve this yourself, you should calculate the difference and base it on those values. I haven't tested RiccardoC's Answer, but this seems as a nice way to go.
As I see in your posting, you calculate a year always as 365 days, so if you don't want to go in a deep detail with time zones, extra hours, extra days, different month lengths etc, you could use something simple as that:
function getElapsedTimeHumanReadable($timestamp) {
$diff = time() - $timestamp;
$years = intval($diff/31536000); //seconds in a year 60*60*24*365
$diff -= ($years*31536000);
$months = intval($diff/2592000); //seconds in a month 60*60*24*30
$diff -= ($months*2592000);
$days = intval($diff/86400); //seconds in a day 60*60*24
return $years." years, ".$months." months, ".$days." days ago";
}
echo getElapsedTimeHumanReadable(1162642968); // November 4th, 2006
Echos 9 years, 0 months, 17 days ago

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

PHP Carbon take number of minutes & convert to days

I am trying to convert a number on minutes into number of days using Carbon.
$minutes = 1400;
I want to do something like below (which of course, does not work):
Carbon->minutes($minutes)->days();
I cannot find an example of this. Thanks for any help.
Not tested, but a quick look at the docs suggests it might be aimed more at DateTime objects than differences in time, so you could do something like this:
$now = Carbon::now();
$days = $now->diffInDays($now->copy()->addMinutes($minutes));
Maybe CarbonInterval::minutes($minutes)->cascade();?
Will cascade down your value and format it for humans.
If you want to convert seconds to Jira style 1y 1m 1w 1h 1m 1s:
class Translator implements TranslatorInterface, TranslatorBagInterface
{
protected const TRANS = [
'year' => 'y',
'month' => 'm',
'week' => 'w',
'day' => 'd',
'hour' => 'h',
'minute' => 'm',
'second' => 's',
];
public function trans(string $id, array $parameters = [], string $domain = null, string $locale = null)
{
return $parameters[':count'].self::TRANS[$id];
}
public function getCatalogue(string $locale = null)
{
return new \Symfony\Component\Translation\MessageCatalogue('pl_PL');
}
}
$second = 1;
$minute = 60 * $second;
$hours = 60 * $minute;
$day = 24 * $hours;
$week = 7 * $day;
$month = 4 * $week;
$year = 12 * $month;
$sum = $second + $minute + $hours + $day + $week + $month + $year;
$interval = CarbonInterval::seconds($sum)->cascade();
$interval->setLocalTranslator(new Translator());
echo $interval->forHumans(); // 1y 1m 1w 1h 1m 1s
if you want to convert to years, months, weeks, days, hours, minutes, seconds, microseconds
use Carbon\CarbonInterval;
echo CarbonInterval::minutes(2212)->cascade()->forHumans();
//output = 1 day 12 hours 52 minutes

displaying relevant date formats in months days minutes or seconds?

im trying to convert a mysql timestamp to time in months or days or hours or minutes.
so the output will look like this:
added 1 month ago / added: 0 hours ago / added: 21 minutes ago / added 30 seconds ago
so i only want one format of time depending on how many minutes or how many hours or how many days etc, so 60 minutes converts to 1 hour ago or 24 hours converts to 1 day ago and 48 hours converts to 2 dayS ago.
so far i have this code:
<?
$datetime1 = new DateTime();
$datetime2 = new DateTime ($news['date_added']);
$interval = $datetime1->diff($datetime2);
str_replace('0 hours', '', $variable);
echo $interval->format('%h hours %i minutes');
?>
and this outputs the following:
added 0 hours ago 57 minutes ago.
can someone help me or show me what id need to do in order to get the formats to display right, im really new to php and am not sure how i can do this. thank you.
From http://php.net/manual/en/ref.datetime.php
Just change $precision to 1 when you call the function and add in whatever text you want to come before and after the date. You'll have to make sure you convert your date objects to timestamps, but that shouldn't be a problem for you.
/**
* this code assumes php >= 5.1.0. if using < 5.1, read
* php.net/strtotime and change the condition for checking
* for failure from strtotime()
*/
// $t1, $t2: unix times, or strtotime parseable
// $precision: max number of units to output
// $abbr: if true, use "hr" instead of "hour", etc.
function date_diff ($t1, $t2, $precision = 6, $abbr = false) {
if (preg_match('/\D/', $t1) && ($t1 = strtotime($t1)) === false)
return false;
if (preg_match('/\D/', $t2) && ($t2 = strtotime($t2)) === false)
return false;
if ($t1 > $t2)
list($t1, $t2) = array($t2, $t1);
$diffs = array(
'year' => 0, 'month' => 0, 'day' => 0,
'hour' => 0, 'minute' => 0, 'second' => 0,
);
$abbrs = array(
'year' => 'yr', 'month' => 'mth', 'day' => 'day',
'hour' => 'hr', 'minute' => 'min', 'second' => 'sec'
);
foreach (array_keys($diffs) as $interval) {
while ($t2 >= ($t3 = strtotime("+1 ${interval}", $t1))) {
$t1 = $t3;
++$diffs[$interval];
}
}
$stack = array();
foreach ($diffs as $interval => $num)
$stack[] = array($num, ($abbr ? $abbrs[$interval] : $interval) . ($num != 1 ? 's' : ''));
$ret = array();
while (count($ret) < $precision && ($item = array_shift($stack)) !== null) {
if ($item[0] > 0)
$ret[] = "{$item[0]} {$item[1]}";
}
return implode(', ', $ret);
}
$t1 = 'Feb 4, 2008 12:16:00';
$t2 = 'Jul 3, 2006 16:15:30';
echo date_diff($t1, $t2), "\n",
date_diff($t1, $t2, 3), "\n",
date_diff($t1, $t2, 2, true), "\n";
?>
Here is a possible solution. You format the time difference as a string with months-days-hours-minutes-seconds, then look through that string for the first non-zero number: that's the one you want...
$mdhms = explode('-',$interval->format('%m-%d-%H-%i-%s'));
$labels = Array(' months', ' days', ' hours', ' minutes', ' seconds');
$i = 0;
foreach($mdhms as $t){
if($t > 0) break;
$i+=1;
}
if ($i < 5) echo "It happened ".$t.$labels[$i]." ago";
else echo "It is happening right now!"

Convert Standard Date to Current Time in Hours/Mins/

Say I have a date function that produces
the output: 2011-10-03
PHP:
$todayDt = date('Y-m-d');
Anyway to get this date to instead show 2 days 1 hour ago
This function might be of some use. You might want to refine the check for months a bit, but this is just a quick example:
function RelativeTime($iTimestamp, $iLevel = 2)
{
!ctype_digit($iTimestamp)
&& $iTimestamp = strtotime($iTimestamp);
$iSecondsInADay = 86400;
$aDisplay = array();
// Start at the largest denominator
$iDiff = time() - $iTimestamp;
$aPeriods = array(
array('Period' => $iSecondsInADay * 356, 'Label' => 'year'),
array('Period' => $iSecondsInADay * 31, 'Label' => 'month'),
array('Period' => $iSecondsInADay, 'Label' => 'day'),
array('Period' => 3600, 'Label' => 'hour'),
array('Period' => 60, 'Label' => 'minute'),
array('Period' => 1, 'Label' => 'second'),
);
foreach ($aPeriods as $aPeriod)
{
$iCount = floor($iDiff / $aPeriod['Period']);
if ($iCount > 0)
{
$aDisplay[] = $iCount . ' ' . $aPeriod['Label'] . ($iCount > 1 ? 's' : '');
$iDiff -= $iCount * $aPeriod['Period'];
}
}
$iRange = count($aDisplay) > $iLevel
? $iLevel
: count($aDisplay);
return implode(' ', array_slice($aDisplay, 0, $iRange)) . ' ago';
}
And some examples of usage:
echo RelativeTime(time() - 102, 1);
// Will output: 1 minute ago
echo RelativeTime(time() - 2002);
// Will output: 33 minutes 22 seconds ago
echo RelativeTime(time() - 100002002, 6);
// Will output: 3 years 2 months 27 days 10 hours 20 minutes 2 seconds ago
echo RelativeTime('2011-09-05');
// Will output: 30 days 22 hours ago
This is post is just for a solution that does not use the DateTime::diff method. It also uses inputs with greater precision, so be aware of that.
$now = date('Y-m-d H:i:s');
$then = '2011-10-03 00:00:00'; // This will calculate the difference
// between now and midnight October 3rd
$nowTime = strtotime($now);
$thenTime = strtotime($then);
$diff = $nowTime - $thenTime;
$secs = $diff % 60;
$diff = intval($diff / 60);
$minutes = $diff % 60;
$diff = intval($diff / 60);
$hours = $diff % 24;
$diff = intval($diff / 24);
$days = $diff;
echo($days . ' days ' . $hours . ' hours ' . $minutes . ' minutes ' . $secs . ' seconds ago');
At the moment I tested it, the output was:
2 days 16 hours 6 minutes 2 seconds ago
If all you want are the days and hours, then you can just choose to echo those two out:
echo($days . ' days ' . $hours . ' hours ago');
2 days 16 hours ago

How to convert seconds to time format? [duplicate]

This question already has answers here:
Convert seconds to Hour:Minute:Second
(30 answers)
Closed 9 years ago.
For some reason I convert a time format like: 03:30 to seconds 3*3600 + 30*60, now. I wanna convert it back to its first (same) format up there. How could that be?
My attempt:
3*3600 + 30*60 = 12600
12600 / 60 = 210 / 60 = 3.5, floor(3.5) = 3 = hour
Now, what about the minutes?
Considering the value can be like 19:00 or 02:51.
I think you got the picture.
And by the way, how to convert 2:0 for example to 02:00 using RegEx?
This might be simpler
gmdate("H:i:s", $seconds)
PHP gmdate
$hours = floor($seconds / 3600);
$mins = floor($seconds / 60 % 60);
$secs = floor($seconds % 60);
If you want to get time format:
$timeFormat = sprintf('%02d:%02d:%02d', $hours, $mins, $secs);
If the you know the times will be less than an hour, you could just use the date() or $date->format() functions.
$minsandsecs = date('i:s',$numberofsecs);
This works because the system epoch time begins at midnight (on 1 Jan 1970, but that's not important for you).
If it's an hour or more but less than a day, you could output it in hours:mins:secs format with `
$hoursminsandsecs = date('H:i:s',$numberofsecs);
For more than a day, you'll need to use modulus to calculate the number of days, as this is where the start date of the epoch would become relevant.
Hope that helps.
Maybe the simplest way is:
gmdate('H:i:s', $your_time_in_seconds);
Let $time be the time as number of seconds.
$seconds = $time % 60;
$time = ($time - $seconds) / 60;
$minutes = $time % 60;
$hours = ($time - $minutes) / 60;
Now the hours, minutes and seconds are in $hours, $minutes and $seconds respectively.
Another solution that will give you the days, hours, minutes, and seconds for a passed-in seconds value:
function seconds_to_time($secs)
{
$dt = new DateTime('#' . $secs, new DateTimeZone('UTC'));
return array('days' => $dt->format('z'),
'hours' => $dt->format('G'),
'minutes' => $dt->format('i'),
'seconds' => $dt->format('s'));
}
print_r(seconds_to_time($seconds_value);
Extra logic will be needed for 'days' if the time is expected to be more than one year. Use str_pad() or ltrim() to add/remove leading zeros.
ITroubs answer doesn't deal with the left over seconds when you want to use this code to convert an amount of seconds to a time format like hours : minutes : seconds
Here is what I did to deal with this:
(This also adds a leading zero to one-digit minutes and seconds)
$seconds = 3921; //example
$hours = floor($seconds / 3600);
$mins = floor(($seconds - $hours*3600) / 60);
$s = $seconds - ($hours*3600 + $mins*60);
$mins = ($mins<10?"0".$mins:"".$mins);
$s = ($s<10?"0".$s:"".$s);
$time = ($hours>0?$hours.":":"").$mins.":".$s;
$time will contain "1:05:21" in this example.
If you were to hardcode it you would use modulus to extract the time as others suggested.
If you are returning the seconds from MySQL database, assuming you don't need the data in seconds format in your app, there is a much cleaner way to do it, you can use MySQL's SEC_TO_TIME and it will return time in hh:mm:ss format.
Eg.
SELECT SEC_TO_TIME(my_seconds_field) AS my_timestring;
Sorry this is too late but maybe useful
function mediaTimeDeFormater($seconds)
{
if (!is_numeric($seconds))
throw new Exception("Invalid Parameter Type!");
$ret = "";
$hours = (string )floor($seconds / 3600);
$secs = (string )$seconds % 60;
$mins = (string )floor(($seconds - ($hours * 3600)) / 60);
if (strlen($hours) == 1)
$hours = "0" . $hours;
if (strlen($secs) == 1)
$secs = "0" . $secs;
if (strlen($mins) == 1)
$mins = "0" . $mins;
if ($hours == 0)
$ret = "$mins:$secs";
else
$ret = "$hours:$mins:$secs";
return $ret;
}
echo mediaTimeDeFormater(216.064000);//3:36
something like this?
if(is_numeric($time)){
$value = array(
"years" => 0, "days" => 0, "hours" => 0,
"minutes" => 0, "seconds" => 0,
);
if($time >= 31556926){
$value["years"] = floor($time/31556926);
$time = ($time%31556926);
}
if($time >= 86400){
$value["days"] = floor($time/86400);
$time = ($time%86400);
}
if($time >= 3600){
$value["hours"] = floor($time/3600);
$time = ($time%3600);
}
if($time >= 60){
$value["minutes"] = floor($time/60);
$time = ($time%60);
}
$value["seconds"] = floor($time);
return (array) $value;
} else{
return (bool) FALSE;
}
grabbed from: http://www.ckorp.net/sec2time.php
Use modulo:
$hours = $time_in_seconds / 3600;
$minutes = ($time_in_seconds / 60) % 60;
just one small additional example
requested time in miliseconds
// ms2time( (microtime(true) - ( time() - rand(0,1000000) ) ) );
// return array
function ms2time($ms){
$return = array();
// ms
$return['ms'] = (int) number_format( ($ms - (int) $ms), 2, '', '');
$seconds = (int) $ms;
unset($ms);
if ($seconds%60 > 0){
$return['s'] = $seconds%60;
} else {
$return['s'] = 0;
}
if ( ($minutes = intval($seconds/60))){
$return['m'] = $minutes;
}
if (isset($return['m'])){
$return['h'] = intval($return['m'] / 60);
$return['m'] = $return['m'] % 60;
}
if (isset($return['h'])){
$return['d'] = intval($return['h'] / 24);
$return['h'] = $return['h'] % 24;
}
if (isset($return['d']))
$return['mo'] = intval($return['d'] / 30);
foreach($return as $k=>$v){
if ($v == 0)
unset($return[$k]);
}
return $return;
}
// ms2time2string( (microtime(true) - ( time() - rand(0,1000000) ) ) );
// return array
function ms2time2string($ms){
$array = array(
'ms' => 'ms',
's' => 'seconds',
'm' => 'minutes',
'h' => 'hours',
'd' => 'days',
'mo' => 'month',
);
if ( ( $return = ms2time($ms) ) && count($ms) > 0){
foreach($return as $key=>$data){
$return[$key] = $data .' '.$array[$key];
}
}
return implode(" ", array_reverse($return));
}
Here is another way with leading '0' for all of them.
$secCount = 10000;
$hours = str_pad(floor($secCount / (60*60)), 2, '0', STR_PAD_LEFT);
$minutes = str_pad(floor(($secCount - $hours*60*60)/60), 2, '0', STR_PAD_LEFT);
$seconds = str_pad(floor($secCount - ($hours*60*60 + $minutes*60)), 2, '0', STR_PAD_LEFT);
It is an adaptation from the answer of Flaxious.
If You want nice format like: 0:00:00 use str_pad() as #Gardner.
1 day = 86400000 milliseconds.
DecodeTime(milliseconds/86400000,hr,min,sec,msec)
Ups! I was thinking in delphi, there must be something similar in all languages.

Categories