From 0bea641eb0447236939676ad7ab25c1c2bf1640d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20M=C3=BCller?= Date: Wed, 17 Jun 2020 15:23:24 +0200 Subject: [PATCH] Add number of months instead of weeks if they exceed a certain amount * default is 2 months as until that a timespan in weeks is sufficient (totally based on my personal gut feeling) * calculates with a rough average of 365 / 12 = 30.42 days per month --- README.md | 20 ++++++++++++++++++++ lib/src/duration.dart | 27 ++++++++++++++++++++------- lib/src/time_const.dart | 4 ++++ test/pretty_duration_test.dart | 23 +++++++++++++++++++++++ 4 files changed, 67 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index f51792b..8cfe15b 100644 --- a/README.md +++ b/README.md @@ -104,3 +104,23 @@ main() { ); } ``` + +## Months instead of weeks + +If a duration spans more than two months it will be formatted as 'x months' instead of 'y weeks'. +To override the amount of months use `minNumberMonths`. + +```dart +main() { + // => 8 weeks 4 days + printDuration( + Duration(days: 60) + ); + + // => 1 month 30 days + printDuration( + Duration(days: 60), + minNumberMonths: 1 + ); +} +``` diff --git a/lib/src/duration.dart b/lib/src/duration.dart index fbce795..ff7b32e 100644 --- a/lib/src/duration.dart +++ b/lib/src/duration.dart @@ -1,3 +1,5 @@ +import 'package:duration/src/time_const.dart'; + import 'locale/locale.dart'; import 'tersity.dart'; @@ -35,7 +37,8 @@ String prettyDuration(Duration duration, String delimiter, String conjunction, bool abbreviated = false, - bool first = false}) { + bool first = false, + int minNumberMonths = 2}) { if (abbreviated && delimiter == null) { delimiter = ', '; spacer = ''; @@ -55,14 +58,22 @@ String prettyDuration(Duration duration, return sb.toString(); }; - final int weeks = (duration.inDays / 7).floor(); + final int months = (duration.inDays / avgDaysPerMonth).floor(); + int daysCounted = 0; - if (weeks > 0) { - out.add(partFmt(weeks, locale.week)); + if (months >= minNumberMonths) { + out.add(partFmt(months, locale.month)); + daysCounted = (months * avgDaysPerMonth).floor(); + } else { + final int weeks = (duration.inDays / 7).floor(); + if (weeks > 0) { + out.add(partFmt(weeks, locale.week)); + daysCounted = weeks * 7; + } } if (tersity >= DurationTersity.day) { - final int days = duration.inDays - (weeks * 7); + final int days = duration.inDays - daysCounted; if (days > 0) out.add(partFmt(days, locale.day)); if (tersity >= DurationTersity.hour) { @@ -126,14 +137,16 @@ String printDuration(Duration duration, String spacer, String delimiter, String conjugation, - bool abbreviated = false}) { + bool abbreviated = false, + int minNumberMonths = 2}) { final String fmt = prettyDuration(duration, tersity: tersity, locale: locale, spacer: spacer, delimiter: delimiter, conjunction: conjugation, - abbreviated: abbreviated); + abbreviated: abbreviated, + minNumberMonths: minNumberMonths); print(fmt); return fmt; } diff --git a/lib/src/time_const.dart b/lib/src/time_const.dart index faa9aff..20f4e58 100644 --- a/lib/src/time_const.dart +++ b/lib/src/time_const.dart @@ -36,3 +36,7 @@ Duration hours(int hours) => Duration(hours: hours); // Creates a [Duration] with given [days] Duration days(int days) => Duration(days: days); + +// Average number of days per month (365 / 12) +// Obviously a bit off on leap years. +const double avgDaysPerMonth = 30.42; diff --git a/test/pretty_duration_test.dart b/test/pretty_duration_test.dart index 3f0f3dc..e6ea47a 100644 --- a/test/pretty_duration_test.dart +++ b/test/pretty_duration_test.dart @@ -97,6 +97,19 @@ void main() { final dur = Duration(days: 14); expect(prettyDuration(dur), '2 weeks'); } + + { + final dur = Duration(days: 60); + expect(prettyDuration(dur), '8 weeks 4 days'); + } + { + final dur = Duration(days: 61); + expect(prettyDuration(dur), '2 months 1 day'); + } + { + final dur = Duration(days: 60); + expect(prettyDuration(dur, minNumberMonths: 1), '1 month 30 days'); + } }); test('Abbreviated', () { @@ -204,6 +217,16 @@ void main() { final dur = Duration(days: 14); expect(prettyDuration(dur, abbreviated: true), '2w'); } + + { + final dur = Duration(days: 60); + expect(prettyDuration(dur, abbreviated: true), '8w, 4d'); + } + + { + final dur = Duration(days: 61); + expect(prettyDuration(dur, abbreviated: true), '2mon, 1d'); + } }); test('Delimiter', () {