Last active
December 14, 2015 17:19
-
-
Save djibouti33/5121436 to your computer and use it in GitHub Desktop.
solution to convert place hours of operation from google place details api to a human readable format.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# the data we get from google looks like: | |
# - close: | |
# day: 0 | |
# time: '1700' | |
# open: | |
# day: 0 | |
# time: '1000' | |
# - close: | |
# day: 3 | |
# time: '1700' | |
# open: | |
# day: 3 | |
# time: '1000' | |
# - close: | |
# day: 4 | |
# time: '1700' | |
# open: | |
# day: 4 | |
# time: '1000' | |
# - close: | |
# day: 5 | |
# time: '1700' | |
# open: | |
# day: 5 | |
# time: '1000' | |
# - close: | |
# day: 6 | |
# time: '1700' | |
# open: | |
# day: 6 | |
# time: '1000' | |
# and we need to be able to display it as: | |
# Wed-Sun : 10am - 5pm | |
# - or - | |
# Mon,Wed,Fri : 8am - 7pm | |
# Tue,Thur : 10am - 11pm | |
# - or - | |
# Mon - Fri : 10am - 2pm, 4pm - 8pm | |
# easiest way to test this is to load the functions below into a rails console, then copy and paste the one of the following: | |
# helper.operating_hours({"periods" => [{"close" => {"day" => 0,"time" => "1700"},"open" => {"day" => 0,"time" => "1000"}},{"close" => {"day" => 3,"time" => "1700"},"open" => {"day" => 3,"time" => "1000"}},{"close" => {"day" => 4,"time" => "1700"},"open" => {"day" => 4,"time" => "1000"}},{"close" => {"day" => 5,"time" => "1700"},"open" => {"day" => 5,"time" => "1000"}},{"close" => {"day" => 6,"time" => "1700"},"open" => {"day" => 6,"time" => "1000"}}]}["periods"]) | |
# helper.operating_hours({"periods" => [{"close" => {"day" => 0,"time" => "1700"},"open" => {"day" => 0,"time" => "1000"}},{"close" => {"day" => 2,"time" => "1700"},"open" => {"day" => 2,"time" => "1000"}},{"close" => {"day" => 4,"time" => "1700"},"open" => {"day" => 4,"time" => "1000"}},{"close" => {"day" => 5,"time" => "1700"},"open" => {"day" => 5,"time" => "1000"}},{"close" => {"day" => 6,"time" => "1700"},"open" => {"day" => 6,"time" => "1000"}}]}["periods"]) | |
# helper.operating_hours({"periods" => [{"close" => {"day" => 0,"time" => "1700"},"open" => {"day" => 0,"time" => "1000"}},{"close" => {"day" => 2,"time" => "1700"},"open" => {"day" => 2,"time" => "1000"}},{"close" => {"day" => 4,"time" => "1915"},"open" => {"day" => 4,"time" => "1000"}},{"close" => {"day" => 5,"time" => "1700"},"open" => {"day" => 5,"time" => "1000"}},{"close" => {"day" => 6,"time" => "1700"},"open" => {"day" => 6,"time" => "1000"}}]}["periods"]) | |
# helper.operating_hours({"periods" => [{"close" => {"day" => 0,"time" => "1700"},"open" => {"day" => 0,"time" => "1000"}},{"close" => {"day" => 2,"time" => "1700"},"open" => {"day" => 2,"time" => "1000"}},{"close" => {"day" => 4,"time" => "1915"},"open" => {"day" => 4,"time" => "1000"}},{"close" => {"day" => 5,"time" => "1700"},"open" => {"day" => 5,"time" => "1000"}}]}["periods"]) | |
# helper.operating_hours({"periods" => [{"close" => {"day" => 0,"time" => "1700"},"open" => {"day" => 0,"time" => "1000"}},{"close" => {"day" => 1,"time" => "1700"},"open" => {"day" => 1,"time" => "1000"}},{"close" => {"day" => 4,"time" => "1700"},"open" => {"day" => 4,"time" => "1000"}},{"close" => {"day" => 5,"time" => "1700"},"open" => {"day" => 5,"time" => "1000"}}]}["periods"]) | |
# helper.operating_hours({"periods" => [{"close" => {"day" => 0,"time" => "1400"},"open" => {"day" => 0,"time" => "1000"}},{"close" => {"day" => 0,"time" => "1900"},"open" => {"day" => 0,"time" => "1700"}},{"close" => {"day" => 1,"time" => "1400"},"open" => {"day" => 1,"time" => "1000"}},{"close" => {"day" => 1,"time" => "1900"},"open" => {"day" => 1,"time" => "1700"}},{"close" => {"day" => 2,"time" => "1400"},"open" => {"day" => 2,"time" => "1000"}},{"close" => {"day" => 2,"time" => "1900"},"open" => {"day" => 2,"time" => "1700"}},{"close" => {"day" => 3,"time" => "1400"},"open" => {"day" => 3,"time" => "1000"}},{"close" => {"day" => 3,"time" => "1900"},"open" => {"day" => 3,"time" => "1700"}},{"close" => {"day" => 4,"time" => "1400"},"open" => {"day" => 4,"time" => "1000"}},{"close" => {"day" => 4,"time" => "1900"},"open" => {"day" => 4,"time" => "1700"}},{"close" => {"day" => 5,"time" => "1400"},"open" => {"day" => 5,"time" => "1000"}},{"close" => {"day" => 5,"time" => "1900"},"open" => {"day" => 5,"time" => "1700"}},{"close" => {"day" => 6,"time" => "1400"},"open" => {"day" => 6,"time" => "1000"}},{"close" => {"day" => 6,"time" => "1900"},"open" => {"day" => 6,"time" => "1700"}}]}["periods"]) | |
# convert place hours data from google into a displayable format | |
# [{"close" => {"day" => 0,"time" => "1700"},"open" => {"day" => 0,"time" => "1000"}}] = { "Sun" => "10am - 5pm"} | |
def operating_hours(periods) | |
# group similar periods together in a hash | |
# key = formatted time (open - close) | |
# value = array of days (as digits) | |
hours_of_op = periods.inject({}) { |memo, period| | |
time = format_time(period) | |
(memo[time] ||= []) << period["open"]["day"]; memo | |
} | |
# now that our hash's values are an array of day digits, | |
# convert that array into a readable string | |
hours_of_op = hours_of_op.reduce({}) { |memo, (key, value)| | |
memo[key] = format_days(value); memo | |
} | |
# displaying the data will be grouped by similar days, then hours. | |
# right now, our data strucutre is organized by the hours, so we need | |
# to do an invert/combine while ensuring we preserve each time span. | |
# this is primarily for those hours of operations that have breaks | |
# (i.e. siestas). as our structure is now, we'd have to say: | |
# Mon - Fri : 10, 2, Mon - Fri : 4 - 8. | |
# with this invert/combine, we'll be able to say: | |
# Mon - Fri : 10-2, 4-8. | |
hours_of_op = hours_of_op.reduce({}) { |memo,(key,value)| | |
(memo[value] ||=[]) << key; memo | |
}.reduce({}) { |memo, (key,value)| | |
memo[key] = value.join(', '); memo | |
} | |
end | |
# convert 24h span ( 1000 - 1700 ) to 12h span ( 10am - 5pm ) | |
def format_time(val) | |
[val["open"]["time"], val["close"]["time"]].inject([]) { |memo, time| | |
memo << Time.strptime(time, "%H%M").strftime("%l:%M%P").gsub(/:00/, '').strip | |
memo | |
}.join(' - ') | |
end | |
# take day digits and turn them into day words, | |
# while combining consecutive days into spans, | |
def format_days(open_days) | |
days_array = %w[Sun Mon Tue Wed Thur Fri Sat] | |
# group by consecutive days | |
prev = open_days[0] | |
consecutive_groups = open_days.slice_before { |cur| | |
prev, prev2 = cur, prev | |
prev2 + 1 != prev | |
}.to_a | |
# if a place is closed in the middle of the week, but open on sunday and saturday, | |
# bring the sunday group around to the last group | |
# so instead of "Sun, Mon, Wed-Sat", you'll have "Wed-Mon" | |
if consecutive_groups.length > 1 and consecutive_groups.first.first == 0 and consecutive_groups.last.last == 6 | |
consecutive_groups.last.concat(consecutive_groups.delete(consecutive_groups.first)) | |
end | |
# convert day digits into day words, creating spans where appropriate | |
consecutive_groups.map! { |range| | |
range.map! { |parts| days_array[parts] } | |
range.length <= 2 ? range.join(', ') : "#{range.first} - #{range.last}" | |
}.join(', ') | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment