Home > Software engineering >  How to create array with hours in ruby
How to create array with hours in ruby

Time:09-28

I need to create the following Array:

array_time = [00:00:00, 00:00:01, ..., 23:59:59]

Is there a way to generate this type of hash with all hours of the day in ruby?

Because then I will need to create the following Hash:

hash = { "time" => { "'00:00:00'" => "23:59:59" } }

And I would like to check if the sub-Hash under key "time" uses keys in the correct format, for example:

hash["time"].each do |key|
  array_time.includes key
end

CodePudding user response:

Assuming that you're happy with Strings, this is a simple way to do it:

array_time = ("00".."23").flat_map do |h|
  ("00".."59").flat_map do |m|
    ("00".."59").map do |s|
      "#{h}:#{m}:#{s}"
    end
  end
end

array_time.length
# => 86400

array_time.first(5)
# => ["00:00:00", "00:00:01", "00:00:02", "00:00:03", "00:00:04"]

array_time.last(5)
#=> ["23:59:55", "23:59:56", "23:59:57", "23:59:58", "23:59:59"]

However, if your goal is:

and I would like to check if the hash time is in the correct format, example:

hash["time"].each do |key|
  array_time.include? key
end

Then that's really not the most efficient way to go about it.

First off, Hash lookups are much faster than Array#include?, so you really want to use a Hash and treat it a Set:

time_set = Hash[
  ("00".."23").flat_map do |h|
    ("00".."59").flat_map do |m|
      ("00".."59").map do |s|
        ["#{h}:#{m}:#{s}", true]
      end
    end
  end
]

time_set
# => {"00:00:00"=>true,
#  "00:00:01"=>true,
#  "00:00:02"=>true,
#  ...
#  "23:59:58"=>true,
#  "23:59:59"=>true}

And then perform your lookups like this:

hash[:time].each do |time_str|
  time_set[time_str]
end

But even this is not great. Not always at least.

If you know you need to perform this check very often, with arbitrary values, and with a lot of values to check, then yes, pre-computing the lookup set once and storing it in a constant could make sense. So you'd use TIME_SET = ... instead of time_set = ....

But if this is performed sporadically, you're just much better off validating the time strings one by one. For example:

TIME_REGEX = %r{^([01][0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9]$}.freeze

hash[:time].each do |time_str|
  TIME_REGEX === time_str
end

CodePudding user response:

Assuming an array of strings is acceptable, here is one way to do it.

time_iterator = Time.at(1_500_076_800) # 2017-07-15 00:00:00  0000
end_time      = time_iterator   1.day
array_time    = []
while time_iterator < end_time
  array_time << time_iterator.strftime('%T')
  time_iterator  = 1.second
end

Apparently in Ruby 1.9 they removed the ability to step-iterate over a time range, so a while loop seems to be preferred now.

I do think that if you're just trying to validate the format of a time-like string (HH:MM:SS) then there are much better ways to accomplish this. A simple RegEx would do it, or something similar.

  • Related