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"}
]
end
TimeMachinex 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.SystemClock
and the ManagedClock in the :test
env:
config :time_machinex, TimeMachinex, adapter: TimeMachinex.ManagedClock
Whenever 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!