I'm new to Ruby so I'm probably going about this completely wrong, but using taglib-ruby I keep getting a wrong result unless it's a wrong amount of seconds maybe nanoseconds?
I tried with bash and mediainfo a different movie but worked ok ...
$(date -ud "#$(($seconds/1000))" +'%_H:%M')
def get_duration_hrs_and_mins(milliseconds)
return '' unless milliseconds
hours, milliseconds = milliseconds.divmod(1000 * 60 * 60)
minutes, milliseconds = milliseconds.divmod(1000 * 60)
seconds, milliseconds = milliseconds.divmod(1000)
"#{hours}h #{minutes}m #{seconds}s #{milliseconds}ms"
end
TagLib::MP4::File.open("filename.mp4") do |mp4|
seconds = mp4.length
puts get_duration_hrs_and_mins(seconds)
end
The amount of seconds is 1932993085 and the duration should be roughly 2 h 15 min.
I'm afraid you are misinformed. The length attribute of a TagLib::MP4::File object is inherited from the regular File class and just tells you the size of the file in bytes; it has nothing to do with the duration of the contained media:
$ ls -l test.mp4
-rw-r--r--# 1 user staff 39001360 Aug 14 2015 test.mp4
$ ruby -rtaglib -e 'TagLib::MP4::File.open("test.mp4"){|f|puts f.length}'
39001360
The particular file I'm examining in the above code snippet happens to be 25 seconds long, but there's no way to tell that from the fact that it's about 39 megabytes in size.
What you want is the #length method of the TagLib::MP4::Properties object, not the ::File one. You can get that by calling #audio_properties on the File object:
TagLib::MP4::File.open("filename.mp4") do |mp4|
seconds = mp4.audio_properties.length
puts get_duration_hrs_and_mins(seconds)
end
That return value is seconds, not milliseconds, so you need to adjust your get_duration method accordingly. Really you just want something like this:
total_seconds = mp4.audio_properties.length
total_minutes, seconds = total_seconds.divmod(60)
total_hours, minutes = total_minutes.divmod(60)
days, hours = total_hours.divmod(24)
puts "Duration is #{days}d#{hours}h#{minutes}m#{seconds}s"
Related
Is it possible to automatically check time then execute certain codes?
timer = os.date('%H:%M:%S', os.time() - 13 * 60 * 60 )
if timer == "18:04:40" then
print("hello")
end
I am trying to print hello on "18:04:40" everyday (os.date's time) without setting up a timer (which counts how much time past since the program's initiation) as I can't run the program 24 hours non-stop...
Thanks for reading.
This may not be the best solution but, when using a library like love2d for example you could run something like this:
function love.update(dt)
timer = os.date('%H:%M:%S', os.time() - 13 * 60 * 60 )
if timer >= value then
--stuff here
end
end
Or if you wanna make it so you have a whole number something like
tick = 0
function love.update(dt)
tick = tick + dt
if tick > 1 then
timer = os.date('%H:%M:%S', os.time() - 13 * 60 * 60 )
if timer >= value then
--stuff here
end
end
end
Lua has to check the time in some way.
Without a loop that can be realized with debug.sethook().
Example with Lua 5.1 typed in an interactive Lua (lua -i)...
> print(_VERSION)
Lua 5.1
> debug.sethook() -- This clears a defined hook
> -- Next set up a hook function that fires on 'line' events
> debug.sethook(function() local hour, min, sec = 23, 59, 59 print(os.date('%H:%M:%S', os.time({year = 2021, month = 12, day = 11, hour = hour, min = min, sec = sec}))) end, 'l')
-- just hit return/enter or do other things
23:59:59
5.9 - The Debug Library
https://www.lua.org/manual/5.1/manual.html#5.9
In my project i get from external system date&time in VARIANT DATE type and need to convert it to datetime (i.e. 43347.6625 => 04/09/2018 16:29:59).
Do you know how to do it in ruby? what is the best approach? I did not find any ruby built-in method to do such a conversion...
here a method to do the calculation, the date you give is not correct, it should be what this method is returning, check with https://planetcalc.com/7027/
def variant2datetime variant
# number of days after 1-1-1900 minus 2 days for starting with 0
# and having a day that didn't exist because 1900 wasn't a leap year
date = Time.new("1900-01-01") + (variant.to_i - 2) * 24 * 60 * 60
fraction = variant % 1
hours = (fraction - fraction.to_i) * 24
minutes = (hours - hours.to_i) * 60
seconds = (minutes - minutes.to_i) * 60
Time.new(date.year, date.month, date.day, hours.to_i, minutes.to_i, seconds.to_i)
end
variant2datetime 43347.6625 # 2018-09-04 15:53:59 +0200
There is the following task: I need to get minutes between one time and another one: for example, between "8:15" and "7:45". I have the following code:
(Time.parse("8:15") - Time.parse("7:45")).minute
But I get result as "108000.0 seconds".
How can I fix it?
The result you get back is a float of the number of seconds not a Time object. So to get the number of minutes and seconds between the two times:
require 'time'
t1 = Time.parse("8:15")
t2 = Time.parse("7:45")
total_seconds = (t1 - t2) # => 1800.0
minutes = (total_seconds / 60).floor # => 30
seconds = total_seconds.to_i % 60 # => 0
puts "difference is #{minutes} minute(s) and #{seconds} second(s)"
Using floor and modulus (%) allows you to split up the minutes and seconds so it's more human readable, rather than having '6.57 minutes'
You can avoid weird time parsing gotchas (Daylight Saving, running the code around midnight) by simply doing some math on the hours and minutes instead of parsing them into Time objects. Something along these lines (I'd verify the math with tests):
one = "8:15"
two = "7:45"
h1, m1 = one.split(":").map(&:to_i)
h2, m2 = two.split(":").map(&:to_i)
puts (h1 - h2) * 60 + m1 - m2
If you do want to take Daylight Saving into account (e.g. you sometimes want an extra hour added or subtracted depending on today's date) then you will need to involve Time, of course.
Time subtraction returns the value in seconds. So divide by 60 to get the answer in minutes:
=> (Time.parse("8:15") - Time.parse("7:45")) / 60
#> 30.0
I am trying to time how long a method takes to execute, so I record the start time and then at the end subtract it from the current time which should give me the difference in seconds. I get back 123 seconds when it actually took over 10 minutes to run.
def perform_cluster_analysis
start = Time.now
# A whole lot of tasks performed here
puts 'time taken: '
puts (Time.now - start)
end
The output I get is:
time taken:
123.395808311
But when timed with a stopwatch it actually took over 10 minutes, so why am I getting back 123 seconds instead of +- 600 (10 minutes)
I know there is the Date#step method, however it wants days for steps. I need a range or array for every minute in a given day (1440 entries).
What's the best, and most effeicient way to do this in Ruby 1.9.3?
Ultimately, I'm going to format the output to be used like this:
00:00:00
00:01:00
00:02:00
...
23:59:00
This might get you started:
0.upto((60 * 24) - 1).each { |m| puts "%02d:%02d:00" % [m / 60, m % 60] }
You can step anyway:
require 'date'
today = Date.today.to_datetime
tomorrow = today+1
min = 1.0/(24*60)
today.step(tomorrow, min){|d| p d.strftime("%H:%M:%S")}