diff --git a/packages/dart_flutter_common/lib/src/date_time.dart b/packages/dart_flutter_common/lib/src/date_time.dart index e1fa2e63..0b3d3de6 100644 --- a/packages/dart_flutter_common/lib/src/date_time.dart +++ b/packages/dart_flutter_common/lib/src/date_time.dart @@ -1,9 +1,67 @@ import 'package:intl/intl.dart'; extension DateTimeExtension on DateTime { + + /// _daysBeforeメソッドで使用される定数。 + /// 「N日前」と表示される最小日数を示す。 + static const _daysBeforeLowerLimit = 2; + + /// _daysBeforeメソッドで使用される定数。 + /// 「N日前」と表示される最大日数を示す。 + static const _daysBeforeUpperLimit = 7; + /// 「yyyy年MM月dd日」形式の文字列を返す。 String formatDate() => DateFormat('yyyy年MM月dd日').format(this); /// 「yyyy年MM月dd日 HH時mm分」形式の文字列を返す。 String formatDateTime() => DateFormat('yyyy年MM月dd日 HH時mm分').format(this); + + /// thisと現在時刻と比較して相対的な日付文字列を返す。 + /// thisが今日であれば、「HH:mm」 + /// 昨日であれば、「昨日」 + /// _daysBeforeLowerLimitから_daysBeforeUpperLimitの範囲内であれば、「N日前」 + /// それ以外は 'yyyy年MM月dd日' 形式の日付 + String formatRelativeDate() { + if (_isToday()) { + return DateFormat('HH:mm').format(this); + } + if (_isYesterday()) { + return '昨日'; + } + final daysBeforeResult = _daysBefore(); + if (daysBeforeResult != null) { + return '$daysBeforeResult日前'; + } + return formatDate(); + } + + /// thisが今日かどうかの真偽値を返す。 + /// thisと現在時刻の「年、月、日」が全て一致する場合には「今日」であるため真を返す。 + bool _isToday() { + final now = DateTime.now(); + return year == now.year && month == now.month && day == now.day; + } + + /// thisが昨日かどうかの真偽値を返す。 + /// thisと現在の日付より1日前の「年、月、日」が全て一致する場合には「昨日」であるため真を返す。 + bool _isYesterday() { + final now = DateTime.now(); + final yesterday = DateTime(now.year, now.month, now.day - 1); + return year == yesterday.year && + month == yesterday.month && + day == yesterday.day; + } + + /// thisと現在時刻との間の日数を計算し、 + /// その日数が[_daysBeforeLowerLimit] 日〜 [_daysBeforeUpperLimit] 日の範囲内ならその数字を、 + /// そうでなければnullを返す + int? _daysBefore() { + final now = DateTime.now(); + final difference = now.difference(this).inDays; + if (difference >= _daysBeforeLowerLimit && + difference <= _daysBeforeUpperLimit) { + return difference; + } + return null; + } } diff --git a/packages/dart_flutter_common/test/date_time_test.dart b/packages/dart_flutter_common/test/date_time_test.dart index 888069b1..89e8304b 100644 --- a/packages/dart_flutter_common/test/date_time_test.dart +++ b/packages/dart_flutter_common/test/date_time_test.dart @@ -1,5 +1,6 @@ import 'package:dart_flutter_common/dart_flutter_common.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'package:intl/intl.dart'; void main() { group('test DateTimeExtension', () { @@ -10,11 +11,49 @@ void main() { expect('1998年05月02日', formattedDate); }); - test('test formatDateTime', () { + test('test formatDateTime', () { final date = DateTime(1998, 5, 2, 10, 7); final formattedDate = date.formatDateTime(); expect('1998年05月02日 10時07分', formattedDate); }); + + test('test formatRelativeDate for today', () { + final now = DateTime.now(); + final date = DateTime(now.year, now.month, now.day, 12, 15); + final formattedRelativeDate = date.formatRelativeDate(); + + expect(formattedRelativeDate, DateFormat('HH:mm').format(date)); + }); + + test('test formatRelativeDate for yesterday', () { + final now = DateTime.now(); + final date = DateTime( + now.year, + now.month, + now.day - 1, + ); + final formattedRelativeDate = date.formatRelativeDate(); + + expect(formattedRelativeDate, '昨日'); + }); + + for (var i = 2; i <= 7; i++) { + test('test formatRelativeDate for $i daysBefore', () { + final now = DateTime.now(); + final date = DateTime(now.year, now.month, now.day - i); + final formattedRelativeDate = date.formatRelativeDate(); + + expect(formattedRelativeDate, '$i日前'); + }); + } + + test('test formatRelativeDate for over a week ago', () { + final now = DateTime.now(); + final date = DateTime(now.year, now.month, now.day - 8); + final formattedRelativeDate = date.formatRelativeDate(); + + expect(formattedRelativeDate, DateFormat('yyyy年MM月dd日').format(date)); + }); }); }