Skip to content

Instantly share code, notes, and snippets.

@speeddragon
Last active November 13, 2018 15:17
Show Gist options
  • Save speeddragon/f5afb7244c874ff7284574a24cadebb6 to your computer and use it in GitHub Desktop.
Save speeddragon/f5afb7244c874ff7284574a24cadebb6 to your computer and use it in GitHub Desktop.
Restaurant Scheduler - Elixir
# Structure
# schema "restaurant_schedule" do
# field(:from_weekday, :integer)
# field(:to_weekday, :integer)
#
# field(:open_time, :time)
# field(:close_time, :time)
# timestamps()
# belongs_to(:restaurant, Restaurant)
# end
# Query which is open
defp inside_schedule(query, time_now) do
current_time = %Time{(time_now |> DateTime.to_time()) | microsecond: {0, 0}}
current_weekday = Helper.RestaurantSchedule.get_weekday(time_now)
tomorrow_weekday = Helper.RestaurantSchedule.next_week_day(current_weekday)
# -- weekday: 3, time: 00:23:00
# SELECT *
# FROM restaurant_schedule
# WHERE restaurant_id = 24 AND (
# (from_weekday < to_weekday AND from_weekday <= 3 AND to_weekday >= 3 AND (
# (open_time < close_time AND open_time <= '00:23:00' AND close_time >= '00:23:00') OR
# (close_time < open_time AND open_time <= '00:23:00' AND '23:59:59' >= '00:23:00'))
# ) OR
# -- from_weekday: 1 | to_weekday: 0
# (from_weekday > to_weekday AND ((to_weekday <= 3 AND 6 >= 3) OR (0 <= 3 AND from_weekday >= 3)) AND (
# (open_time < close_time AND open_time <= '00:23:00' AND close_time >= '00:23:00') OR
# (close_time < open_time AND open_time <= '00:23:00' AND '23:59:59' >= '00:23:00'))
# ) OR
# -- Special case, after midnight should be +1 when close_time < open_time
# (from_weekday < to_weekday AND from_weekday <= 3+1 AND to_weekday >= 3+1 AND
# (close_time < open_time AND '00:00:00' <= '00:23:00' AND close_time >= '00:23:00')
# ) OR
# (from_weekday > to_weekday AND ((to_weekday <= 3+1 AND 6 >= 3+1) OR (0 <= 3+1 AND from_weekday >= 3+1)) AND
# (close_time < open_time AND '00:00:00' <= '00:23:00' AND close_time >= '00:23:00')
# )
# )
query
|> where(
[rs],
# from_weekday: 1 | to_weekday: 0
# Special case, after midnight should be +1 when rs.close_time < rs.open_time
(rs.from_weekday < rs.to_weekday and rs.from_weekday <= ^current_weekday and
rs.to_weekday >= ^current_weekday and
((rs.open_time < rs.close_time and rs.open_time <= ^current_time and
rs.close_time >= ^current_time) or
(rs.close_time < rs.open_time and rs.open_time <= ^current_time and
type(^~T[23:59:59], :time) >= ^current_time))) or
(rs.from_weekday > rs.to_weekday and
((rs.to_weekday <= ^current_weekday and 6 >= ^current_weekday) or
(0 <= ^current_weekday and rs.from_weekday >= ^current_weekday)) and
((rs.open_time < rs.close_time and rs.open_time <= ^current_time and
rs.close_time >= ^current_time) or
(rs.close_time < rs.open_time and rs.open_time <= ^current_time and
type(^~T[23:59:59], :time) >= ^current_time))) or
(rs.from_weekday < rs.to_weekday and rs.from_weekday <= ^tomorrow_weekday and
rs.to_weekday >= ^tomorrow_weekday and
(rs.close_time < rs.open_time and type(^~T[00:00:00], :time) <= ^current_time and
rs.close_time >= ^current_time)) or
(rs.from_weekday > rs.to_weekday and
((rs.to_weekday <= ^tomorrow_weekday and 6 >= ^tomorrow_weekday) or
(0 <= ^tomorrow_weekday and rs.from_weekday >= ^tomorrow_weekday)) and
(rs.close_time < rs.open_time and type(^~T[00:00:00], :time) <= ^current_time and
rs.close_time >= ^current_time))
)
end
# Query which is close
defp outside_schedule(query, time_now) do
current_time = %Time{(time_now |> DateTime.to_time()) | microsecond: {0, 0}}
current_weekday = Helper.RestaurantSchedule.get_weekday(time_now)
tomorrow_weekday = Helper.RestaurantSchedule.next_week_day(current_weekday)
query
|> where(
[rs],
# from_weekday: 1 | to_weekday: 0
# Special case, after midnight should be +1 when rs.close_time < rs.open_time
not ((rs.from_weekday < rs.to_weekday and rs.from_weekday <= ^current_weekday and
rs.to_weekday >= ^current_weekday and
((rs.open_time < rs.close_time and rs.open_time <= ^current_time and
rs.close_time >= ^current_time) or
(rs.close_time < rs.open_time and rs.open_time <= ^current_time and
type(^~T[23:59:59], :time) >= ^current_time))) or
(rs.from_weekday > rs.to_weekday and
((rs.to_weekday <= ^current_weekday and 6 >= ^current_weekday) or
(0 <= ^current_weekday and rs.from_weekday >= ^current_weekday)) and
((rs.open_time < rs.close_time and rs.open_time <= ^current_time and
rs.close_time >= ^current_time) or
(rs.close_time < rs.open_time and rs.open_time <= ^current_time and
type(^~T[23:59:59], :time) >= ^current_time))) or
(rs.from_weekday < rs.to_weekday and rs.from_weekday <= ^tomorrow_weekday and
rs.to_weekday >= ^tomorrow_weekday and
(rs.close_time < rs.open_time and type(^~T[00:00:00], :time) <= ^current_time and
rs.close_time >= ^current_time)) or
(rs.from_weekday > rs.to_weekday and
((rs.to_weekday <= ^tomorrow_weekday and 6 >= ^tomorrow_weekday) or
(0 <= ^tomorrow_weekday and rs.from_weekday >= ^tomorrow_weekday)) and
(rs.close_time < rs.open_time and type(^~T[00:00:00], :time) <= ^current_time and
rs.close_time >= ^current_time)))
)
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment