In Ruby, what is the right way to get the current system time since epoch(1970) in milliseconds?
I tried Time.now.to_i , it seems not the result I want. I need the result shows milliseconds and with long type, not float or double.
(Time.now.to_f * 1000).to_i
Time.now.to_f shows you the time including decimal numbers. To get number of miliseconds just multiply the time by 1000.
You can combine to_i and usec. The former returns the number of seconds since the Epoch, the latter returns the number of microseconds:
require 'time'
t = Time.at(1473152006, 2000)
t.to_i * 1000 + t.usec / 1000
#=> 1473152006002
This is equivalent to:
t.strftime('%s%L')
#=> "1473152006002"
In some cases like the above, to_f would introduce a slight floating point error:
t.to_f * 1000
#=> 1473152006001.9998
(t.to_f * 1000).to_i
#=> 1473152006001
Related
I have 2 DateTimes and I want to check if they're roughly 24 hours apart, plus or minus a small amount, say 5 minutes. Is there a built in way to do this?
There is not, but it is easy enough:
(-5 * 60 .. 5 * 60).include?((t2 - t1).abs - 24 * 3600)
"is the absolute difference between the two dates, when you subtract a full day, within plus or minus five minutes?"
Version 1: Works for both DateTime and Time. Converts everything to seconds.
def time_apart_within_drift?(t1, t2, diff: 24*60*60, drift: 5*60)
(t1.to_i - t2.to_i).abs <= diff + drift
end
As per the Ruby Style Guide, you should almost always use Time instead of DateTime. A Time object can still include the date, and it will make your calculations much cleaner.
This is because subtracting two DateTime objects gives you the difference in days as a Rational object, whereas subtracting two Time objects gives you the difference in seconds as a Float.
This allows you to write your function like so:
def time_apart_within_drift?(t1, t2, diff: 24*60*60, drift: 5*60)
(t1 - t2).abs <= diff + drift
end
# true
time_apart_within_drift?(Time.new(2020,3,5), Time.new(2020,3,4))
# true
time_apart_within_drift?(Time.new(2020,3,5), Time.new(2020,3,3,23,57))
# false
time_apart_within_drift?(Time.new(2020,3,5), Time.new(2020,3,3,23,47))
If using Time as well as rails and/or activesupport, the args can be made more readable using Duration objects:
def time_apart_within_drift?(t1, t2, diff: 24.hours, drift: 5.minutes)
(t1 - t2).abs <= diff + drift
end
I'm trying to find the decimal value from a percentage that a user inputs.
For example, if a user inputs "15", i will need to do a calculation of 0.15 * number.
I've tried using .to_f, but it returns 15.0:
15.to_f
#=> 15.0
I also tried to add 0. to the beginning of the percentage, but it just returns 0:
15.to_s.rjust(4, "0.").to_i
#=> 0
Divide by 100.0
The easiest way to do what you're trying to do is to divide your input value by a Float (keeping in mind the inherent inaccuracy of floating point values). For example:
percentage = 15
percentage / 100.0
#=> 0.15
One benefit of this approach (among others) is that it can handle fractional percentages just as easily. Consider:
percentage = 15.6
percentage / 100.0
#=> 0.156
If floating point precision isn't sufficient for your use case, then you should consider using Rational or BigDecimal numbers instead of a Float. Your mileage will very much depend on your semantic intent and accuracy requirements.
Caveats
Make sure you have ahold of a valid Integer in the first place. While others might steer you towards String#to_i, a more robust validation is to use Kernel#Integer so that an exception will be raised if the value can't be coerced into a valid Integer. For example:
print "Enter integer: "
percentage = Integer gets
If you enter 15\n then:
percentage.class
#=> Integer
If you enter something that can't be coerced to an Integer, like foo\n, then:
ArgumentError (invalid value for Integer(): "foo\n")
Using String#to_i is much more permissive, and can return 0 when you aren't expecting it, such as when called on nil, an empty string, or alphanumeric values that don't start with an integer. It has other interesting edge cases as well, so it's not always the best option for validating input.
I'm trying to find the amount from a percentage that a user inputs
If you retrieve the input via gets, you typically convert it to a numeric value first, e.g.
percentage = gets.to_i
#=> 15
Ruby is not aware that this 15 is a percentage. And since there's no Percentage class, you have to convert it into one of the existing numeric classes.
15% is equal to the fraction 15/100, the ratio 15:100, or the decimal number 0.15.
If you want the number as a (maybe inexact) Float, you can divide it by 100 via fdiv:
15.fdiv(100)
#=> 0.15
If you prefer a Rational you can use quo: (it might also return an Integer)
15.quo(100)
#=> (3/20)
Or maybe BigDecimal for an arbitrary-precision decimal number:
require 'bigdecimal'
BigDecimal(15) / 100
#=> 0.15e0
BigDecimal also accepts strings, so you could pass the input without prior conversion:
input = gets
BigDecimal(input) / 100
#=> 0.15e0
I'd like to create a ruby program to calculate the 1% on my investment every day for one year.
For example, if I invest 1000$ and get a profit of 1% at the end of the day will be 1010.0$ The second day I will invest 1010.0$ and I will get a 1% profit of 1020.1$ and so on.
I'd like to determine after 365 days what will be my initial investment.
I'm trying with a loop to print every single returning value but as you see I'm still a superrookie.
Thanks. Sam
I made it alone! Thanks for all of your answers!
money = 1000
days = 0
perc = 0.01
while days < 366
puts days
puts money
days += 1
money = money * perc + money
end
1000 * 1.01**365
#=> 37783.43433288728
You don't need to write a program for this; it's a one-line calculation.
But if you want to do it one day at a time and show the output of each day, how about:
money = 1000
(1..365).each do |day|
money *= 1.01
puts "After #{day} days: $#{money.round(2)}"
end
You should use BigDecimal instead of Float when dealing with monetary values:
require 'bigdecimal'
money = BigDecimal('1000')
percentage = BigDecimal('0.01')
For the loop I'd use upto which works very intuitively:
1.upto(365) do |day|
money += (money * percentage).round(2)
printf("%3d: %8.2f$\n", day, money)
end
money * percentage calculates the day's profit, rounded to 2 digits via round. You can adjust the rounding mode by passing a second argument.
printf then outputs day and money using the given formatting:
%3d prints an integer with width 3
%8.2f prints a float with 2 fractional digits and a total width of 8
Output:
1: 1010.00$
2: 1020.10$
3: 1030.30$
...
363: 37039.07$
364: 37409.46$
365: 37783.55$
The following is super simple but will get the job done. Basically you initialize a variable to 1000, we then loop 365 times. We have a block where all the math happens. It takes the value 1000 and multiplies it by 1.01 and overwrites the value of the intial investment. You can change the 365 to 2 or however many days you want. The puts print the value of the start. Just run this by putting it in a .rb file and running 'ruby file.rb'
start = 1000
365.times do
start = start*1.01
puts start
end
puts start
I want to get the most possible precis time using Ruby. For example:
3.times.map do
Thread.new do
# Expect 3 differnt results from each thread
p Time.now.precis_time
end
end.each(&:join)
However, even using the strftime, I still can not achieve the goal. So is there any other way to get this?
The most precise timer available to Ruby is Process::clock_gettime. To avoid losing precision to float rounding, use :nanosecond unit:
3.times { p Process.clock_gettime(Process::CLOCK_REALTIME, :nanosecond) }
# => 1491185078101717000
# => 1491185078101741000
# => 1491185078101747000
EDIT: This is the same time that is available by Time.now. On Linux, the two have nanosecond precision. However, there is another clock that has nanosecond precision even on OSX: CLOCK_MONOTONIC. This clock does not track time from epoch, but time from "some event", this event normally being your computer's boot time. To get the most precise time, one can take the difference between CLOCK_REALTIME and CLOCK_MONOTONIC and apply it later:
clock_diff = Process.clock_gettime(Process::CLOCK_REALTIME, :nanosecond) -
Process.clock_gettime(Process::CLOCK_MONOTONIC, :nanosecond)
3.times {
nsec = Process.clock_gettime(Process::CLOCK_MONOTONIC, :nanosecond) + clock_diff
time = Time.at(nsec / 1_000_000_000, nsec % 1_000_000_000 / 1_000.0)
p time.strftime("%Y-%m-%d %H:%i:%s.%N")
}
On Linux, I think the most precise time is just Time.now. The to_r method "is intended to be used to get an accurate value representing the nanoseconds since the Epoch" (from the docs).
t = Time.now
p t.to_r # =>(1491206113721862629/1000000000)
p [t.to_i, t.nsec] # =>[1491206113, 721862629]
On JRuby, you can use java.lang.System.nano_time :
java.lang.System.nano_time - java.lang.System.nano_time
# -15607
to get nanoseconds since a fixed but arbitrary origin. From the documentation :
This method can only be used to measure elapsed time and is not
related to any other notion of system or wall-clock time. The value
returned represents nanoseconds since some fixed but arbitrary origin
time (perhaps in the future, so values may be negative). The same
origin is used by all invocations of this method in an instance of a
Java virtual machine; other virtual machine instances are likely to
use a different origin.
If you want a precise Time with Java < 9, you could use currentTimeMillis :
java.lang.System.current_time_millis
#=> 1491214503112
But then, you wouldn't get more information than from Time.now :
Time.now.to_f
#=> 1491214592.562
So Time.now might be your best bet : it will work on any Ruby version on any system. Note that nanoseconds precision doesn't mean nanoseconds accuracy.
I dare say you could ignore any digit related to a shorter time than milliseconds. You could output the distance between NYC and Los-Angeles in micrometers, it doesn't mean it would be useful though.
I'm wishing to figure out how many milliseconds a particular function uses. So I looked high and low, but could not find a way to get the time in Ruby with millisecond precision.
How do you do this? In most programming languages its just something like
start = now.milliseconds
myfunction()
end = now.milliseconds
time = end - start
You can use ruby's Time class. For example:
t1 = Time.now
# processing...
t2 = Time.now
delta = t2 - t1 # in seconds
Now, delta is a float object and you can get as fine grain a result as the class will provide.
You can also use the built-in Benchmark.measure function:
require "benchmark"
puts(Benchmark.measure { sleep 0.5 })
Prints:
0.000000 0.000000 0.000000 ( 0.501134)
Using Time.now (which returns the wall-clock time) as base-lines has a couple of issues which can result in unexpected behavior. This is caused by the fact that the wallclock time is subject to changes like inserted leap-seconds or time slewing to adjust the local time to a reference time.
If there is e.g. a leap second inserted during measurement, it will be off by a second. Similarly, depending on local system conditions, you might have to deal with daylight-saving-times, quicker or slower running clocks, or the clock even jumping back in time, resulting in a negative duration, and many other issues.
A solution to this issue is to use a different time of clock: a monotonic clock. This type of clock has different properties than the wall clock.
It increments monitonically, i.e. never goes back and increases at a constant rate. With that, it does not represent the wall-clock (i.e. the time you read from a clock on your wall) but a timestamp you can compare with a later timestamp to get a difference.
In Ruby, you can use such a timestamp with Process.clock_gettime(Process::CLOCK_MONOTONIC) like follows:
t1 = Process.clock_gettime(Process::CLOCK_MONOTONIC)
# => 63988.576809828
sleep 1.5 # do some work
t2 = Process.clock_gettime(Process::CLOCK_MONOTONIC)
# => 63990.08359163
delta = t2 - t1
# => 1.5067818019961123
delta_in_milliseconds = delta * 1000
# => 1506.7818019961123
The Process.clock_gettime method returns a timestamp as a float with fractional seconds. The actual number returned has no defined meaning (that you should rely on). However, you can be sure that the next call will return a larger number and by comparing the values, you can get the real time difference.
These attributes make the method a prime candidate for measuring time differences without seeing your program fail in the least opportune times (e.g. at midnight at New Year's Eve when there is another leap-second inserted).
The Process::CLOCK_MONOTONIC constant used here is available on all modern Linux, BSD, and macOS systems as well as the Linux Subsystem for Windows. It is however not yet available for "raw" Windows systems. There, you can use the GetTickCount64 system call instead of Process.clock_gettime which also returns a timer value in millisecond granularity on Windows (>= Windows Vista, Windows Server 2008).
With Ruby, you can call this function like this:
require 'fiddle'
# Get a reference to the function once
GetTickCount64 = Fiddle::Function.new(
Fiddle.dlopen('kernel32.dll')['GetTickCount64'],
[],
-Fiddle::TYPE_LONG_LONG # unsigned long long
)
timestamp = GetTickCount64.call / 1000.0
# => 63988.576809828
You should take a look at the benchmark module to perform benchmarks. However, as a quick and dirty timing method you can use something like this:
def time
now = Time.now.to_f
yield
endd = Time.now.to_f
endd - now
end
Note the use of Time.now.to_f, which unlike to_i, won't truncate to seconds.
Also we can create simple function to log any block of code:
def log_time
start_at = Time.now
yield if block_given?
execution_time = (Time.now - start_at).round(2)
puts "Execution time: #{execution_time}s"
end
log_time { sleep(2.545) } # Execution time: 2.55s
Use Time.now.to_f
The absolute_time gem is a drop-in replacement for Benchmark, but uses native instructions to be far more accurate.
If you use
date = Time.now.to_i
You're obtaining time in seconds, that is far from accurate, specially if you are timing little chunks of code.
The use of Time.now.to_i return the second passed from 1970/01/01. Knowing this you can do
date1 = Time.now.to_f
date2 = Time.now.to_f
diff = date2 - date1
With this you will have difference in second magnitude. If you want it in milliseconds, just add to the code
diff = diff * 1000
I've a gem which can profile your ruby method (instance or class) - https://github.com/igorkasyanchuk/benchmark_methods.
No more code like this:
t = Time.now
user.calculate_report
puts Time.now - t
Now you can do:
benchmark :calculate_report # in class
And just call your method
user.calculate_report