I'm trying to make a correct sum() of hh:mm:ss type of data, and i'm trying to understand why it has this behaviour when the minutes or seconds are getting >= 100. And how can i fix it?
correct:
incorrect:
This is the sum() function i took from Datatables forum:
jQuery.fn.dataTable.Api.register('sum()', function () {
return this.flatten().reduce(function (a, b) {
if (typeof a === 'string') {
a = a.replace(/[^\d.-]/g, '') * 1;
}
if (typeof b === 'string') {
b = b.replace(/[^\d.-]/g, '') * 1;
}
return a + b;
}, 0);
});
And this is the rest of the code full of conversions, and making my head spin.
var tempoPage = tempo.column(3, { page: 'current' })
.data()
.sum();
tempoPage = tempoPage.toString();
while (tempoPage.length < 6) {
tempoPage = "0" + tempoPage
}
tempoPage = tempoPage.replace(/^(\d+)(\d{2})(\d{2})$/, function (m, m1, m2, m3) {
m1 = Number(m1);
m2 = Number(m2);
m2 += parseInt(m3 / 60, 10);
m3 = m3 % 60; // get soconds
m1 += parseInt(m2 / 60, 10); //get hours
m2 = m2 % 60; // get minutes
//convert back to string
m2 = m2.toString();
m3 = m3.toString();
m1 = m1.toString();
while (m1.length < 2){
m1 = '0' + m1
}
while (m2.length < 2){
m2 = '0' + m2
}
while (m3.length < 2){
m3 = '0' + m3
}
return m1 + ':' + m2.slice(-2) + ':' + m3.slice(-2);
})
//write in footer
$(tempo.column(3)
.footer()).html(tempoPage);
},
Does any one see a better way to do this or can point me on the right track?
Thank you.
I cannot say what is wrong with the code. It seems really complicated, the only thing we need to do is to sum 3 values, and add for example 1 minute when seconds increases 60. Have made this less complicated sumHours() plugin, it seems to do the job (but have not tested in depth) :
jQuery.fn.dataTable.Api.register( 'sumHours()', function ( ) {
function pad(int) {
return int > 9 ? int.toString() : '0' + int.toString()
}
var t, hours = 0, mins = 0, secs = 0;
for (var i=0; i<this.length; i++) {
t = this[i].split(':')
hours += parseInt(t[0])
mins += parseInt(t[1])
if (mins >= 60) {
mins -= 60
hours += 1
}
secs += parseInt(t[2])
if (secs >= 60) {
secs -= 60
mins += 1
}
}
return pad(hours) + ':' + pad(mins) + ':' + pad(secs)
})
You can use this the same way as the as the official sum() example you hve linked to :
api.column( 0, {page:'current'} ).data().sumHours()
demo -> http://jsfiddle.net/vbuyjm9s/
Related
Im trying to write a function that takes my decimal degrees (lat or long) and converts them to DMS degrees minutes seconds. I know I am meant to times the decimal point number by 60 then it's decimal again. But am a noob. Would I split the number?
function ConvertDDToDMS(DD) {
eg. DD =-42.4
D= 42;
M= 4*60;
S= .M * 60;
var DMS =
return DMS //append Direction (N, S, E, W);
}
Am I on the right track?
function ConvertDDToDMS(D, lng) {
return {
dir: D < 0 ? (lng ? "W" : "S") : lng ? "E" : "N",
deg: 0 | (D < 0 ? (D = -D) : D),
min: 0 | (((D += 1e-9) % 1) * 60),
sec: (0 | (((D * 60) % 1) * 6000)) / 100,
};
}
The above gives you an object {deg, min, sec, dir} with sec truncated to two digits (e.g. 3.14) and dir being one of N, E, S, W depending on whether you set the lng (longitude) parameter to true. e.g.:
ConvertDDToDMS(-18.213, true) == {
deg : 18,
min : 12,
sec : 46.79,
dir : 'W'
}
Or if you just want the basic string:
function ConvertDDToDMS(D){
return [0|D, 'd ', 0|(D=(D<0?-D:D)+1e-4)%1*60, "' ", 0|D*60%1*60, '"'].join('');
}
ConvertDDToDMS(-18.213) == `-18d 12' 47"`
[edit June 2019] -- fixing an 8 year old bug that would sometimes cause the result to be 1 minute off due to floating point math when converting an exact minute, e.g. ConvertDDToDMS(4 + 20/60).
[edit Dec 2021] -- Whoops. Fix #2. Went back to the original code and added 1e-9 to the value which a) bumps any slightly low floating point errors to the next highest number and b) is less than .01 sec, so has no effect on the output. Added 1e-4 to the "string" version which is the same fix, but also rounds seconds (it's close to 1/2 sec).
It's not clear how you need the output. Here's a version that returns all 3 values as a string:
function ConvertDDToDMS(dd)
{
var deg = dd | 0; // truncate dd to get degrees
var frac = Math.abs(dd - deg); // get fractional part
var min = (frac * 60) | 0; // multiply fraction by 60 and truncate
var sec = frac * 3600 - min * 60;
return deg + "d " + min + "' " + sec + "\"";
}
Update: I remove the part that did not make any sense (thanks cwolves!).
Here you have yet another implementation. It won't be as short nor efficient as the previous ones, but hopefully much easier to understand.
To get it right, first you need to understand how the calculations are done and only then attempt to implement them. For that, pseudocode is a great option, since you write down the steps in plain English or a simplified syntax that is easy to understand, and then translate it onto the programming language of choice.
I hope it's useful!
/* This is the pseudocode you need to follow:
* It's a modified version from
* http://en.wikipedia.org/wiki/Geographic_coordinate_conversion#Conversion_from_Decimal_Degree_to_DMS
function deg_to_dms ( degfloat )
Compute degrees, minutes and seconds:
deg ← integerpart ( degfloat )
minfloat ← 60 * ( degfloat - deg )
min ← integerpart ( minfloat )
secfloat ← 60 * ( minfloat - min )
Round seconds to desired accuracy:
secfloat ← round( secfloat, digits )
After rounding, the seconds might become 60. These two
if-tests are not necessary if no rounding is done.
if secfloat = 60
min ← min + 1
secfloat ← 0
end if
if min = 60
deg ← deg + 1
min ← 0
end if
Return output:
return ( deg, min, secfloat )
end function
*/
function deg_to_dms (deg) {
var d = Math.floor (deg);
var minfloat = (deg-d)*60;
var m = Math.floor(minfloat);
var secfloat = (minfloat-m)*60;
var s = Math.round(secfloat);
// After rounding, the seconds might become 60. These two
// if-tests are not necessary if no rounding is done.
if (s==60) {
m++;
s=0;
}
if (m==60) {
d++;
m=0;
}
return ("" + d + ":" + m + ":" + s);
}
Try this working perfect!!!
function truncate(n) {
return n > 0 ? Math.floor(n) : Math.ceil(n);
}
function getDMS(dd, longOrLat) {
let hemisphere = /^[WE]|(?:lon)/i.test(longOrLat)
? dd < 0
? "W"
: "E"
: dd < 0
? "S"
: "N";
const absDD = Math.abs(dd);
const degrees = truncate(absDD);
const minutes = truncate((absDD - degrees) * 60);
const seconds = ((absDD - degrees - minutes / 60) * Math.pow(60, 2)).toFixed(2);
let dmsArray = [degrees, minutes, seconds, hemisphere];
return `${dmsArray[0]}°${dmsArray[1]}'${dmsArray[2]}" ${dmsArray[3]}`;
}
var lat = 13.041107;
var lon = 80.233232;
var latDMS = getDMS(lat, 'lat');
var lonDMS = getDMS(lon, 'long');
console.log('latDMS: '+ latDMS);
console.log('lonDMS: '+ lonDMS);
Output:
latDMS: 13°2'27.99" N
lonDMS: 80°13'59.64" E
A solution with the option for specifying the decimal places in output seconds and correction of any edge cases due to rounding seconds and minutes.
// # input {deg} Numeric; degrees number to convert
// # input {dplaces} Decimal places to use for output seconds
// Default 0 places
// # return {DMS} string degrees (°) minutes (') seconds (")
//
function degToDMS (deg, dplaces=0) {
var d = Math.floor (deg); // make degrees
var m = Math.floor((deg-d)*60); // make minutes
var s = Math.round(((deg-d)*60-m)*60*Math.pow(10,dplaces))/Math.pow(10,dplaces); // Make sec rounded
s == 60 && (m++, s=0 ); // if seconds rounds to 60 then increment minutes, reset seconds
m == 60 && (d++, m=0 ); // if minutes rounds to 60 then increment degress, reset minutes
return (d + "° " + m + "' " + s+'"'); // create output DMS string
}
// ----- tests ------
console.log(degToDMS(55.23456)); // 55° 14' 4"
console.log(degToDMS(55.23456 ,3)); // 55° 14' 4.416"
console.log(degToDMS(4 + 20/60 ,2)); // 4° 20' 0"
console.log(degToDMS(89.64789 ,2)); // 89° 38' 52.4"
console.log(degToDMS(-23.1234567,3)); // -24° 52' 35.556"
This one works %100 in TypeScript:
ConvertDDToDMS(deg: number, lng: boolean): string {
var d = parseInt(deg.toString());
var minfloat = Math.abs((deg - d) * 60);
var m = Math.floor(minfloat);
var secfloat = (minfloat - m) * 60;
var s = Math.round((secfloat + Number.EPSILON) * 100) / 100
d = Math.abs(d);
if (s == 60) {
m++;
s = 0;
}
if (m == 60) {
d++;
m = 0;
}
let dms = {
dir: deg < 0 ? lng ? 'W' : 'S' : lng ? 'E' : 'N',
deg: d,
min: m,
sec: s
};
return `${dms.deg}\u00B0 ${dms.min}' ${dms.sec}" ${dms.dir}`
}
private static DecimalFormat DecimalFormat = new DecimalFormat(".##");
public static void main(String[] args){
double decimal_degrees = 22.4229541515;
System.out.println(getDMS(decimal_degrees));
}
public static String getDMS(double decimal_degrees) {
double degree = Math.floor(decimal_degrees);
double minutes = ((decimal_degrees - Math.floor(decimal_degrees)) * 60.0);
double seconds = (minutes - Math.floor(minutes)) * 60.0;
return ((int)degree)+":"+((int)minutes)+":"+decimalFormat.format(seconds);
}
INPUT : 22.4229541515 OUTPUT: 22:25:22.63
Based on above answer, i've written them into javascript and php style.
JS-
function convertDDToDMS(deg, lng){
var d = parseInt(deg);
var minfloat = Math.abs((deg-d) * 60);
var m = Math.floor(minfloat);
var secfloat = (minfloat-m)*60;
var s = Math.round(secfloat);
d = Math.abs(d);
if (s==60) {
m++;
s=0;
}
if (m==60) {
d++;
m=0;
}
return {
dir : deg<0?lng?'W':'S':lng?'E':'N',
deg : d,
min : m,
sec : s
};
}
PHP-
function convertDDtoDMS($deg, $lng){
$dd = intval($deg);
$minfloat = abs(($deg - $dd) * 60);
$mm = floor($minfloat);
$secfloat = ($minfloat - $mm) * 60;
$ss = round($secfloat);
$dd = abs($dd);
if($ss == 60){
$mm++;
$ss = 0;
}
if($mm == 60){
$dd++;
$mm = 0;
}
$dd = array(
'dir' => $deg < 0 ? ($lng ? 'W' : 'S') : ($lng ? 'E' : 'N'),
'deg' => abs($dd),
'min' => $mm,
'sec' => $ss,
);
return $dd;
}
couldnt get the script above working, after some time came up with this;
just give the dms to the script
function ConvertDMSToDEG(dms) {
var dms_Array = dms.split(/[^\d\w\.]+/);
var degrees = dms_Array[0];
var minutes = dms_Array[1];
var seconds = dms_Array[2];
var direction = dms_Array[3];
var deg = (Number(degrees) + Number(minutes)/60 + Number(seconds)/3600).toFixed(6);
if (direction == "S" || direction == "W") {
deg = deg * -1;
} // Don't do anything for N or E
return deg;
}
and visa versa just give the degrees to the script, and true of false for lat (latitude)
function ConvertDEGToDMS(deg, lat) {
var absolute = Math.abs(deg);
var degrees = Math.floor(absolute);
var minutesNotTruncated = (absolute - degrees) * 60;
var minutes = Math.floor(minutesNotTruncated);
var seconds = ((minutesNotTruncated - minutes) * 60).toFixed(2);
if (lat) {
var direction = deg >= 0 ? "N" : "S";
} else {
var direction = deg >= 0 ? "E" : "W";
}
return degrees + "°" + minutes + "'" + seconds + "\"" + direction;
}
hope this helps people..
I'm surprised all solutions are using some additional logic to handle the "rounds to 60" cases (if they're aware of it at all), but nobody thought of doing it the other way round, starting with (rounded) seconds and then using mod and int-div and not have to worry about all that:
function coordToStr(coord)
{
let seconds = Math.round(Math.abs(coord) * 3600)
let sec = Math.floor(seconds % 60)
let minutes = Math.floor(seconds / 60)
let min = minutes % 60
let deg = Math.floor(minutes / 60)
return deg + "°" + ((min < 10) ? "0" : "") + min + "'" + ((sec < 10) ? "0" : "") + sec
}
Sorry, this is without the N/S, E/W part, would need some additional method calling it.
If you want second-fractions, you could use this:
function coordToStrWithDecimals(coord)
{
let centiSecs = Math.round(Math.abs(coord) * 360000)
let frac = Math.floor(centiSecs % 100)
let seconds = Math.floor(centiSecs / 100)
let sec = Math.floor(seconds % 60)
let minutes = Math.floor(seconds / 60)
let min = minutes % 60
let deg = Math.floor(minutes / 60)
return deg + "°" + ((min < 10) ? "0" : "") + min + "'" + ((sec < 10) ? "0" : "") + sec + "." + ((frac < 10) ? "0" : "") + frac + '"'
}
just for remark, the answer
function ConvertDDToDMS(D){
return [0|D, 'd ', 0|(D<0?D=-D:D)%1*60, "' ", 0|D*60%1*60, '"'].join('');
}
does not work for angles between -1° and 0°.
Bad luck!
hc
Trying to get it to change between 16:30:00 and 17:30:00, to change the text font colour
Tried nested if statements as well
function startTime() {
var today = new Date();
var h = today.getHours();
var m = today.getMinutes();
var s = today.getSeconds();
m = checkTime(m);
s = checkTime(s);
document.getElementById('txt').innerHTML =
h + ":" + m + ":" + s;
var t = setTimeout(startTime, 500);
if ((h>=16 && m >=30) && (h<=17 && m<=30))
{
document.getElementById("txt").style.color = "red";
}
else
{
document.getElementById("txt").style.color = "black";
}
}
function checkTime(i) {
if (i < 10) {i = "0" + i}; // add zero in front of numbers < 10
return i;
}
try to use setInterval() it's look more clear:
function startTime() {
var today = new Date();
var h = today.getHours();
var m = today.getMinutes();
if((h==16 && m>=30) || (h==17 && m<=30)){
document.getElementById("txt").style.color = "red";
}
else
{
document.getElementById("txt").style.color = "black";
}
};
setInterval(startTime, 500);
The main bug in your logic is looking for minutes where it is both less than and equal to 30 AND greater than and equal to 30. The only way that part evaluates to true is if minutes is 30.
I would normalize the time (so that each combination of hour, minute and second can be represented by a unique number) and use that for comparisons.
function startTime(el) {
var today = new Date();
var hour = today.getHours(),
minute = today.getMinutes(),
second = today.getSeconds();
var normalized_time = normalizeTime(hour, minute, second);
document.getElementById(el).innerHTML
= hour + ":" + padTime(minute) + ":" + padTime(second);
document.getElementById(el).style.color
= normalized_time >= normalizeTime(16, 30, 0)
&& normalized_time <= normalizeTime(17, 30, 0)
? 'red'
: 'black';
}
/*
* Add a 0 to the beginning of the number if one-digit number
*/
function padTime(i) {
return i < 10 ? '0' + i : i;
}
/*
* Converts the time to a normalized version
*/
function normalizeTime(h, m, s) {
return s + (60 * m) + (60 * 60 * h);
}
var t = setInterval(startTime, 500, 'txt');
<span id="txt"></span>
Edit: As per you question you want to take hour and minute into account for comparison, So i have not included the second's part.
The following function get an integer value against time , that later used for the comparison.
function getSeconds(hh,mm,ss)
{
return (Number(hh) * 60 * 60) + (Number(mm) * 60) + Number(ss);
}
Complete code :
function getSeconds(hh,mm,ss)
{
return (Number(hh) * 60 * 60) + (Number(mm) * 60) + Number(ss);
}
function startTime() {
var today = new Date();
var h = today.getHours();
var m = today.getMinutes();
var s = today.getSeconds();
m = checkTime(m);
s = checkTime(s);
document.getElementById('txt').innerHTML =
h + ":" + m + ":" + s;
var t = setTimeout(startTime, 500);
var timeNow = getSeconds(h,m,s);
//if ((h>=16 && m >=30) && (h<=17 && m<=30))
if (timeNow >= getSeconds(16,30,0) && timeNow <= getSeconds(17,30,00))
{
document.getElementById("txt").style.color = "red";
}
else
{
document.getElementById("txt").style.color = "black";
}
}
function checkTime(i) {
if (i < 10) {i = "0" + i}; // add zero in front of numbers < 10
return i;
}
startTime();
Updated Fiddle
Previous Response
Try the Fiddle
The problem with your code is you are comparing m with contradictory conditions.
I have concatenated the hour and minutes like following and used that for time comparison
var hrs = Number(h+'.'+m);
function startTime() {
var today = new Date();
var h = today.getHours();
var m = today.getMinutes();
var s = today.getSeconds();
m = checkTime(m);
s = checkTime(s);
document.getElementById('txt').innerHTML =
h + ":" + m + ":" + s;
var t = setTimeout(startTime, 500);
var hrs = Number(h+'.'+m);
//if ((h>=16 && m >=30) && (h<=17 && m<=30))
if (hrs >= 16.30 && hrs <= 17.30)
{
document.getElementById("txt").style.color = "red";
}
else
{
document.getElementById("txt").style.color = "black";
}
}
function checkTime(i) {
if (i < 10) {i = "0" + i}; // add zero in front of numbers < 10
return i;
}
startTime();
Hello i have a problem with this code. I have tried several ways but without a success to get zero before hours etc. Also I checked different topics but without a success.
var timestamp = (Date.now() + 1000 * 2 * 60 * 24 * 1) - Date.now();
timestamp /= 1000;
function component(x, v) {
return Math.floor(x / v);
}
/* last thing i tried but maybe it will help someone
Number.prototype.pad = function(size) {
var s = String(this);
while (s.length < (size || 2)) {s = "0" + s;}
return s;
};
*/
var $div = $('div');
setInterval(function () {
timestamp--;
var
hours = component(timestamp, 60 * 60),
minutes = component(timestamp, 60) % 60,
seconds = component(timestamp, 1) % 60;
$div.html(hours + ":" + minutes + ":" + seconds);
}, 1000);
DEMO : http://jsfiddle.net/5z7ahmze/1/
Thank you for your time.
You can check your variable and add a 0 before if needed :
var comp = component(timestamp, 60 * 60);
var hour = comp < 10 ? '0' + comp : comp;
You can create a function like this
function pad(number, length) {
var str = '' + number;
while (str.length < length) {
str = '0' + str;
}
return str;
}
and then
$div.html(pad(hours, 2) + ":" + pad(minutes, 2) + ":" + pad(seconds, 2));
Maybe that is what you want. Right?
EDIT
Ok, the final answer.
var interval = setInterval(function () {
timestamp--;
function addZero (number) {
var zeroedNumber = (number < 10) ? 0 + "" + number : number;
return zeroedNumber;
}
var
hours = addZero(component(timestamp, 60 * 60)),
minutes = addZero(component(timestamp, 60) % 60),
seconds = addZero(component(timestamp, 1) % 60);
$div.html(hours + ":" + minutes + ":" + seconds);
//Below, i helped you with a "stop count" handler. (:
if(hours == 0 & minutes == 0 & seconds == 1){
clearInterval(interval);
}
}, 1000);
Dinamically dding zeroes to your counter if (hour or minute or second) is < 10.
I think your code is working, if you call the pad function on the numbers:
$div.html(hours.pad() + ":" + minutes.pad() + ":" + seconds.pad());
Have been fighting this for too many days. I am trying to display the difference of a date (x) and now as follows:
If the diff is exactly a year or years - just display the year diff
If the diff is years and months (1 year, 5 months) display it like that
If the diff is months (no years), display the months diff
If it's days, display the days.
Hope that's clear - I'm very tired.
Here is my code (the commented lines are what I can't get to work):
function RelativeTime(x){
var plural = '';
var mins = 60, hour = mins * 60; day = hour * 24,
week = day * 7, month = week * 4, year = day * 365;
if (x >= year){ x = (x / year)|0; dformat="year"; }
//else
//if ((x >= year)&& (x >= month)) { x = (x / year), (x / month)|0 ; dformat="year" , "month"; }
else if (x >= month) { x = (x / month)|0; dformat="month"; }
else if (x >= day*4) { x = (x / day)|0; dformat="day"; }
else if (x >= hour) { x = (x / hour)|0; dformat="hr"; }
else if (x >= mins) { x = (x / mins)|0; dformat="min"; }
else { x |= 0; dformat="sec"; }
if (x > 1) plural = 's';
if (x < 0) x = 0;
return x + ' ' + dformat + plural;
}
Try, this http://jsfiddle.net/mk95J/5/:
var age = '';
function RelativeTime(x){
var ymwdhm = [ [31536000, 'year'],
[2419200, 'month'],
[604800, 'week'],
[86400, 'day'],
[3600, 'hour'],
[60, 'min'],
[1, 'sec'] ];
for(var i=0;i<7;i++) {
if(x >= ymwdhm[i][0]) {
var res = parseInt(x / ymwdhm[i][0], 10);
age += res;
age += ymwdhm[i][1];
age += res > 1 ? 's ' : ' '; // plural
RelativeTime(x - (res * ymwdhm[i][0]));
break;
}
}
}
RelativeTime( 35746121 );
document.write(age); // 1year 1month 2weeks 6days 17hours 28mins 41 secs
I would think you would want to construct your string as you go, since you want to build it up. The "else if" constructs would be good if you were only going to show the highest level of difference (only years, or only months).
Maybe something like this:
function RelativeTime(x) {
var mins = 60, hour = mins * 60; day = hour * 24,
week = day * 7, month = week * 4, year = day * 365;
var responseString = '';
if (x >= year) {
var numberOfYears = parseInt(x / year, 10);
x = x - (numberOfYears * year);
responseString += numberOfYears + ' year';
if (numberOfYears > 1) {
responseString += 's';
}
responseString += ' ';
}
if (x >= month) {
var numberOfMonths = parseInt(x / month, 10);
x = x - (numberOfMonths * month);
responseString += numberOfMonths + ' month';
if (numberOfMonths > 1) {
responseString += 's';
}
responseString += ' ';
}
return responseString;
}
// And so on ....
document.write(RelativeTime(35746121));
There are some efficiencies that could be managed within there as well (it's certainly looking like a function could come out of there to replace the almost duplicate code, and you could probably reuse some variables through there).
I basically want to produce the following:
from int 67 to 1 minute 7 seconds
from int 953 to 15 minutes 53 seconds
from int 3869 to 1 hour 4 minutes 29 seconds
pseudo code:
// original
<span class="time">67</span>
//output
<span class="time">1 minute 7 seconds</span>
// js
$('.time').format_duration();
Borrowing most of Guffa's answer, this should do the trick as a jQuery plugin:
jQuery.fn.time_from_seconds = function() {
return this.each(function() {
var t = parseInt($(this).text(), 10);
$(this).data('original', t);
var h = Math.floor(t / 3600);
t %= 3600;
var m = Math.floor(t / 60);
var s = Math.floor(t % 60);
$(this).text((h > 0 ? h + ' hour' + ((h > 1) ? 's ' : ' ') : '') +
(m > 0 ? m + ' minute' + ((m > 1) ? 's ' : ' ') : '') +
s + ' second' + ((s > 1) ? 's' : ''));
});
};
If you have HTML like this:
<span class='time'>67</span>
<span class='time'>953</span>
<span class='time'>3869</span>
And you call it like this:
$('.time').time_from_seconds();
The HTML is turned to:
<span class="time">1 minute 7 seconds</span>
<span class="time">15 minutes 53 seconds</span>
<span class="time">1 hour 4 minutes 29 seconds</span>
Each element also has a data attribute of 'original' with the seconds it originally contained.
My answer directly answers your question, but I'm going to take a shot in the dark: if you want to show how long ago something happened in human time (ie, "5 minutes ago") there is the jQuery timeago plugin for this. I don't think it accepts seconds as the format, though. It has to be a ISO 8601 date.
<html>
<head>
<script language="javascript" type="text/javascript" src="jquery.js"></script>
<script>
var tbl = [
[ 7*24*60*60, 'week' ],
[ 24*60*60, 'day' ],
[ 60*60, 'hour' ],
[ 60, 'minute' ],
[ 1, 'second' ]
];
function convert() {
var t = parseInt($('#val').val());
var r = '';
for (var i = 0; i < tbl.length; i++) {
var d = tbl[i];
if (d[0] < t) {
var u = Math.floor(t / d[0]);
t -= u * d[0];
r += u + ' ' + d[1] + (u == 1 ? ' ' : 's ');
}
}
$('#result').html(r);
}
</script>
</head>
<body>
<input id='val' type='text' size='10' />
<input type='button' value='convert' onclick='convert()' />
<div id='result' />
</body>
</html>
Give the element an id so that it's easy to access:
<span id="time">67</span>
Now you can get the value and convert it:
var o = document.getElementById('time');
var t = parseInt(o.innerHTML);
var h = Math.floor(t / 3600);
t %= 3600;
var m = Math.floor(t / 60);
var s = t % 60;
o.innerHTML =
(h > 0 ? h + ' hours ' : '') +
(m > 0 ? m + ' minutes ' : '') +
s + ' seconds';
Edit:
Added Math.floor() as suggested by Mike B.
Just in case you're looking for something more concise, and want to avoid the trailing whitespace and incorrect pluralization issues of some of the other attempts:
function timeString( t ) {
var ret = [], t = {
hour: parseInt(t/3600),
minute: parseInt(t/60%60),
second: t%60
};
for ( var n in t )
t[n] && ret.push( t[n], n + "s".substr( t[n] < 2 ) );
return ret.join(" ");
}
It's not elegant, but should work:
function format_duration(elem) {
var num = parseInt($(elem).text());
var hours = 0;
var mins = 0;
var secs = 0;
while (num > 0) {
if (num < 60) {
secs += num;
num = 0;
}
else if (num < 3600) {
mins++;
num -= 60;
}
else if (num < 86400) {
hours++;
num -= 3600;
}
}
var rv = "";
if (hours > 0) {
rv += hours+" hours ";
}
if (mins > 0) {
rv += mins+" mins ";
}
if (secs > 0) {
rv += secs+" secs ";
}
$(elem).text(rv);
}
(updated to answer jquery usage too)
Use
setTimeOut(expression,milisecs)
where expression can be the function to be called when the time in milisecs is completed.
A good example manipulating several time counters can be found at:
http://www.plus2net.com/javascript_tutorial/timer-set.php
nice Guffa. You'll need to add some "floor" calls in there, though:
<snip>
var h = Math.floor(t / 3600);
t %= 3600;
var m = Math.floor(t / 60);
<snip>