If available in Hex, the package can be installed
by adding time_machinex to your list of dependencies in mix.exs:
def deps do
[
{:time_machinex, "~> 0.3.0"}
]
endTimeMachinex is just a managed clock around the system clock which works with DateTime.t() types.
Configuring TimeMachine is very simple. What you generally want to do is to configure the SystemClock for :prod and :dev env:
config :time_machinex, TimeMachinex, adapter: TimeMachinex.SystemClockand the ManagedClock in the :test env:
config :time_machinex, TimeMachinex, adapter: TimeMachinex.ManagedClockWhenever you need the current system time just replace the standard DateTime.utc_now/0 call with a TimeMachinex.utc_now/0 or TimeMachinex.utc_now/1 call.
Please note that utc_now returns an UTCDateTime type. (Please use now/0 and now/1 if you need a standard DateTime)
In :prod and :dev this will have no real side effects, since the now/0 function is just an alias for the DateTime.utc_now/0 thanks to the inline compilation attribute.
The magic happens in the :test environment since the TimeMachinex.ManagedClock adapter will kick in (if configured properly).
The only thing you need to do in your tests is to start the ManagedClock:
ex(1)> TimeMachinex.ManagedClock.start()
{:ok, #PID<0.190.0>}
when it starts it is configured with the current time:
iex(2)> TimeMachinex.ManagedClock.utc_now()
~Z[2019-12-16 14:34:32.623987]
but now all the calls to TimeMachinex.utc_now/0 will read the time from the ManagedClock
iex(3)> TimeMachinex.utc_now()
~Z[2019-12-16 14:34:32.623987]
which means that you can manipulate, simulate the time passing and test the time used in your production code.
And yes, you stopped the time!
iex(4)> TimeMachinex.utc_now()
~Z[2019-12-16 14:34:32.623987]
iex(5)> TimeMachinex.utc_now()
~Z[2019-12-16 14:34:32.623987]
If you want to update the TimeMachinex with the current time again (to simulate time passing) you can just:
iex(7)> TimeMachinex.ManagedClock.set()
:ok
iex(8)> TimeMachinex.utc_now()
~Z[2019-12-16 14:38:04.255975]
or you may just want to set a specific time and wait for Marty McFly:
iex(9)> ~N[1985-10-26 09:00:00] |> DateTime.from_naive!("Etc/UTC") |> TimeMachinex.ManagedClock.set()
:ok
iex(10)> TimeMachinex.utc_now()
~Z[1985-10-26 09:00:00]
Happy time travel!