@@ -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 ]
440426end
0 commit comments