@@ -299,6 +299,55 @@ defmodule Duration do
299
299
}
300
300
end
301
301
302
+ @ doc """
303
+ Compares two durations.
304
+
305
+ Returns `:eq` if the durations are equal, `:lt` if the first duration is less than the second, and `:gt` if the first
306
+ duration is greater than the second.
307
+
308
+ ## Examples
309
+
310
+ iex> Duration.compare(Duration.new!(second: 10), Duration.new!(second: 20))
311
+ :lt
312
+ iex> Duration.compare(Duration.new!(second: 20), Duration.new!(second: 10))
313
+ :gt
314
+ iex> Duration.compare(Duration.new!(second: 10), Duration.new!(second: 10))
315
+ :eq
316
+ """
317
+ @ doc since: "1.19.0"
318
+ @ spec compare ( t , t ) :: :eq | :lt | :gt
319
+ def compare ( % Duration { } = d1 , % Duration { } = d2 ) do
320
+ d1_us = to_microseconds ( d1 )
321
+ d2_us = to_microseconds ( d2 )
322
+
323
+ cond do
324
+ d1_us == d2_us -> :eq
325
+ d1_us < d2_us -> :lt
326
+ d1_us > d2_us -> :gt
327
+ end
328
+ end
329
+
330
+ @ second_in_us 1_000_000 # 1 second in microseconds
331
+ @ minute_in_us @ second_in_us * 60 # 1 minute = 60 seconds
332
+ @ hour_in_us @ minute_in_us * 60 # 1 hour = 60 minutes
333
+ @ day_in_us @ hour_in_us * 24 # 1 day = 24 hours
334
+ @ week_in_us @ day_in_us * 7 # 1 week = 7 days
335
+ @ month_in_us @ day_in_us * 30 # 1 month = 30 days
336
+ @ year_in_us @ day_in_us * 365 # 1 year = 365 days
337
+
338
+ def to_microseconds ( duration ) do
339
+ { microsecond , _precision } = duration . microsecond
340
+
341
+ duration . year * @ year_in_us +
342
+ duration . month * @ month_in_us +
343
+ duration . week * @ week_in_us +
344
+ duration . day * @ day_in_us +
345
+ duration . hour * @ hour_in_us +
346
+ duration . minute * @ minute_in_us +
347
+ duration . second * @ second_in_us +
348
+ microsecond
349
+ end
350
+
302
351
@ doc """
303
352
Parses an [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601#Durations) formatted duration string to a `Duration` struct.
304
353
0 commit comments