views:

1079

answers:

6

I was wondering what the best way is to calculate the difference in time from now to a certain point, lets say the countdown time.

I have an auction that has a closetime at a certain point, this time is stored in an mysql record in the format " DATETIME 00-00-000 00:00:00 ". This record is called closetime.

Now on my website i have a javascript that gets this time via a php file. The javascript loops every second using setInterval 1000. The php file gets the closetime from the db, and sends it back in this format

strtotime($result['closetime']);

And i get the time of the request, i want to use the server time, and not the time in javascript, because the clock of the user can be off.

strtotime(date("H:i:s", $_SERVER['REQUEST_TIME']))

I send back these two timestamps and calculate the time difference between them in javascript. I use this function to do it, the values send back from php i call currentTime and closeTime, i think this should be clear.

function auctionDelayTime(currentTime,closeTime){
    totaldelay = closeTime - currentTime;
    if(totaldelay <= 0){
        return 'ended';
    }else{
        if( days=parseInt((Math.floor(totaldelay/86400))) )
            totaldelay = totaldelay % 86400;
        if( hours=parseInt((Math.floor(totaldelay/3600))) )
            totaldelay = totaldelay % 3600;
      if( minutes=parseInt((Math.floor(totaldelay/60))) )
            totaldelay = totaldelay % 60;
        if( seconds=parseInt((Math.floor(totaldelay/1))) )
            totaldelay = totaldelay % 1;

        return hours+':'+formatTimes(minutes)+':'+formatTimes(seconds);
    }
}
function formatTimes(value){
    return value < 10 ? '0'+value : value;
}

I think this is a awful lot of code do something so simple. Does anyone have a better solution or maybe a more 'beautiful' code.

enjoy!

A: 

Use Date object.

var d = new Date(difference_in_milliseconds);
var seconds = d.getSeconds();
var minutes = d.getMinutes();
var hours = d.getHours() - 1; //See note

Note: Strangely, hours value is bigger by one than I would expect for reason I don't understand. It looks like "midnight Jan 1, 1970" was at 1 AM :-)

UPDATE: The difference of 1 is due to the offset of my timezone (GMT +1).

Slight change that will solve this:

var d = new Date();
var offset = d.getTimezoneOffset() * 60000;
var d = new Date(difference_in_milliseconds + offset);
var seconds = d.getSeconds();
var minutes = d.getMinutes();
var hours = d.getHours();
Josef Sábl
I believe that's because of the timezone on your computer. The a timestamp of 0 is 00:00 Jan 1 1970 UTC
adam
I will try this method to. Do you think the time calculation will be faster in php or javascript?
Saif Bechan
I would not bother with the speed of this calculation. Both ways will be very fast. I would prefer php side, it will be more reliable.
Josef Sábl
+1  A: 

In php you can also do it this way:

$time_period = ( $tEnd - $tStart );
$time_increments = array( 'days' => 86400, 'hrs' => 3600, 'mins' => 60, 's' => 1 );

## will hold our values for ( day, minute, hour, seconds )
$time_span = array();

## cycle through time_increments
while( list( $key, $value ) = each( $time_increments )) {
   $this_value = (int) ( $time_period / $value );
   $time_period = ( $time_period % $value );

   # save value
   $time_span[$key] = $this_value;
 }

 ## show results
 while( list( $key, $value ) = each( $time_span )) {
    print "$value $key ";
 }

EDIT as Josef said:

 $tEnd = mktime(14,15,00,1,7,2009);
 $tStart = mktime(15,10,00,12,5,2006);
 $time_period = ( $tEnd - $tStart );

 echo date("z H:i:s", $time_period); 

the result is: 33 '23:05:00' :S

NoOne
Wow, what an overengineered solution. I am not even sure what you tried to do here, but would not it be simpler to just use date function? I mean like date("z H:i:s", $time_period); Nice adept for The Daily WTF :-)
Josef Sábl
Good to point that this will not work for times bigger then one year.
Josef Sábl
Thanks for the answers, i will try the solution josef used. But will this solution give me the exact remaining time, or will this solution make a new date given the timestamp. For example if there are 2 mins remaining the outcome would have to be 00:02:00. And not a new date given the timestamp of 120.
Saif Bechan
The first solution i posted (using $tEnd = mktime(14,15,00,1,7,2009) and $tStart = mktime(15,10,00,12,5,2006)) will print: 763 days 23 hrs 5 mins 0 s. But you can, offcorse, costumize the output.
NoOne
A: 

