Subtract Time from CSV using Ruby - ruby

Hi I would like to subtract time from a CSV array using Ruby
time[0] is 12:12:00AM
time[1] is 12:12:01AM
Here is my code
time_converted = DateTime.parse(time)
difference = time_converted[1].to_i - time_converted[0].to_i
p difference
However, I got 0
p time[0].to_i gives me 12
is there a way to fix this?

You can use Time#strptime to define the format of the parsed string.
In your case the string is %I:%M:%S%p.
%I = 12 hour time
%M = minutes
%S = seconds
%p = AM/PM indicator
So to parse your example:
require 'time'
time = %w(12:12:00AM 12:12:01AM)
parsed_time = time.map { |t| Time.strptime(t, '%I:%M:%S%p').to_i }
parsed_time.last - parsed_time.first
=> 1

Use the Ruby DateTime class and parse your dates into objects of that class.

Related

Time Delta problem in Hackerrank not taking good answer / Python 3

The hackerrank challenge is in the following url: https://www.hackerrank.com/challenges/python-time-delta/problem
I got testcase 0 correct, but the website is saying that I have wrong answers for testcase 1 and 2, but in my pycharm, I copied the website expected output and compared with my output and they were exactly the same.
Please have a look at my code.
#!/bin/pyth
# Complete the time_delta function below.
from datetime import datetime
def time_delta(tmp1, tmp2):
dicto = {'Jan':1, 'Feb':2, 'Mar':3,
'Apr':4, 'May':5, 'Jun':6,
'Jul':7, 'Aug':8, 'Sep':9,
'Oct':10, 'Nov':11, 'Dec':12}
# extracting t1 from first timestamp without -xxxx
t1 = datetime(int(tmp1[2]), dicto[tmp1[1]], int(tmp1[0]), int(tmp1[3][:2]),int(tmp1[3][3:5]), int(tmp1[3][6:]))
# extracting t1 from second timestamp without -xxxx
t2 = datetime(int(tmp2[2]), dicto[tmp2[1]], int(tmp2[0]), int(tmp2[3][:2]), int(tmp2[3][3:5]), int(tmp2[3][6:]))
# converting -xxxx of timestamp 1
t1_utc = int(tmp1[4][:3])*3600 + int(tmp1[4][3:])*60
# converting -xxxx of timestamp 2
t2_utc = int(tmp2[4][:3])*3600 + int(tmp2[4][3:])*60
# absolute difference
return abs(int((t1-t2).total_seconds()-(t1_utc-t2_utc)))
if __name__ == '__main__':
# fptr = open(os.environ['OUTPUT_PATH'], 'w')
t = int(input())
for t_itr in range(t):
tmp1 = list(input().split(' '))[1:]
tmp2 = list(input().split(' '))[1:]
delta = time_delta(tmp1, tmp2)
print(delta)
t1_utc = int(tmp1[4][:3])*3600 + int(tmp1[4][3:])*60
For a time zone like +0715, you correctly add “7 hours of seconds” and “15 minutes of seconds”
For a timezone like -0715, you are adding “-7 hours of seconds” and “+15 minutes of seconds”, resulting in -6h45m, instead of -7h15m.
You need to either use the same “sign” for both parts, or apply the sign afterwards.

DateTime Ruby How to format correctly

