Skip to content

Commit 90e9097

Browse files
authored
"Confinement" de la librairie Timex (#4385)
* Extract iso-extended parsing to a central place * Add TODO * Add wrapper for "{YYYY}{0M}{0D}" * Add TODO * Move test calls * Wrap now() and shift() * Wrap Timex conversion calls * Add doctest wrapper * Add note * Fix credo warnings * Add doc * Update time_wrapper.ex * Forbid direct use of Timex
1 parent c1258dd commit 90e9097

File tree

8 files changed

+70
-16
lines changed

8 files changed

+70
-16
lines changed

.credo.exs

+6-1
Original file line numberDiff line numberDiff line change
@@ -129,10 +129,15 @@
129129

130130
# Deprecated checks (these will be deleted after a grace period)
131131
#
132-
{Credo.Check.Readability.Specs, false}
132+
{Credo.Check.Readability.Specs, false},
133133

134134
# Custom checks can be created using `mix credo.gen.check`.
135135
#
136+
137+
{Credo.Check.Warning.ForbiddenModule,
138+
[
139+
modules: [Timex]
140+
]}
136141
]
137142
}
138143
]

apps/shared/lib/date_time_display.ex

+5-8
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ defmodule Shared.DateTimeDisplay do
3434
def format_date(nil, _), do: ""
3535

3636
def format_date(date, locale, iso_extended: true) do
37-
date |> Timex.parse!("{ISO:Extended}") |> format_date(locale)
37+
date |> TimeWrapper.parse!("{ISO:Extended}") |> format_date(locale)
3838
end
3939

