Converting Time strings into proper Formats in Ruby - ruby

I am tried to convert following strings into a proper Time in Ruby,
For.Ex.
string_a = "1 minute, 6 seconds"
string_b = "3 minutes, 35 seconds"
I am trying to achieve is,
convert: string_a into time format: 1:06 - as it has just 6 second, adding 0 in front of it.
and string_b into time format: 3.35
Could you please someone help me out?

Assuming input strings will always be in same format:
time = string_a.scan(/\d+/)
time[0] + ":" + time[1].rjust(2,'0')
# => "1:06"
string_b = "3 minutes, 35 seconds"
timeb = string_b.scan(/\d+/)
timeb[0] + ":" + timeb[1].rjust(2,'0')
# => "3:35"
You can make your regex stricter, however if the input strings are always in "m minute, s seconds" format then this should be sufficient.

Related

Convert supposed seconds to duration?

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"

Ruby Date Time Subtraction

I am trying to calculate the exact duration a process took from some log file result. After parsing the log, I reached at the following stage:
my_array = ["Some_xyz_process", "Start", "2018-07-12", "12:59:53,397", "End", "2018-07-12", "12:59:55,913"]
How can I subtract the start date and time from the end date and time in order to retrieve the exact duration the process took?
my_array = ["Some_xyz_process",
"Start", "2018-07-12", "12:59:53,397",
"End", "2018-07-12", "12:59:55,913"]
require 'date'
fmt = '%Y-%m-%d%H:%M:%S,%L'
is = my_array.index('Start')
#=> 1
ie = my_array.index('End')
#=> 4
DateTime.strptime(my_array[ie+1] + my_array[ie+2], fmt).to_time -
DateTime.strptime(my_array[is+1] + my_array[is+2], fmt).to_time
#=> 2.516 (seconds)
See DateTime#strptime and DateTime# (the latter for format directives). As long as the date and time formats are known I always prefer strptime to parse. Here's an example of why:
DateTime.parse 'Theresa May has had a bad week over Brexit'
#=> #<DateTime: 2018-05-01T00:00:00+00:00 ((2458240j,0s,0n),+0s,2299161j)>`.
You can concat the date and time field and use Time.parse to convert it to a time object and then calculate the difference in number of seconds
Time.parse('2018-07-12 12:59:55,397').to_i - Time.parse('2018-07-12 12:59:53,913').to_i
Hope this helps

Ruby time subtraction

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

How to convert 24:00 hours to 12:00 format

I need help with my pseudocode assignment: convert 2400 hours to 12 format
Design an algorithm that will prompt for and receive the item expresses in 2400 format (e.g. 2305 Hours), convert it to 12 hour format (e.g. 11.05pm) and display sentinel time of 9999 is entered.
Prompt for hrs, mins
Get hrs, mins
DOWHILE(hrs NOT = 99) AND (mins NOT = 99) // If hrs & mins not = to 99 then it will run if not it will stop
IF (hrs = 00) THEN // midnight. 0030. It will + 12 and display 12:30am
format = am
time = hrs + 12
Display hrs, ":" , mins, format
ELSE
IF (hrs > 12) THEN // afternoon. 1630. It will – 12 and display 4:30pm
format = pm
hrs = hrs – 12
Display hrs, ":" , mins, format
ELSE
IF (hrs < 12) THEN // from midnight 0100 to 1159. It will display AM
format = am
Display hrs, ":" , mins, format
IF (hrs = 12) THEN // if format is 1230. It will display 1230PM
format = pm
Display hrs, ":" , mins, format
ENDIF
ENDIF
ENDIF
ENDIF
IF (hrs < 0) OR (hrs > 23) THEN // hrs less than 0 or more than 23 is error.
Display ‘Invalid hour input’
IF (mins < 0) OR (mins >59) THEN // mins less than 0 or more than 59 is error.
Display ‘Invalid mins input’
ENDIF
ENDIF
Prompt for hrs, mins // you prompt again , we are still in the loop until we hit 9999
Get hrs, mins
ENDDO // which stop here because it’s 9999
Am i doing correctly? Please advice. New student here! many thanks!
Well, depending upon how your professor expects your pseudocode to look like, what you have should work fine, I think. A few of the lines are a bit redundant, though. You could combine the out-of-bounds checking of the hours and minutes into one IF statement. You could then set your time variable to "am" by default, which would turn your IF - ELSE IF - ELSE to a single IF - ELSE. Oh, and not that I'm sure it matters much, but rather than using hours = hours + 12 when hours = 0, you could probably just do hours = 12. Again, what you have should work just fine, I think.
EDIT: Ah... again, not sure if this matters, but have a way to possibly terminate the program might be useful, too. Otherwise, you'll be stuck in your loop forever, it seems.
EDIT 2: Here's what I would do...
done = false
DOWHILE !done
PROMPT hours, minutes
GET hours, minutes
IF hours < 0 OR hours > 23 OR minutes < 0 OR minutes > 60
DISPLAY "Invalid Time"
ELSE
format = "AM"
IF hours > 12
format = "PM"
hours = hours - 12
ELSE IF hours == 0
hours = 12
ELSE IF hours == 12
format = "PM"
DISPLAY hours ":" minutes format
ENDIF
ENDIF
PROMPT "Are you done?"
GET done
ENDLOOP

ROR + Ruby Date Decrease by 15 minutes

If I have #time = Time.now.strftime("%Y-%m-%d %H:%M:%S"),
How can I reduce this time by 15 minutes ?
I already tried this one :: #reducetime = #time-15.minutes, works fine at console but give errors while execution. Other than this Is there any way to resolve this issue.
Thanks
Your problem is that you're formatting your time into a string before you're done treating it as a time. This would make more sense:
#time = Time.now
#reducetime = #time - 15.minutes
# And then later when you're reading to display #time...
formatted_time = #time.strftime("%Y-%m-%d %H:%M:%S")
You shouldn't format your data until right before you're ready to display it.
If you must have #time as the formatted time then you're going to have to parse it before computing #reducetime:
#reducetime = (DateTime.strptime(#time, "%Y-%m-%d %H:%M:%S") - 15.minutes).to_time

Resources