Skip to content

Commit 967c87b

Browse files
committed
Simplify iso conversion, prefer Duration.new!
1 parent cd1529f commit 967c87b

File tree

1 file changed

+36
-50
lines changed

1 file changed

+36
-50
lines changed

lib/elixir/lib/calendar/duration.ex

+36-50
Original file line numberDiff line numberDiff line change
@@ -183,9 +183,9 @@ defmodule Duration do
183183
184184
## Examples
185185
186-
iex> Duration.add(%Duration{week: 2, day: 1}, %Duration{day: 2})
186+
iex> Duration.add(Duration.new!(week: 2, day: 1), Duration.new!(day: 2))
187187
%Duration{week: 2, day: 3}
188-
iex> Duration.add(%Duration{microsecond: {400, 3}}, %Duration{microsecond: {600, 6}})
188+
iex> Duration.add(Duration.new!(microsecond: {400, 3}), Duration.new!(microsecond: {600, 6}))
189189
%Duration{microsecond: {1000, 6}}
190190
191191
"""
@@ -213,9 +213,9 @@ defmodule Duration do
213213
214214
## Examples
215215
216-
iex> Duration.subtract(%Duration{week: 2, day: 1}, %Duration{day: 2})
216+
iex> Duration.subtract(Duration.new!(week: 2, day: 1), Duration.new!(day: 2))
217217
%Duration{week: 2, day: -1}
218-
iex> Duration.subtract(%Duration{microsecond: {400, 6}}, %Duration{microsecond: {600, 3}})
218+
iex> Duration.subtract(Duration.new!(microsecond: {400, 6}), Duration.new!(microsecond: {600, 3}))
219219
%Duration{microsecond: {-200, 6}}
220220
221221
"""
@@ -241,9 +241,9 @@ defmodule Duration do
241241
242242
## Examples
243243
244-
iex> Duration.multiply(%Duration{day: 1, minute: 15, second: -10}, 3)
244+
iex> Duration.multiply(Duration.new!(day: 1, minute: 15, second: -10), 3)
245245
%Duration{day: 3, minute: 45, second: -30}
246-
iex> Duration.multiply(%Duration{microsecond: {200, 4}}, 3)
246+
iex> Duration.multiply(Duration.new!(microsecond: {200, 4}), 3)
247247
%Duration{microsecond: {600, 4}}
248248
249249
"""
@@ -266,9 +266,9 @@ defmodule Duration do
266266
267267
## Examples
268268
269-
iex> Duration.negate(%Duration{day: 1, minute: 15, second: -10})
269+
iex> Duration.negate(Duration.new!(day: 1, minute: 15, second: -10))
270270
%Duration{day: -1, minute: -15, second: 10}
271-
iex> Duration.negate(%Duration{microsecond: {500000, 4}})
271+
iex> Duration.negate(Duration.new!(microsecond: {500000, 4}))
272272
%Duration{microsecond: {-500000, 4}}
273273
274274
"""
@@ -353,78 +353,60 @@ defmodule Duration do
353353
354354
## Examples
355355
356-
iex> Duration.to_iso8601(%Duration{year: 3})
356+
iex> Duration.to_iso8601(Duration.new!(year: 3))
357357
"P3Y"
358-
iex> Duration.to_iso8601(%Duration{day: 40, hour: 12, minute: 42, second: 12})
358+
iex> Duration.to_iso8601(Duration.new!(day: 40, hour: 12, minute: 42, second: 12))
359359
"P40DT12H42M12S"
360-
iex> Duration.to_iso8601(%Duration{second: 30})
360+
iex> Duration.to_iso8601(Duration.new!(second: 30))
361361
"PT30S"
362362
363-
iex> Duration.to_iso8601(%Duration{})
363+
iex> Duration.to_iso8601(Duration.new!([]))
364364
"PT0S"
365365
366-
iex> Duration.to_iso8601(%Duration{second: 1, microsecond: {2_200, 3}})
366+
iex> Duration.to_iso8601(Duration.new!(second: 1, microsecond: {2_200, 3}))
367367
"PT1.002S"
368-
iex> Duration.to_iso8601(%Duration{second: 1, microsecond: {-1_200_000, 4}})
368+
iex> Duration.to_iso8601(Duration.new!(second: 1, microsecond: {-1_200_000, 4}))
369369
"PT-0.2000S"
370370
"""
371371

372372
@spec to_iso8601(t) :: String.t()
373-
def to_iso8601(duration)
374-
375-
def to_iso8601(%Duration{
376-
year: 0,
377-
month: 0,
378-
week: 0,
379-
day: 0,
380-
hour: 0,
381-
minute: 0,
382-
second: 0,
383-
microsecond: {0, _}
384-
}) do
385-
"PT0S"
373+
def to_iso8601(%Duration{} = duration) do
374+
case {to_iso8601_duration_date(duration), to_iso8601_duration_time(duration)} do
375+
{[], []} -> "PT0S"
376+
{date, time} -> IO.iodata_to_binary([?P, date, time])
377+
end
386378
end
387379

388-
def to_iso8601(%Duration{} = d) do
389-
IO.iodata_to_binary([?P, to_iso8601_duration_date(d), to_iso8601_duration_time(d)])
380+
defp to_iso8601_duration_date(%{year: 0, month: 0, week: 0, day: 0}) do
381+
[]
390382
end
391383

392-
defp to_iso8601_duration_date(d) do
393-
[
394-
if(d.year == 0, do: [], else: [Integer.to_string(d.year), ?Y]),
395-
if(d.month == 0, do: [], else: [Integer.to_string(d.month), ?M]),
396-
if(d.week == 0, do: [], else: [Integer.to_string(d.week), ?W]),
397-
if(d.day == 0, do: [], else: [Integer.to_string(d.day), ?D])
398-
]
384+
defp to_iso8601_duration_date(%{year: year, month: month, week: week, day: day}) do
385+
[pair(year, ?Y), pair(month, ?M), pair(week, ?W), pair(day, ?D)]
399386
end
400387

401-
defp to_iso8601_duration_time(%Duration{hour: 0, minute: 0, second: 0, microsecond: {0, _}}) do
388+
defp to_iso8601_duration_time(%{hour: 0, minute: 0, second: 0, microsecond: {0, _}}) do
402389
[]
403390
end
404391

405-
defp to_iso8601_duration_time(d) do
406-
[
407-
?T,
408-
if(d.hour == 0, do: [], else: [Integer.to_string(d.hour), ?H]),
409-
if(d.minute == 0, do: [], else: [Integer.to_string(d.minute), ?M]),
410-
second_component(d)
411-
]
392+
defp to_iso8601_duration_time(%{hour: hour, minute: minute} = d) do
393+
[?T, pair(hour, ?H), pair(minute, ?M), second_component(d)]
412394
end
413395

414-
defp second_component(%Duration{second: 0, microsecond: {0, _}}) do
396+
defp second_component(%{second: 0, microsecond: {0, _}}) do
415397
[]
416398
end
417399

418-
defp second_component(%Duration{second: 0, microsecond: {_, 0}}) do
400+
defp second_component(%{second: 0, microsecond: {_, 0}}) do
419401
~c"0S"
420402
end
421403

422-
defp second_component(%Duration{microsecond: {_, 0}} = d) do
423-
[Integer.to_string(d.second), ?S]
404+
defp second_component(%{second: second, microsecond: {_, 0}}) do
405+
[Integer.to_string(second), ?S]
424406
end
425407

426-
defp second_component(%Duration{microsecond: {ms, p}} = d) do
427-
total_ms = d.second * @microseconds_per_second + ms
408+
defp second_component(%{second: second, microsecond: {ms, p}}) do
409+
total_ms = second * @microseconds_per_second + ms
428410
second = total_ms |> div(@microseconds_per_second) |> abs()
429411
ms = total_ms |> rem(@microseconds_per_second) |> abs()
430412
sign = if total_ms < 0, do: ?-, else: []
@@ -437,4 +419,8 @@ defmodule Duration do
437419
?S
438420
]
439421
end
422+
423+
@compile {:inline, pair: 2}
424+
defp pair(0, _key), do: []
425+
defp pair(num, key), do: [Integer.to_string(num), key]
440426
end

0 commit comments

Comments
 (0)