I have a large number in seconds that I'm looking to convert into a result for example;
But that value is stored in seconds 1728000.
This is my current code but nothing is returned. As you can see I'm trying to make it as Human-Like as possible.
function convert_seconds($seconds)
{
if ($seconds <= 60){
return "nill";
} else if ($seconds >= 60 || $seconds <= 3600){ # hr
$time = ($seconds) / 3600;
$time_val = "Hour";
} else if ($seconds >= 3600 || $seconds <= 86400){ # day
$time = 0;
$time = ($seconds) / 86400;
$time_val = "Day";
} else if ($seconds >= 86400 || $seconds <= 604800){ # week
$time = 0;
$time = ($seconds) / 604800;
$time_val = "Week";
}
if ($time_val == "Hour" || $time <= 120){
$time_val == "Hours";
} else if ($time_val == "Day" || $time <= 7200){
$time_val == "Days";
} else if ($time_val == "Week" || $time <= 172800){
$time_val == "Weeks";
}
return $time.' '.$time_val;
}
echo convert_seconds(1728000);
The code isn't presise enough, for example 60 seconds will return 0.0169444444444 Hours?? If anyone knows a better way I would love to hear.
You need to use a return statement. You also should use a single "=" to assign a variable.
function convert_seconds($seconds)
{
if ($seconds <= 60){
return "nill";
} else if ($seconds >= 60 || $seconds <= 3600){ # hr
$time = ($seconds) / 3600;
$time_val = "Hour";
} else if ($seconds >= 3600 || $seconds <= 86400){ # day
$time = 0;
$time = ($seconds) / 86400;
$time_val = "Day";
} else if ($seconds >= 86400 || $seconds <= 604800){ # week
$time = 0;
$time = ($seconds) / 604800;
$time_val = "Week";
}
if ($time_val == "Hour" || $time <= 120){
$time_val = "Hours";
} else if ($time_val == "Day" || $time <= 7200){
$time_val = "Days";
} else if ($time_val == "Week" || $time <= 172800){
$time_val = "Weeks";
}
return $time.' '.$time_val;
}
There are a few problems with your code. Firstly you need to use &&, not || in the conditions, otherwise your second condition is always true. Also, your conditions are such that $time will always be 0 or 1 since you are dividing by the biggest value it can be for that condition. Try this instead:
function convert_seconds($seconds) {
if ($seconds < 60){
return "nill\n";
}
else if ($seconds >= 60 && $seconds < 3600){ # hr
$time = floor($seconds / 60);
$time_val = "Minute";
}
else if ($seconds >= 3600 && $seconds < 86400){ # day
$time = floor($seconds / 3600);
$time_val = "Hour";
}
else if ($seconds >= 86400 && $seconds < 604800){ # week
$time = floor($seconds / 86400);
$time_val = "Day";
}
else if ($seconds >= 604800) {
$time = floor($seconds / 604800);
$time_val = "Week";
}
if ($time > 1) $time_val .= 's';
return "$time $time_val\n";
}
echo convert_seconds(40);
echo convert_seconds(530);
echo convert_seconds(35930);
echo convert_seconds(240000);
echo convert_seconds(2345775);
Output:
nill
8 Minutes
9 Hours
2 Days
3 Weeks
I've assumed you want integer output, if you want decimal (e.g. 8.25 Hours), you can change the floor to an appropriate round e.g. $time = round($seconds / 60, 2);
Demo on 3v4l.org
Related
I have a simple script that will dynamically convert minutes into minutes, hours and days dynamically( Meaning if I have 1 minute, the script will put put "1 Minute", and if I have 61 mins, the script will say "1 Hour and 1 Minute" etc. with the proper grammar). Basically, although I try to set the value of a variable as an int, my current time (112 mins) comes out as: 1.8666666666667 Hours and 52 Minutes.
settype($otime, "integer");
settype($hours, "integer");
settype($mins, "integer");
settype($hour, "integer");
if($otime == 1) {
$otime = "1 Minute";
}else if($otime < 60 && $otime !=1) {
$otime = $otime." Minutes";
}
else if($otime >= 60 && $otime < 1440) {
$hours = $otime / 60;
$mins = $otime % 60;
if($mins == 1 && $hours != 1) {
$otime = $hours." Hours and ".$mins." Minute";
}
else if($mins != 1 && $hours == 1) {
$otime = $hours." Hour and ".$mins." Minutes";
}
else if($mins == 1 && $hours == 1) {
$otime = $hours." Hour and ".$mins." Minute";
}
else {
$otime = $hours." Hours and ".$mins." Minutes";
}
}
else if($otime >= 1440) {
$days = $otime / 1440;
$hour = $otime % 1440;
$hours = $hour / 60;
$mins = $hour % 60;
if($days == 1 && $hours != 1 && $mins != 1) {
$otime = $days." Day ".$hours." Hours and ".$mins." Minutes";
}
if($days != 1 && $hours == 1 && $mins != 1) {
$otime = $days." Days ".$hours." Hour and ".$mins." Minutes";
}
if($days != 1 && $hours != 1 && $mins == 1) {
$otime = $days." Days ".$hours." Hours and ".$mins." Minute";
}
if($days == 1 && $hours == 1 && $mins != 1) {
$otime = $days." Day ".$hours." Hour and ".$mins." Minutes";
}
if($days == 1 && $hours == 1 && $mins == 1) {
$otime = $days." Day ".$hours." Hour and ".$mins." Minute";
}
if($days != 1 && $hours == 1 && $mins == 1) {
$otime = $days." Days ".$hours." Hour and ".$mins." Minute";
}
if($days == 1 && $hours != 1 && $mins == 1) {
$otime = $days." Day ".$hours." Hours and ".$mins." Minute";
}
if($days != 1 && $hours != 1 && $mins != 1) {
$otime = $days." Days ".$hours." Hours and ".$mins." Minutes";
}
}
Also - Is there a simpler way to do this? and did I miss any if's (For grammar purposes)
Try something like this :
echo gmdate("H:i:s", ($minutes * 60));
Or with a function DateTime() :(Thanks to #Ryan Kempt)
function minutesToTime($minutes) {
$minutes = $minutes * 60;
$dtF = new DateTime("#0");
$dtT = new DateTime("#$minutes");
if($dtF->diff($dtT)->format('%i') !=0 ){
$min = ($dtF->diff($dtT)->format('%i') == 1 ? ' %i Minute' : ' %i Minutes');
}
else{
$min = '';
}
if($dtF->diff($dtT)->format('%h') !=0 ){
$hours = ($dtF->diff($dtT)->format('%h') == 1 ? ' %h Hour' : ' %h Hours');
}
else{
$hours = '';
}
if($dtF->diff($dtT)->format('%a') !=0 ){
$days = ($dtF->diff($dtT)->format('%a') == 1 ? ' %a Day' : ' %a Days');
}
else{
$days = '';
}
if($dtF->diff($dtT)->format('%s') !=0 ){
$seconds = ($dtF->diff($dtT)->format('%s') == 1 ? ' %s Second' : ' %s Seconds');
}
else{
$seconds = '';
}
return $dtF->diff($dtT)->format($days.' '.$hours.' '.$min.' '.$seconds.'');
}
echo minutesToTime(456543.5);
OUTPUT
1317 Days, 1 Hour, 3 Minutes and 30 Seconds
There is a much simpler way of doing this without so many if statements but also providing the correct plural language.
echo minutes2human(1211);
function minutes2human($mins) {
$m = floor($mins % 60);
$h = floor(($mins % 1440) / 60);
$d = floor($mins / 1440);
$m_word = ($m == 1 ? 'Minute' : 'Minutes');
$h_word = ($h == 1 ? 'Hour' : 'Hours');
$d_word = ($d == 1 ? 'Day' : 'Days');
return "$d $d_word $h $h_word and $m $m_word";
}
We reduce a lot of your if statements by checking if minutes are 1, hours are 1, and if days are 1, then just combining them all into one string. As opposed to checking each possible case (if minutes are 1 and hours are not 1 and days are not 1, if minutes are 1, hours are 1, and days are not 1) etc...
Your problem is that you are setting the type for the variables before than the variables have value.
For the $hours, set the type after the division. Replace the line
$hours = $otime / 60;
for:
$hours = $otime / 60;
settype($hours, "integer");
It's probably that you will need to do this with the other variables $mins and $hour
I have a MySql datetime value like "2012-04-17 20:48:29". I want to convert this to a simple text like "10 days ago". I want to do this in either php or javascript! I tried to create my own algorithm to do this. But is there an already available solution for doing this?
you could use this pattern
$date = "2012-04-17 20:48:29";
$seconds = time() - strtotime($date);
$days = floor($seconds / 86400);
$seconds -= $days * 86400;
$hours = floor($seconds / 3600);
$seconds -= $hours * 3600;
$minutes = floor($seconds / 60);
$seconds -= $minutes * 60;
echo "$days days, $hours hours, $minutes minutes, $seconds seconds ago";
you should of course add some conditions before echoing the result. to only show 1 minute ago, or 3 hours ago, or 10 days ago...
With this function you'll get outputs like:
1 minute
5 minutes
15 hours
4 days
2 months
1.5 years
function time_ago_in_words($time) {
$from_time = strtotime($time);
$to_time = strtotime(gmd());
$distance_in_minutes = round((($to_time - $from_time))/60);
if ($distance_in_minutes < 0)
return (string)$distance_in_minutes.'E';
if (between($distance_in_minutes, 0, 1))
return '1 minute';
elseif (between($distance_in_minutes, 2, 44))
return $distance_in_minutes.' minutes';
elseif (between($distance_in_minutes, 45, 89))
return '1 hour';
elseif (between($distance_in_minutes, 90, 1439))
return round($distance_in_minutes/60).' hours';
elseif (between($distance_in_minutes, 1440, 2879))
return '1 day';
elseif (between($distance_in_minutes, 2880, 43199))
return round($distance_in_minutes/1440).' days';
elseif (between($distance_in_minutes, 43200, 86399))
return '1 month';
elseif (between($distance_in_minutes, 86400, 525959))
return round($distance_in_minutes/43200).' months';
elseif ($distance_in_minutes > 525959)
return number_format(round(($distance_in_minutes/525960), 1), 1).' years';
}
So you could do:
// Last time you logged in: 15 days ago.
Last time you logged in: <?php echo time_ago_in_words($user['last_logged_in']) ?> ago.
// We haven't seen you for 15 days!
We haven't seen you for <?php echo time_ago_in_words($user['last_logged_in']) ?>!
With PHP, you can call strftime to get different out put. Look here for more details.
There is also a jQuery plugin that you might look at as well: jQuery-dateFormat
Have fun!
I use this function:
function duration($integer)
{
$seconds=$integer;
$minutes = 0;
$hours = 0;
$days = 0;
$weeks = 0;
$return = "";
if ($seconds/60 >=1)
{
$minutes=floor($seconds/60);
if ($minutes/60 >= 1)
{ # Hours
$hours=floor($minutes/60);
if ($hours/24 >= 1)
{ #days
$days=floor($hours/24);
if ($days/7 >=1)
{ #weeks
$weeks=floor($days/7);
if ($weeks>=2) $return="$weeks Weeks";
else $return="$weeks Week";
} #end of weeks
$days=$days-(floor($days/7))*7;
if ($weeks>=1 && $days >=1) $return="$return, ";
if ($days >=2) $return="$return $days days";
if ($days ==1) $return="$return $days day";
} #end of days
$hours=$hours-(floor($hours/24))*24;
if ($days>=1 && $hours >=1) $return="$return, ";
if ($hours >=2) $return="$return $hours hours";
if ($hours ==1) $return="$return $hours hour";
} #end of Hours
$minutes=$minutes-(floor($minutes/60))*60;
if ($hours>=1 && $minutes >=1) $return="$return, ";
if ($minutes >=2) $return="$return $minutes minutes";
if ($minutes ==1) $return="$return $minutes minute";
} #end of minutes
$seconds=$integer-(floor($integer/60))*60;
if ($minutes>=1 && $seconds >=1) $return="$return, ";
if ($seconds >=2) $return="$return $seconds seconds";
if ($seconds ==1) $return="$return $seconds second";
$return="$return.";
return $return;
}
echo duration(time() - strtotime($date));
Sorry for the slightly misleading title, I'm not really sure how to word this.
Basically, I'm working on a time clock-in system.
I've got the data for each clock in: clock in timestamp and clock out timestamp.
After all of the clockins have been displayed in a specific period, the script adds up all of the differences between the two timestamps.
The one thing I need to do now, is actually convert this figure into hours and minutes.
Use this function from more detailed output
function datefor($date, $time)
{
$days = floor($time / (60 * 60 * 24));
$remainder = $time % (60 * 60 * 24);
$hours = floor($remainder / (60 * 60));
$remainder = $remainder % (60 * 60);
$minutes = floor($remainder / 60);
$seconds = $remainder % 60;
if($days > 0) {
$data = date('F d Y', $date);
reset($date);
}
elseif($days == 0 && $hours == 0 && $minutes == 0) {
$data = "few seconds ago";
}
elseif($days == 0 && $hours == 0) {
$data = $minutes.' minutes ago';
}
elseif($days == 0 && $hours > 0) {
$data = $hours.' hour ago';
}
else {
$data = "few seconds ago";
}
return $data;
}
and select using the following statement
SELECT *,UNIX_TIMESTAMP() - datetime AS TimeSpent FROM `table_name`;
$result=mysql_query($sql);
while($rows=mysql_fetch_array($result)){
//call function
$check = datefor($rows['datetime'], $rows['TimeSpent']);}
now echo $check; where you want the time to be displayed.
<strong>So far, you have worked <?php
$hours = floor($i / 3600);
$i -= 3600 * floor($i / 3600);
$minutes = floor($i / 60);
echo $hours; ?> hours and <?php echo $minutes; ?> minutes</strong>
yep, it works.
Outputting from a directions api I have a duration it will take the user to get from a to b. At the moment it is minutes but if the users journey will take 3 hours and 20 minutes it will output 200 minutes.
I would like it to work out that that is greater than 60 minutes. then divide by 60 and add the remainder to give
3 hours 20 minutes.
How do we do this.
Marvellous
with php >= 5.3.0 you could do that :
$dt = new DateTime();
$dt->add(new DateInterval('PT200M'));
$interval = $dt->diff(new DateTime());
echo $interval->format('%Hh %Im %Ss');
Output (on my locale) : 02h 40m 00s
source : http://php.net/manual/en/class.dateinterval.php
function getNiceDuration($durationInSeconds) {
$duration = '';
$days = floor($durationInSeconds / 86400);
$durationInSeconds -= $days * 86400;
$hours = floor($durationInSeconds / 3600);
$durationInSeconds -= $hours * 3600;
$minutes = floor($durationInSeconds / 60);
$seconds = $durationInSeconds - $minutes * 60;
if($days > 0) {
$duration .= $days . ' days';
}
if($hours > 0) {
$duration .= ' ' . $hours . ' hours';
}
if($minutes > 0) {
$duration .= ' ' . $minutes . ' minutes';
}
if($seconds > 0) {
$duration .= ' ' . $seconds . ' seconds';
}
return $duration;
}
In case you have duration in seconds, you can format it with PHP gmdate() function:
echo gmdate("H:i:s", $seconds);
(Note: works for durations up to 24 hours)
$minutes = 200;
if ($minutes >= 60)
{
$hours = (int)($minutes / 60);
$minutes = $minutes % 60;
}
<?php
$time = 200; // minutes
if ($time > 60) {
$minutes = $time % 60;
$hours = ($time - $minutes) / 60;
}
echo "$hours hours $minutes minutes";
?>
Use modulo division :)
function format_minutes($value)
{
$hours = intval($value / 60);
$minutes = $value % 60;
if ($hours != 0) {
$str = $hours . ' hour';
// Handle pluralisation.
if (abs($hours) != 1) {
$str .= 's';
}
}
// Always show minutes if there are no hours.
if ($minutes != 0 || $hours == 0) {
$str .= ' ' . $minutes . ' minute';
// Handle pluralisation.
if (abs($minutes) != 1) {
$str .= 's';
}
}
// There will be a leading space if hours is zero.
return trim($str);
}
Thanks for the function. I needed to change it to make it work better:
The minutes were over 60:
$seconds = $secs % 60;
$hours = floor($secs / 3600);
$secs = $secs - $hours*3600;
$minutes = floor($secs / 60);
Best
For those who need it... Minutes to Period of Time - PT:
<?php
function pttime($time, $format)
{
if ($time < 1) {
return;
}
$hours = floor($time / 60);
$minutes = ($time % 60);
//is PT
if ($format == 'PT') {
//full hour
if (($hours > 0) && ($minutes == 0)) {
$time_result = 'PT' . $hours . 'H';
}
//hour and minutes
if (($hours > 0) && ($minutes <> 0)) {
$time_result = 'PT' . $hours . 'H' . $minutes . 'M';
}
//just minutes
if ($hours == 0) {
$time_result = 'PT' . $minutes . 'M';
}
}
//it's not PT
else {
$time_result = sprintf("%02s", $hours) . ':' . sprintf("%02s", $minutes);
}
return $time_result;
}
//input in minutes and its outputs
echo pttime(155,'PT'); //output -> PT2H35M
echo pttime(52,'PT'); //output -> PT52M
echo pttime(60,'PT'); //output -> PT1H
echo pttime(60,''); //output -> 01:00
A simple duration-to-formatted-time example (with the duration given in seconds, and the output formatted as [##:]##:##):
public function format_duration($secs, $delimiter = ':')
{
$seconds = $secs % 60;
$minutes = floor($secs / 60);
$hours = floor($secs / 3600);
$seconds = str_pad($seconds, 2, "0", STR_PAD_LEFT);
$minutes = str_pad($minutes, 2, "0", STR_PAD_LEFT).$delimiter;
$hours = ($hours > 0) ? str_pad($hours, 2, "0", STR_PAD_LEFT).$delimiter : '';
return "$hours$minutes$seconds";
}
If my code looks like:
if($seconds < 60)
$interval = "$seconds seconds ago";
else
if($seconds < 3600)
$interval = floor($seconds / 60) . "minutes ago";
else
if($seconds < 86400)
$interval = floor($seconds / 3600) . "hours ago";
else
$interval = floor($seconds / 86400) . "days ago";
How would I get rid of it saying stuff like:
1 Days ago.
1 Years ago.
1 Minutes ago.
1 Hours ago.
Thanks :)
If your app is international and using the gettext extension, you can do something like this:
sprintf(ngettext('%d minute', '%d minutes', $amount), $amount);
You can create a wrapper function to it:
function pluralize($singular, $plural, $num) {
return sprintf(ngettext($singular, $plural, $num), $num);
}
This is the best way imo.
Can be done quite concisely with a ternary operator:
if($seconds < 60) {
$interval = "$seconds second" . (($seconds != 1) ? "s" : "") . " ago";
} else {
if($seconds < 3600) {
$minutes = floor($seconds / 60);
$interval = "$minutes minute" . (($minutes > 1) ? "s" : "") . " ago";
} else {
if($seconds < 86400) {
$hours = floor($seconds / 3600);
$interval = "$hours hour" . (($hours > 1) ? "s" : "") . " ago";
} else {
$days = floor($seconds / 86400);
$interval = "$days day" . (($days > 1) ? "s" : "") . " ago";
}
}
}
Yet another solution.
if($seconds < 60)
$interval = "$seconds second";
else
if($seconds < 3600)
$interval = floor($seconds / 60) . " minute";
else
if($seconds < 86400)
$interval = floor($seconds / 3600) . " hour";
else
$interval = floor($seconds / 86400) . " day";
$interval .= (reset(explode(" ", $interval)) != 1 ? "s" : "")." ago";
$time = "120";
$array = array("second" => 1,
"minute" => 60,
"hour" => 60,
"day" => 24,
"year" => 365);
$old_time = 0;
$old_type = false;
// Loop through each type
foreach($array as $type => $seconds)
{
// Divide
$time = floor($time/$seconds);
// If it went into a value lower than 0, stop dividing
if($time < 1)
{
$time = $old_time;
$type = $old_type;
break;
}
else
{
// Continue dividing.
$old_time = $time;
$old_type = $type;
}
}
if($time == 1)
{
$interval = $time . " ". $type . " ago";
}
else
{
$interval = $time ." " . $type . "s ago";
}
echo $interval;
This divides through all the possible time types, and gives one that doesn't turn it into a fraction. By separating the number value from the type, we are then able to test if the number is == 1, and correct the word.
if ($interval < 60) {
$unit = 'Second';
} else if ($interval < 1440) {
$unit = 'Minute'; $interval /= 60;
} else if ($interval < 86400) {
$unit = 'Hour'; $interval /= 1440;
} else {
$unit = 'Day'; $interval /= 86400;
}
$interval = intval($interval);
$interval = "$interval $unit" . ($interval == 1 ? '' : 's') . " ago";
Here is a generic PHP snip for getting strings like "1 month, 2 weeks and 30 seconds ago".
$timeUnits = array("month" => 2592000,
"week" => 604800,
"day" => 86400,
"hour" => 3600,
"minute" => 60,
"second" => 1);
$tmpSeconds = $seconds;
$timeAgoStrings = array();
foreach ($timeUnits as $name => $numOfSeconds) {
if ($seconds > $numOfSeconds) {
$val = floor($tmpSeconds / $numOfSeconds);
$agoStr = ($val > 1) ? $name."s" : $name;
$timeAgoStrings[] = "$val $agoStr";
$tmpSeconds = $tmpSeconds - $val; // cut the used time units off our tmpSeconds variable
}
}
//check if we have more than one string - in case we do then we will pop the last val and add an "and" prefix before the last val instead of a comma
if (count($timeAgoStrings) > 1) {
$lastString = array_pop($timeAgoStrings);
$timeAgoStr = implode(", ",$timeAgoStrings)." and $lastString ago";
} else {
$timeAgoStr = $timeAgoStrings[0]." ago";
}
Do the math.
else if($seconds < 120)
$interval = "1 minute ago";
else if($seconds < 172800)
$interval = "1 day ago"
etc.