This JavaScript library is easy to use and will likely serve you well.

Upper Stage
A library can be handy, but i think this is such a simple thing to do that i prefer to use raw code than a whole library. But i will sure check it out, thank you for your time.
Saif Bechan
I understand; good luck.
Upper Stage
A: 

Why not have the php page give you the difference?

$sql = "SELECT UNIX_TIMESTAMP(NOW()) as currentTime, UNIX_TIMESTAMP(closeTime) as closeTime FROM yourTable WHERE yourRecordId = '123'";

$query = mysql_query($sql);

$result = mysql_fetch_assoc($query);

echo timeRemaining($result['currentTime'], $result['closeTime']);

function timeRemaining($start, $end) {
    $dateDiff = $end - $start;
    if ($dateDiff <= 0) { return 'Ended'; }
    $fullDays = floor($dateDiff/(60*60*24));
    $fullHours = floor(($dateDiff-($fullDays*60*60*24))/(60*60));
    $fullMinutes = floor(($dateDiff-($fullDays*60*60*24)-($fullHours*60*60))/60);
    return "Ending in $fullDays days, $fullHours hours and $fullMinutes minutes.";   
}
cOle2
There will be a lot of calculation every second. This will have to run every second for every user. So if there are 1000 users there will be a lot of php calculations every second for the server to do. If o do this in javascript is will be the work of the browser and not my server. It is a fairly small calculation and would not take much of the server, but i think over a large amount of time and a large number of hits this does make a slight difference. What do you think
Saif Bechan
A: 

Do you really have to get the time through AJAX every 1000 ms? (i suppose that you're hoping for closetime changes? ...)

But if you really must do it this way, i'd suggest getting the time difference directly in MySQL for code simplicity.

$sql = "SELECT TIMEDIFF(NOW(), `CreateTime`) from `Table` WHERE `id`=1;"
Trouts
Solutions with functions like NOW() in mysql do not scale well in large applications i have heard, there are some recourses available online you can read trough. Its better to just get the time in PHP and inset that in the query. Secondly i want to lay the stress on the browser side, and not the server. I want the php to run as fast as possible and get the request back to the user. And the browser can do the rest of the calculations.
Saif Bechan
+1  A: 

There is a jquery Countdown Plugin that supports server sync through AJAX:

From the docs:

Synchronise the client's time with that of the server by providing a function that returns the current server date and time. This date and time should take into account the server's timezone and any difference between that time and the client's is applied to the countdown when it is started or changed.

The following example uses a PHP program on the server to return the current server time in a format that can be used directly by the JavaScript callback. You should make sure that your server call is synchronous.

$(selector).countdown({ 
    until:liftoffTime, serverSync: serverTime}); 

function serverTime() { 
    var time = null; 
    $.ajax({url: 'http://myserver.com/serverTime.php', 
        async: false, dataType: 'text', 
        success: function(text) { 
            time = new Date(text); 
        }, error: function(http, message, exc) { 
            time = new Date(); 
    }}); 
    return time; 
}

serverTime.php:

<?php 
$now = new DateTime(); 
echo $now->format("M j, Y H:i:s O")."\n"; 
?>
jbochi
I use this plugins in my the online exam taking application. I can add an event handler when countdown reach zero to automatically submit the page. This plugins is easy to use, easy to extended, so I recomend you to try it.
Donny Kurnia
I my application, I don't care the user's browser time. I just passing the number of second left to the plugins, and it display the remaining time. No need for the resource heavy AJAX, just for displaying time left. Imagine there are 1000 user, simultaneously do AJAX request every second, your hosting might think of it as DDoS attack :)
Donny Kurnia
This method did not work well for me. The method Josef described did the trick. This plugin only gives me the servers time, it does not calculate any difference between the two given times.
Saif Bechan