README.md
1## Timex Plugin for Ecto
2
3[![Master](https://travis-ci.org/bitwalker/timex_ecto.svg?branch=master)](https://travis-ci.org/bitwalker/timex_ecto)
4[![Hex.pm Version](http://img.shields.io/hexpm/v/timex_ecto.svg?style=flat)](https://hex.pm/packages/timex_ecto)
5
6## Getting Started
7
8Learn how to add `timex_ecto` to your Elixir project and start using it.
9
10**NOTE**: You must use Timex 3.0.2 or greater with timex_ecto 3.x!
11
12### Adding timex_ecto To Your Project
13
14To use timex_ecto with your projects, edit your `mix.exs` file and add it as a dependency:
15
16```elixir
17def application do
18 [ applications: [:timex_ecto, ...], ...]
19end
20
21defp deps do
22 [{:timex, "~> 3.0"},
23 {:timex_ecto, "~> 3.0"}]
24end
25```
26
27### Adding Timex types to your Ecto models
28
29```elixir
30defmodule User do
31 use Ecto.Schema
32
33 schema "users" do
34 field :name, :string
35 # Stored as an ISO date (year-month-day), reified as Date
36 field :a_date, Timex.Ecto.Date # Timex version of :date
37 # Stored as an ISO time (hour:minute:second.fractional), reified as Timex.Duration
38 field :a_time, Timex.Ecto.Time # Timex version of :time
39 # Stored as an ISO 8601 datetime in UTC (year-month-day hour:minute:second.fractional),
40 # reified as DateTime in UTC
41 field :a_datetime, Timex.Ecto.DateTime # Timex version of :datetime
42 # DateTimeWithTimezone is a special case, please see the `Using DateTimeWithTimezone` section!
43 # Stored as a tuple of ISO 8601 datetime and timezone name ((year-month-day hour:minute:second.fractional, timezone)),
44 # reified as DateTime in stored timezone
45 field :a_datetimetz, Timex.Ecto.DateTimeWithTimezone # A custom datatype (:datetimetz) implemented by Timex
46 # Stored as an ISO 8601 datetime in UTC (year-month-day hour:minute:second.fractional),
47 # reified as DateTime in local timezone
48 field :a_timestamptz, Timex.Ecto.TimestampWithTimezone # Timex version of :timestamptz
49 end
50end
51```
52
53## Using DateTimeWithTimezone
54
55Please see the documentation [here](https://hexdocs.pm/timex_ecto/Timex.Ecto.DateTimeWithTimezone.html#content).
56
57### Change the default timestamps type of Ecto's `timestamps` macro
58
59According to the documentation for [Ecto.Schema.timestamps/1](https://hexdocs.pm/ecto/Ecto.Schema.html#timestamps/1), it is simple to change the default timestamps type to others by setting `@timestamps_opts`. For example, you can use `Timex.Ecto.TimestampWithTimezone` with the following options.
60
61```elixir
62defmodule User do
63 use Ecto.Schema
64
65 @timestamps_opts [type: Timex.Ecto.TimestampWithTimezone,
66 autogenerate: {Timex.Ecto.TimestampWithTimezone, :autogenerate, []}]
67
68 schema "users" do
69 field :name, :string
70 timestamps()
71 end
72end
73```
74
75### Using Timex with Ecto's `timestamps` macro
76
77Super simple! Your timestamps will now be `Timex.Ecto.DateTime` structs instead of `Ecto.DateTime` structs.
78
79```elixir
80defmodule User do
81 use Ecto.Schema
82
83 @timestamps_opts [type: Timex.Ecto.DateTime]
84
85 schema "users" do
86 field :name, :string
87 timestamps()
88 end
89end
90```
91
92### Using with Phoenix
93
94Phoenix allows you to apply defaults globally to Ecto models via `web/web.ex` by changing the `model` function like so:
95
96```elixir
97def model do
98 quote do
99 use Ecto.Schema
100
101 @timestamps_opts [type: Timex.Ecto.DateTime]
102 end
103end
104```
105
106By doing this, you bring the Timex timestamps into scope in all your models.
107
108
109### Precision
110
111By default Timex will generate a timestamp to the nearest second. If you would
112like to generate a timestamp with more precision you can pass the option
113`usec: true` to the macro. This will configure Timex to generate timestamps
114down to the microsecond level of precision.
115
116```elixir
117@timestamps_opts [type: Timex.Ecto.DateTime,
118 autogenerate: {Timex.Ecto.DateTime, :autogenerate, [:usec]}]
119```
120
121
122## Example Usage
123
124The following is a simple test app I built for vetting this plugin:
125
126```elixir
127defmodule EctoTest.Repo do
128 use Ecto.Repo, otp_app: :timex_ecto_test
129end
130
131defmodule EctoTest.User do
132 use Ecto.Schema
133
134 @timestamps_opts [type: Timex.Ecto.DateTime,
135 autogenerate: {Timex.Ecto.DateTime, :autogenerate, []}]
136
137 schema "users" do
138 field :name, :string
139 field :date_test, Timex.Ecto.Date
140 field :time_test, Timex.Ecto.Time
141 field :datetime_test, Timex.Ecto.DateTime
142 field :datetimetz_test, Timex.Ecto.DateTimeWithTimezone
143 field :timestamptz_test, Timex.Ecto.TimestampWithTimezone
144
145 timestamps()
146 end
147end
148
149defmodule EctoTest do
150 import Ecto.Query
151 use Timex
152
153 alias EctoTest.User
154 alias EctoTest.Repo
155
156 def seed do
157 time = Duration.now
158 date = Timex.today
159 datetime = Timex.now
160 datetimetz = Timezone.convert(datetime, "Europe/Copenhagen")
161 timestamptz = Timex.local
162 u = %User{name: "Paul", date_test: date, time_test: time, datetime_test: datetime, datetimetz_test: datetimetz, timestamptz_test: timestamptz}
163 Repo.insert!(u)
164 end
165
166 def all do
167 query = from u in User,
168 select: u
169 Repo.all(query)
170 end
171end
172
173defmodule EctoTest.App do
174 use Application
175
176 def start(_type, _args) do
177 import Supervisor.Spec
178 tree = [worker(EctoTest.Repo, [])]
179 opts = [name: EctoTest.Sup, strategy: :one_for_one]
180 Supervisor.start_link(tree, opts)
181 end
182end
183```
184
185And the results:
186
187```elixir
188iex(1)> EctoTest.seed
189
19014:45:43.461 [debug] INSERT INTO "users" ("date_test", "datetime_test", "datetimetz_test", "name", "time_test") VALUES ($1, $2, $3, $4, $5) RETURNING "id" [{2015, 6, 25}, {{2015, 6, 25}, {19, 45, 43, 457000}}, {{{2015, 6, 25}, {21, 45, 43, 457000}}, "Europe/Copenhagen"}, "Paul", {19, 45, 43, 457000}] OK query=3.9ms
191%EctoTest.User{__meta__: %Ecto.Schema.Metadata{source: "users",
192 state: :loaded},
193 date_test: ~D[2015-06-25],
194 datetime_test: #<DateTime(2015-06-25T21:45:43.457Z Etc/UTC)>,
195 datetimetz_test: #<DateTime(2015-06-25T21:45:43.457+02:00 Europe/Copenhagen)>,
196 timestamptz_test: #<DateTime(2015-06-25T13:45:43.457-06:00 America/Chicago)>,
197 name: "Paul", time_test: #<Duration(P45Y6M6DT19H45M43.456856S)>}
198iex(2)> EctoTest.all
199
20014:45:46.721 [debug] SELECT u0."id", u0."name", u0."date_test", u0."time_test", u0."datetime_test", u0."datetimetz_test" FROM "users" AS u0 [] OK query=0.7ms
201[%EctoTest.User{__meta__: %Ecto.Schema.Metadata{source: "users",
202 state: :loaded},
203 date_test: ~D[2015-06-25],
204 datetime_test: #<DateTime(2015-06-25T21:45:43.457Z Etc/UTC)>,
205 datetimetz_test: #<DateTime(2015-06-25T21:45:43.457+02:00 Europe/Copenhagen)>,
206 timestamptz_test: #<DateTime(2015-06-25T13:45:43.457-06:00 America/Chicago)>,
207 name: "Paul", time_test: #<Duration(PT19H45M43S)>}]
208iex(3)>
209```
210
211## Additional Documentation
212
213Documentation for Timex and timex_ecto are available
214[here], and on [hexdocs].
215
216[here]: https://hexdocs.pm/timex
217[hexdocs]: http://hexdocs.pm/timex_ecto/
218
219## License
220
221This project is MIT licensed. See the LICENSE file in this repo.
222