4040
@doc """
@@ -100,7 +100,7 @@ defmodule Shared.DateTimeDisplay do
100100

101101
def format_datetime_to_paris(datetime, locale, options) when is_binary(datetime) do
102102
datetime
103-
|> Timex.parse!("{ISO:Extended}")
103+
|> TimeWrapper.parse!("{ISO:Extended}")
104104
|> format_datetime_to_paris(locale, options)
105105
end
106106

@@ -157,7 +157,7 @@ defmodule Shared.DateTimeDisplay do
157157

158158
def format_time_to_paris(datetime, locale, options) when is_binary(datetime) do
159159
datetime
160-
|> Timex.parse!("{ISO:Extended}")
160+
|> TimeWrapper.parse!("{ISO:Extended}")
161161
|> format_time_to_paris(locale, options)
162162
end
163163

@@ -225,14 +225,11 @@ defmodule Shared.DateTimeDisplay do
225225

226226
@spec convert_to_paris_time(DateTime.t() | NaiveDateTime.t()) :: DateTime.t()
227227
def convert_to_paris_time(%DateTime{} = dt) do
228-
case Timex.Timezone.convert(dt, "Europe/Paris") do
229-
%Timex.AmbiguousDateTime{after: dt} -> dt
230-
%DateTime{} = dt -> dt
231-
end
228+
TimeWrapper.convert_to_paris_time(dt)
232229
end
233230

234231
def convert_to_paris_time(%NaiveDateTime{} = ndt) do
235-
ndt |> Timex.Timezone.convert("UTC") |> convert_to_paris_time()
232+
ndt |> TimeWrapper.convert("UTC") |> convert_to_paris_time()
236233
end
237234

238235
defp get_localized_datetime_format("en" = locale, options) do

apps/shared/lib/time_wrapper.ex

+48
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
defmodule TimeWrapper do
2+
@moduledoc """
3+
This module concentrates all the calls to `Timex` in a single place.
4+
5+
The idea behind this module is 1. to reduce our dependency on `Timex`, and
6+
2. to ideally gradually replace calls by built-in Elixir `DateTime` calls, since
7+
`Timex` filled a void in the language that has been partially filled now.
8+
"""
9+
10+
# credo:disable-for-this-file Credo.Check.Warning.ForbiddenModule
11+
12+
def parse!(date_as_string, "{ISO:Extended}" = param) do
13+
Timex.parse!(date_as_string, param)
14+
end
15+
16+
def parse!(date_as_string, "{YYYY}{0M}{0D}" = param) do
17+
Timex.parse!(date_as_string, param)
18+
end
19+
20+
# NOTE: try not to use this, we will remove it. This is rfc2822 ;
21+
# Plug encodes it, but there is no built-in decoder.
22+
def parse!(datetime_as_string, "{WDshort}, {D} {Mshort} {YYYY} {h24}:{m}:{s} GMT" = param) do
23+
Timex.parse!(datetime_as_string, param)
24+
end
25+
26+
def diff(first, second, :hours = param) do
27+
Timex.diff(first, second, param)
28+
end
29+
30+
def now do
31+
Timex.now()
32+
end
33+
34+
def shift(dt, months: months) do
35+
Timex.shift(dt, months: months)
36+
end
37+
38+
def convert(dt, "UTC") do
39+
Timex.Timezone.convert(dt, "UTC")
40+
end
41+
42+
def convert_to_paris_time(dt) do
43+
case Timex.Timezone.convert(dt, "Europe/Paris") do
44+
%Timex.AmbiguousDateTime{after: dt} -> dt
45+
%DateTime{} = dt -> dt
46+
end
47+
end
48+
end
+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
defmodule TimeWrapperTest do
2+
use ExUnit.Case, async: true
3+
doctest TimeWrapper
4+
end

apps/transport/lib/jobs/gtfs_to_db.ex

+3-3
Original file line numberDiff line numberDiff line change
@@ -120,8 +120,8 @@ defmodule Transport.Jobs.GtfsToDB do
120120
friday: friday = r |> Map.fetch!("friday") |> String.to_integer(),
121121
saturday: saturday = r |> Map.fetch!("saturday") |> String.to_integer(),
122122
sunday: sunday = r |> Map.fetch!("sunday") |> String.to_integer(),
123-
start_date: r |> Map.fetch!("start_date") |> Timex.parse!("{YYYY}{0M}{0D}") |> NaiveDateTime.to_date(),
124-
end_date: r |> Map.fetch!("end_date") |> Timex.parse!("{YYYY}{0M}{0D}") |> NaiveDateTime.to_date()
123+
start_date: r |> Map.fetch!("start_date") |> TimeWrapper.parse!("{YYYY}{0M}{0D}") |> NaiveDateTime.to_date(),
124+
end_date: r |> Map.fetch!("end_date") |> TimeWrapper.parse!("{YYYY}{0M}{0D}") |> NaiveDateTime.to_date()
125125
}
126126

127127
res
@@ -214,7 +214,7 @@ defmodule Transport.Jobs.GtfsToDB do
214214
%{
215215
data_import_id: data_import_id,
216216
service_id: r |> Map.fetch!("service_id"),
217-
date: r |> Map.fetch!("date") |> Timex.parse!("{YYYY}{0M}{0D}") |> NaiveDateTime.to_date(),
217+
date: r |> Map.fetch!("date") |> TimeWrapper.parse!("{YYYY}{0M}{0D}") |> NaiveDateTime.to_date(),
218218
exception_type: r |> Map.fetch!("exception_type") |> String.to_integer()
219219
}
220220
end)

apps/transport/lib/transport_web/live/discussions_live.ex

+1-1
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ defmodule TransportWeb.DiscussionsLive do
115115
end)
116116
|> Enum.max(DateTime)
117117

118-
two_months_ago = DateTime.utc_now() |> Timex.shift(months: -2)
118+
two_months_ago = DateTime.utc_now() |> TimeWrapper.shift(months: -2)
119119
DateTime.compare(two_months_ago, latest_comment_datetime) == :gt
120120
end
121121

apps/transport/test/transport_web/live_views/discussions_live_test.exs

+1-1
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,7 @@ defmodule Transport.TransportWeb.DiscussionsLiveTest do
209209
end
210210

211211
defp iso8601_string_x_months_ago(x) do
212-
DateTime.utc_now() |> Timex.shift(months: -x) |> DateTime.to_iso8601()
212+
DateTime.utc_now() |> TimeWrapper.shift(months: -x) |> DateTime.to_iso8601()
213213
end
214214

215215
defp discussions do

apps/transport/test/transport_web/routing/headers_and_cookies_test.exs

+2-2
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ defmodule TransportWeb.HeadersAndCookiesTest do
2424
"expires" => datetime
2525
} = Plug.Conn.Cookies.decode(header)
2626

27-
datetime = Timex.parse!(datetime, "{WDshort}, {D} {Mshort} {YYYY} {h24}:{m}:{s} GMT")
28-
assert_in_delta Timex.diff(datetime, Timex.now(), :hours), 15 * 24, 1
27+
datetime = TimeWrapper.parse!(datetime, "{WDshort}, {D} {Mshort} {YYYY} {h24}:{m}:{s} GMT")
28+
assert_in_delta TimeWrapper.diff(datetime, TimeWrapper.now(), :hours), 15 * 24, 1
2929
end
3030
end

0 commit comments

Comments
 (0)