Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ruby Time comparison mayhem and chaos. An unsolvable mystery [closed]

Tags:

ruby

Look, here's the thing... There is absolutely no reason why this is not working. However, I've decided to publicly come here and express my discontent and frustration towards this piece of code. For as much as I love Ruby I believe there are things coming past me unseen. Please, take a look at it.

def pull(start_time=10.minutes.ago.utc, end_time=Time.now.utc)
  count = 0
  binding.pry
  while start_time.utc <= end_time.utc do
    count =+ 1
    start_time = (start_time + 1.minute).utc
  end
  p "Count is at #{count}, and start_time is at #{start_time}"
end

I've tried to compare Time objects multiple times and in many different ways but I could never make an incremental loop using this comparison. I've been inside the loop and appended the binding.pry to inspect the values of start_time. It's properly being incremented. But the loop is failing to be making any logical sense.

To experiment, I have also printed a message at the end to check the values of the counter count to see how many times the loop is going through. It stops after the first round. Immediately after start_time gets assigned a new value inside the loop. This is the only message I have from calling this method.

"Count is at 1, and start_time is at 2020-01-26 17:49:37 UTC"

I look forward to hearing suggestions about something unseen and escaping me. Because I came from Rails I admit I'm not entirely sure about all Ruby's default libraries and how to use them.

By the way, to run this code you will have to require these:

require 'active_support/core_ext/numeric'
require 'pry'
like image 422
Matheus Avatar asked Dec 15 '25 03:12

Matheus


2 Answers

You're doing count =+ 1, not count += 1 like you intended.

Here's the corrected version:

def pull(start_time=10.minutes.ago.utc, end_time=Time.now.utc)
  count = 0
  while start_time.utc <= end_time.utc do
    count += 1
    start_time = (start_time + 1.minute).utc
  end
  p "Count is at #{count}, and start_time is at #{start_time}"
end

Output with corrected version:

=> "Count is at 11, and start_time is at 2020-01-26 18:41:22 UTC"
like image 68
anothermh Avatar answered Dec 18 '25 08:12

anothermh


It might not be a full answer but I think it could prevent you from having yet another headache:

def pull(start_time=10.minutes.ago, end_time=Time.now)

This line looks simple enough but there's a problem lurking: When no argument is sent, start_time will be initialized to 10.minutes.ago and end_time will be initialized to Time.now.

The problem is that end_time will be initialized a few microseconds after start_time, so the difference between both will be 10 minutes + a few microseconds, which is strictly longer than 10 minutes:

 10.minutes.ago - Time.now
 => -600.000279946

In the other direction, it would be a bit shorter than 10 minutes:

Time.now - 10.minutes.ago
# => 599.999981608

You might want to divide by 60 and round to avoid this problem:

(Time.now - 10.minutes.ago) / 60
#=> 9.99999967125
((Time.now - 10.minutes.ago) / 60).round
#=> 10
like image 28
Eric Duminil Avatar answered Dec 18 '25 08:12

Eric Duminil



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!