Create date and time from separate strings
You can combine a date and a time like this:
date = '2014-07-09'
time = '9:30am'
DateTime.parse([ date, time ].join(' '))
# => Wed, 09 Jul 2014 09:30:00 +0000
I've got my local time-zone in Rails set to UTC.
Ruby merge time and date to datetime
You can construct a new DateTime using DateTime.new
and passing the single date components such as year and month.
class Product < AR::Base
MANUFACTURE_TIME = '08:00'
def manufactured_at
hour, minute = MANUFACTURE_TIME.split(':')
DateTime.new(manufacture_date.year, manufacture_date.month, manufacture_date.day, hour, minute)
end
end
You can store the time as you want, even in a array if you don't want to decompose it later using split
.
Union arrays of date time object
Here's one solution:
parse = ->(r) { DateTime.parse(r[:start])..DateTime.parse(r[:end]) }
ranges = list1.map(&parse) + list2.map(&parse)
merged = ranges.sort_by(&:begin).reduce([]) do |acc, range|
if acc.any? && acc.last.cover?(range.begin)
last = acc.pop
acc.push last.begin..range.end
else
acc.push range
end
acc
end
Your solution doesn't "merge" the time ranges, because it just sorts the list of times by ascending distance between start times. This will obviously not produce any useful merging of times!
I'm using Ruby's Range construct to create a time range from each start/end pair, then I sort all the ranges by their beginning time, then reduce the list of individual ranges with the algorithm:
if the current range covers the next range's start date:
extend the current range to the next range's end date
else
add the next range into the return list
It's worth noting that I'm just merging all the ranges via any intersections; there's no need to split them into two lists, because if there is an overlapping range in one list or the other, they would union together anyhow.
You don't have to use ranges, but they map onto this concept cleanly, and you can then use them to produce intervals or whatever you're looking to do.
Edit: As Cary pointed out, if the data contains an inverted range, the results get a little funky. Here's an alternate parsing scheme which addresses that issue:
ranges = [list1, list2].flatten.map(&:values).map do |v|
Range.new *v.map {|d| DateTime.parse d}.sort.take(2)
end
Related Topics
Converting from Xml Name-Values into Simple Hash
Array of Indexes to Array of Ranges
Trying to Install Ruby-Filemagic on Snow Leopard Using Brew Rather Than Ports
Rails: Encoding Woes with Serialized Hashes Despite Utf8
Net::Ssh Sudo Command Hangs After Entering Password
Sort a Collection of Objects by Number (Highest First) Then by Letter (Alphabetical)
How to Read Whole File in Ruby
Regex, How to Match Multiple Lines
How to Check If a Ruby Array Includes One of Several Values
How Is Each_With_Object Supposed to Work
Putting the Results of Pp (Or Anything Outputted to Console) into a String
HTML Code Inside Buttons with Simple_Form
Ruby - Digest::Digest Is Deprecated; Use Digest