Skip to content

Commit

Permalink
feat: Text encoding for BYHOUR, BYMINUTE, BYSECOND
Browse files Browse the repository at this point in the history
  • Loading branch information
plammens committed Apr 28, 2023
1 parent 81be667 commit 4572ed6
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 7 deletions.
30 changes: 27 additions & 3 deletions lib/src/codecs/text/encoder.dart
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,9 @@ class RecurrenceRuleToTextEncoder extends Converter<RecurrenceRule, String> {
combination: input.hasByWeekDays
? ListCombination.disjunctive
: ListCombination.conjunctiveShort,
));
))
// [at 8:00 & 12:00]
..add(_formatByTime(input));
}

void _convertWeekly(RecurrenceRule input, StringBuffer output) {
Expand All @@ -137,7 +139,9 @@ class RecurrenceRuleToTextEncoder extends Converter<RecurrenceRule, String> {
variant: input.hasBySetPositions
? InOnVariant.instanceOf
: InOnVariant.simple,
));
))
// [at 8:00 & 12:00]
..add(_formatByTime(input));
}

void _convertMonthly(RecurrenceRule input, StringBuffer output) {
Expand Down Expand Up @@ -176,7 +180,9 @@ class RecurrenceRuleToTextEncoder extends Converter<RecurrenceRule, String> {
combination: input.hasByWeekDays
? ListCombination.disjunctive
: ListCombination.conjunctiveShort,
));
))
// [at 8:00 & 12:00]
..add(_formatByTime(input));
}

void _convertYearly(RecurrenceRule input, StringBuffer output) {
Expand Down Expand Up @@ -283,6 +289,8 @@ class RecurrenceRuleToTextEncoder extends Converter<RecurrenceRule, String> {
if (limits.isNotEmpty) {
output.add(l10n.list(limits, ListCombination.conjunctiveLong));
}

output.add(_formatByTime(input));
}

String? _formatBySetPositions(RecurrenceRule input) {
Expand Down Expand Up @@ -378,6 +386,22 @@ class RecurrenceRuleToTextEncoder extends Converter<RecurrenceRule, String> {
variant: variant,
);
}

String? _formatByTime(RecurrenceRule input) {
final byHours = input.hasByHours ? input.byHours : {null};
final byMinutes = input.hasByMinutes ? input.byMinutes : {null};
final bySeconds = input.hasBySeconds ? input.bySeconds : {null};

final timesOfDay = [
for (var hour in byHours)
for (var minute in byMinutes)
for (var second in bySeconds)
if (!(hour == null && minute == null && second == null))
l10n.timeOfDay(hour, minute, second)
];

return timesOfDay.isEmpty ? null : l10n.atTimesOfDay(timesOfDay);
}
}

extension on StringBuffer {
Expand Down
19 changes: 19 additions & 0 deletions lib/src/codecs/text/l10n/en.dart
Original file line number Diff line number Diff line change
Expand Up @@ -181,4 +181,23 @@ class RruleL10nEn extends RruleL10n {

return number < 0 ? '$string-to-last' : string;
}

@override
String timeOfDay(int? hour, int? minute, int? second) {
final minutesFormat = NumberFormat('00');
final secondsFormat = minutesFormat;

final parts = [
if (hour != null) hour.toString(),
if (minute != null) ':${minutesFormat.format(minute)}',
if (minute == null && second != null) ':',
if (second != null) ':${secondsFormat.format(second)}'
];
return parts.join();
}

@override
String atTimesOfDay(List<String> timesOfDay) {
return 'at ${list(timesOfDay, ListCombination.conjunctiveShort)}';
}
}
4 changes: 4 additions & 0 deletions lib/src/codecs/text/l10n/l10n.dart
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,10 @@ abstract class RruleL10n {
}

String ordinal(int number);

String timeOfDay(int? hour, int? minute, int? second);

String atTimesOfDay(List<String> timesOfDay);
}

enum InOnVariant { simple, also, instanceOf }
Expand Down
5 changes: 1 addition & 4 deletions lib/src/recurrence_rule.dart
Original file line number Diff line number Diff line change
Expand Up @@ -363,13 +363,10 @@ class RecurrenceRule {

/// Whether this rule can be converted to a human-readable string.
///
/// - Unsupported attributes: [bySeconds], [byMinutes], [byHours]
/// - Unsupported frequencies (if any by-parts are specified):
/// [Frequency.secondly], [Frequency.hourly], [Frequency.daily]
bool get canFullyConvertToText {
if (hasBySeconds || hasByMinutes || hasByHours) {
return false;
} else if (frequency <= Frequency.daily) {
if (frequency <= Frequency.daily) {
return true;
} else if (hasBySetPositions ||
hasBySeconds ||
Expand Down
16 changes: 16 additions & 0 deletions test/codecs/text/daily_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -107,4 +107,20 @@ void main() {
string:
'RRULE:FREQ=DAILY;BYSETPOS=1,-2;BYMONTH=1,12;BYMONTHDAY=1,-1;BYDAY=MO,TH',
);

// Time of day.

testText(
'Daily at 8:30 & 12:30',
string: 'RRULE:FREQ=DAILY;BYHOUR=8,12;BYMINUTE=30',
);

test('canConvertToText is true when byHours is specified', () async {
final rrule = RecurrenceRule(frequency: Frequency.daily, byHours: {8});
expect(rrule.canFullyConvertToText, isTrue);
expect(
rrule.toText(l10n: await RruleL10nEn.create()),
equals('Daily at 8'),
);
});
}

0 comments on commit 4572ed6

Please sign in to comment.