I am quite new to Elixir.
I am working on a Phoenix/LiveView application that has a App.Utils.DateHelper
module as part of its App.Utils
that contains a bunch of functions like:
def today do
Date.utc_today()
end
def yesterday do
Date.utc_today() |> Timex.shift(days: -1)
end
....
I need to modify each of these functions and shift their returned value by some constant that depends on the user’s timezone.
I know how to fetch the user’s timezone front the front-end (e.g., on app.js
), and how to resurface it in views, especially using get_connect_params
(Fundamentals of passing data from the Plug connection to the LiveView - #2 by josevalim).
But I’d like to avoid having to add a “shift” parameters to each of these functions. That is, instead of something like
def today(shift) do
Date.utc_today() |> Timex.shift(hours: -shift)
end
def yesterday(shift) do
Date.utc_today() |> Timex.shift(days: -1) |> Timex.shift(hours: -shift)
end
....
I’d like to be able to import those functions into views directly with the proper shift parameter included:
def today do
Date.utc_today() |> Timex.shift(hours: -shift)
end
def yesterday do
Date.utc_today() |> Timex.shift(days: -1) |> Timex.shift(hours: -shift)
end
....
In the best of worlds, the shift
parameter would be fetched and all the functions would be adjusted before the module is imported or aliased into a view. But I don’t think there is a way to surface the value of that parameter all the way from the front end to the defmodule
definition itself?
Alternatively, I’d be ok with having to initialize it through something like a create_date_helper(shift)
function at the top of each view where I need the date helpers.
I’ve tried to hack into macros, but can’t quite wrap my head around them and understand how they would apply here.
defmacro date_helper_creator(shift) do quote do def today do Date.utc_today() |> Timex.shift(hours: -unquote(shift)) end def yesterday do Date.utc_today() |> Timex.shift(days: -1) |> Timex.shift(hours: -unquote(shift)) end end end
does not seem to work.
Any suggestions on how I could achieve this?