5

I found a countdown timer on this site which works well in linux, but I need this exact thing done in Ruby. I am new to ruby so having trouble figuring this out.

  ==Linux version==

   seconds=20; date1=$((`date +%s` + $seconds)); 
   while [ "$date1" -ne `date +%s` ]; do 
   echo -ne "$(date -u --date @$(($date1 - `date +%s` )) +%H:%M:%S)\r"; 
   done

So far I have tried this which does not give me the desired output

   t = Time.now
    seconds = 30
    date1 = (t + seconds)
    while t != date1
      puts t 
      sleep 1
    end

This gives an output like this which A) is not counting down and B) has date added which I don't want.

  2015-05-28 09:57:18 -0500
  2015-05-28 09:57:18 -0500
  2015-05-28 09:57:18 -0500
  2015-05-28 09:57:18 -0500

I want it to output like the linux version which looks like this

  00:00:30
  00:00:29
  00:00:28
Dennis Ferguson
  • 97
  • 2
  • 10
  • 3
    what have you tried so far and what is causing it to fail - please give some code examples and/or error messages so we can see the trouble you're having. – dax May 28 '15 at 14:52
  • All the solutions below will not print _exactly_ once a second, but every one second plus the time it takes to run the code inside the loop. If you're running this for a long time, it might be off quite a bit. The solutions might work fine for you though, you have to decide that depending on your use case. For a solution that counteracts this effect see http://stackoverflow.com/a/12522514/192702 – Patrick Oscity May 28 '15 at 15:35
  • @PatrickOscity, that's a nice solution – dax May 28 '15 at 15:36

3 Answers3

8

Try this, if you just need the output and don't use any Time related info :

30.downto(0) do |i|
  puts "00:00:#{'%02d' % i}"
  sleep 1
end

With time (1st draft) :

t = Time.new(0)
countdown_time_in_seconds = 300 # change this value

countdown_time_in_seconds.downto(0) do |seconds|
  puts (t + seconds).strftime('%H:%M:%S')
  sleep 1
end
floum
  • 1,149
  • 6
  • 17
  • Thanks this works also and it doesn't have the 18 in the time. – Dennis Ferguson May 28 '15 at 15:44
  • But what if I want it to count down more than 60 seconds say 5 minutes or 300 seconds? – Dennis Ferguson May 28 '15 at 16:02
  • In that case, it's really easier to go for some date formatting. Gonna edit my answer to reflect that. – floum May 28 '15 at 17:58
  • Thanks everyone these are all great answers. @floum your answer also worked. I cannot select all answers so going to select yours to close this topic out. – Dennis Ferguson May 29 '15 at 15:51
  • note that for 30 seconds, it is probably no big deal. if it is to count down 2 hours or 1.5 days, then this will be counting that many seconds plus any processing time between the sleep call... so the final sleeping time will be more than what is specified. @dax 's answer won't have that issue, as it is using a time now and end time to compare – nonopolarity Dec 04 '20 at 10:31
1

Try this:

def countdown(seconds)
  date1 = Time.now + seconds
  while Time.now < date1
    t = Time.at(date1.to_i - Time.now.to_i)
    p t.strftime('%H:%M:%S')
    sleep 1
  end
end

This is tacking an extra hour to the time...not sure why that is, but the big thing is to use Time.now the whole way through.

edit if you don't want to use it as a method, you can just use the code inside:

date1 = Time.now + 5 # your time here
while Time.now < date1
  t = Time.at(date1.to_i - Time.now.to_i)
  p t.strftime('%H:%M:%S')
  sleep 1
end
dax
  • 10,779
  • 8
  • 51
  • 86
  • it's a method, so you need to call `countdown x` where `x` is what you want to countdown from – dax May 28 '15 at 15:34
  • yeah sorry, I forgot to call the method doh! It is working now. Thank you!! – Dennis Ferguson May 28 '15 at 15:37
  • Only one thing... why does it format the time as "18:00:30" instead of 00:00:30..00:00:29...? – Dennis Ferguson May 28 '15 at 15:40
  • funny it was formatting it as "01:00:30" for me...maybe something with time zones? – dax May 28 '15 at 18:42
  • Just out of curiosity, how would you do this so that it prints the output on the same line overwriting the last output? I have been playing around using \r & "$stdout.flush" but haven't had much luck. it keeps putting each countdown on a separate line. It would be nice to have this output on just one line. – Dennis Ferguson May 29 '15 at 16:14
  • on the command line? I don't think that's possible..I could be wrong though. – dax May 29 '15 at 17:46
0

I ended up using the first method dax mentioned but removing the %H which allowed me to call it using longer times

def countdown(seconds)
  date1 = Time.now + seconds
  while Time.now < date1
    t = Time.at(date1.to_i - Time.now.to_i)
    puts t.strftime('%M:%S')
    sleep 1
  end 
end
dax
  • 10,779
  • 8
  • 51
  • 86
Dennis Ferguson
  • 97
  • 2
  • 10