My project is supposed to fetch specific values from multiple hashes a put those values in a text file. Ideally what I need my code to do is to have every date for the employees be seven days apart, so the text file would look something like this:
"Rachel Thorndike
2017-10-09-T04:29:46-05:00
Stacie Smith
2017-10-16-T04:29:46-05:00"
What this is supposed to do is fetch employee's names and put the time of their "handoff" on the line under them. I looked online and found the DateTime that Ruby features but it looks like whatever I do isn't working. My code is this:
require 'date'
jsonUser["users"].each do |user|
somefile.puts user["user"]["summary"]
print 'Handoff Date + Time: '
parsed = DateTime.strptime(jsonUser["start"], '%d-%m-%Y %H:%M')
utc = parsed.next_day(7).strftime('%d-%m-%Y %H:%M')
puts utc
end
But terminal returns this code with an error 'strptime': invalid date (ArgumentError). Would anybody help me get this code to work the way I want to? Anything that points me to the right direction? With explanations, if it isn't too much.
Thank you so much!
Update
I was able to get the iso8601 to appear under their name. My new code is
require 'date'
jsonUser["users"].each do |user|
somefile.puts user["user"]["summary"]
print 'Handoff Date + Time: '
parsed = DateTime.iso8601(jsonUser["start"])
utc = parsed.next_day(7).iso8601
somefile.puts utc
end
BUT the .next_day method isn't increasing by 7 days that I want too. Thought? I have only got one value that is appearing and that is going under every line. Its the value of jsonUser["start"] + 7 days...so `2017-
10-16T04:29:46-05:00`
This is what parse.next_day(7) gives me.
"Sr Chid
Handoff Date + Time: 2017-10-16T04:29:46-05:00
Ash A
Handoff Date + Time: 2017-10-16T04:29:46-05:00
Ven D
Handoff Date + Time: 2017-10-16T04:29:46-05:00
Abhi S
Handoff Date + Time: 2017-10-16T04:29:46-05:00"
The value of jsonUser["start"] is 2017-10-09T04:29:46-05:00 so the good thing is that it did increase by 7 but it only did it once.
Update for Amadan
require 'date'
date = DateTime.iso8601(jsonUser["start"])
jsonUser["users"].each do |user|
if user["user"]["self"] == nil
nil
else
somefile.puts user["user"]["summary"].gsub(/\w+/, &:capitalize).gsub(/[.]/, ' ')
somefile.print 'Handoff Date + Time: '
date = date.next_day(7)
somefile.puts date.iso8061
end
end

Nicest way to turn "2015-03-18 22:00" into a Time object

I have three strings, pulled from a database:
"2015-03-18" (the date the event occurs)
"22:00" (the hour an event occurs)
"-05:00" (the UTC offset in the location the event occurs).
I want to combine these three strings to produce a Ruby Time object. I'm doing:
utc_offset = "-05:00"
airtime = "22:00"
airday = "2015-03-18"
year,month,day,hour,minutes = airday.split("-").map(&:to_i) + airtime.split(":").map(&:to_i)
Time.new(year,month,day,hour,minutes,0,utc_offset)
This works; I'm just wondering if it's the correct/standard/idiomatic/clearest way.
By using Time.parse
When ‘time’ is required, Time is extended with additional methods for
parsing and converting Times.
require 'time'
utc_offset = "-05:00"
airtime = "22:00"
airday = "2015-03-18"
time = Time.parse("#{airday} #{airtime} #{utc_offset}")
I think this is the way to do it.
Time.new(*airday.split("-"), *airtime.split(":"), 0, utc_offset)
How about this? http://ruby-doc.org/stdlib-2.1.5/libdoc/time/rdoc/Time.html#method-c-strptime
require 'time'
raw_time = '2015-03-18 22:00'
parsed_time = Time.strptime(raw_time, '%Y-%m-%d %H:%M') # 2015-03-18 22:00:00 +0100

Calculating the difference between durations with milliseconds in Ruby

TL;DR: I need to get the difference between HH:MM:SS.ms and HH:MM:SS.ms as HH:MM:SS:ms
What I need:
Here's a tricky one. I'm trying to calculate the difference between two timestamps such as the following:
In: 00:00:10.520
Out: 00:00:23.720
Should deliver:
Diff: 00:00:13.200
I thought I'd parse the times into actual Time objects and use the difference there. This works great in the previous case, and returns 00:0:13.200.
What doesn't work:
However, for some, this doesn't work right, as Ruby uses usec instead of msec:
In: 00:2:22.760
Out: 00:2:31.520
Diff: 00:0:8.999760
Obviously, the difference should be 00:00:8:760 and not 00:00:8.999760. I'm really tempted to just tdiff.usec.to_s.gsub('999','') ……
My code so far:
Here's my code so far (these are parsed from the input strings like "0:00:10:520").
tin_first, tin_second = ins.split(".")
tin_hours, tin_minutes, tin_seconds = tin_first.split(":")
tin_usec = tin_second * 1000
tin = Time.gm(0, 1, 1, tin_hours, tin_minutes, tin_seconds, tin_usec)
The same happens for tout. Then:
tdiff = Time.at(tout-tin)
For the output, I use:
"00:#{tdiff.min}:#{tdiff.sec}.#{tdiff.usec}"
Is there any faster way to do this? Remember, I just want to have the difference between two times. What am I missing?
I'm using Ruby 1.9.3p6 at the moment.
Using Time:
require 'time' # Needed for Time.parse
def time_diff(time1_str, time2_str)
t = Time.at( Time.parse(time2_str) - Time.parse(time1_str) )
(t - t.gmt_offset).strftime("%H:%M:%S.%L")
end
out_time = "00:00:24.240"
in_time = "00:00:14.520"
p time_diff(in_time, out_time)
#=> "00:00:09.720"
Here's a solution that doesn't rely on Time:
def slhck_diff( t1, t2 )
ms_to_time( time_as_ms(t2) - time_as_ms(t1) )
end
# Converts "00:2:22.760" to 142760
def time_as_ms( time_str )
re = /(\d+):(\d+):(\d+)(?:\.(\d+))?/
parts = time_str.match(re).to_a.map(&:to_i)
parts[4]+(parts[3]+(parts[2]+parts[1]*60)*60)*1000
end
# Converts 142760 to "00:02:22.760"
def ms_to_time(ms)
m = ms.floor / 60000
"%02i:%02i:%06.3f" % [ m/60, m%60, ms/1000.0 % 60 ]
end
t1 = "00:00:10.520"
t2 = "01:00:23.720"
p slhck_diff(t1,t2)
#=> "01:00:13.200"
t1 = "00:2:22.760"
t2 = "00:2:31.520"
p slhck_diff(t1,t2)
#=> "00:00:08.760"
I figured the following could work:
out_time = "00:00:24.240"
in_time = "00:00:14.520"
diff = Time.parse(out_time) - Time.parse(in_time)
Time.at(diff).strftime("%H:%M:%S.%L")
# => "01:00:09.720"
It does print 01 for the hour, which I don't really understand.
In the meantime, I used:
Time.at(diff).strftime("00:%M:%S.%L")
# => "00:00:09.720"
Any answer that does this better will get an upvote or the accept, of course.
in_time = "00:02:22.760"
out_time = "00:02:31.520"
diff = (Time.parse(out_time) - Time.parse(in_time))*1000
puts diff
OUTPUT:
8760.0 millliseconds
Time.parse(out_time) - Time.parse(in_time) gives the result in seconds so multiplied by 1000 to convert into milliseconds.

Date-time comparison in Ruby

I have one date, let's say '2010-12-20' of a flight departure, and two times, for instance, '23:30' and '02:15'.
The problem: I need to get datetimes (yyyy-MM-dd HH:mm:ss, for example, 2010-12-17 14:38:32) of both of these dates, but I don't know the day of the second time (it can be the same day as departure, or the next one).
I am looking for the best solution in Ruby on Rails. In PHP would just use string splitting multiple times, but I believe, that Rails as usually, has a much more elegant way.
So, here is my pseudo code, which I want to turn into Ruby:
depart_time = '23:30'
arrive_time = '02:15'
depart_date = '2010-12-20'
arrive_date = (arrive.hour < depart.hour and arrive.hour < 5) ? depart_date + 1 : depart_date
# Final results
depart = depart_date + ' ' + depart_time
arrive = arrive_date + ' ' + arrive_time
I want to find the best way to implement this in Ruby on Rails, instead of just playing with strings.
This is just pure Ruby, nothing to do with Rails:
require 'date'
depart_time = DateTime.strptime '23:30', '%H:%M'
arrive_time = DateTime.strptime '02:15', '%H:%M'
arrive_date = depart_date = Date.parse( '2010-12-20' )
arrive_date += 1 if arrive_time.hour < depart_time.hour and arrive_time.hour < 5
puts "#{depart_date} #{depart_time.strftime '%H:%M'}",
"#{arrive_date} #{arrive_time.strftime '%H:%M'}"
#=> 2010-12-20 23:30
#=> 2010-12-21 02:15

Resources