Skip to content

Commit

Permalink
feat: add method subtractRound to prevent date overflow (#42)
Browse files Browse the repository at this point in the history
  • Loading branch information
g1eny0ung authored Feb 3, 2022
1 parent 95282a1 commit 9226606
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 51 deletions.
16 changes: 16 additions & 0 deletions API.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ Also inherit from Day.js, part of manipulations is immutable.
- [Add `.add(int val, String unit)`](#add-addint-val-string-unit)
- [Add Round `.addRound(int val, String unit)`](#add-round-addroundint-val-string-unit)
- [Subtract `.subtract(int val, String unit)`](#subtract-subtractint-val-string-unit)
- [Subtract Round `.subtractRound(int val, String unit)`](#subtract-round-subtractroundint-val-string-unit)
- [Inc (Same as add)](#inc-same-as-add)
- [Dec (Same as subtract)](#dec-same-as-subtract)
- [Displaying](#displaying)
Expand Down Expand Up @@ -309,12 +310,27 @@ d.addRound(1, 'month'); // 2022-04-30T15:52:50.000Z

Returns a cloned day with a specified amount of time subtracted.

So if you wanna receive a non-overflow date, you should use `.subtractRound()` method below.

Refer to [`.add()`](#add-addint-val-string-unit) for more details.

```dart
final d = Day();
d.subtract(1, 'date');
```

### Subtract Round `.subtractRound(int val, String unit)`

Returns a cloned day with a specified amount of time subtracted but rounded to the last day of the current month if overflowed.

```dart
final d = Day.fromString('2022-03-31T15:52:50.000Z');
d.subtract(1, 'month'); // 2022-03-03T15:52:50.000Z
d.subtractRound(1, 'month'); // 2022-02-28T15:52:50.000Z
```

### Inc (Same as add)

A `.add()` shorthand.
Expand Down
43 changes: 8 additions & 35 deletions lib/src/day.dart
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,7 @@ class Day {
Day? _add({
required int val,
required String unit,
bool opposite = false,
bool rounded = false,
}) {
final processedUnit = Unit.fromShorthand(unit);
Expand All @@ -339,13 +340,13 @@ class Day {
if (duration != null) {
final d = clone();

d._time = d._time.add(duration);
d._time = !opposite ? d._time.add(duration) : d._time.subtract(duration);
d._parseTime();

return d;
} else {
if (unit == Unit.y || unit == 'y') {
final currentYear = year() + val;
final currentYear = year() + (!opposite ? val : -val);

if (rounded) {
final currentMonth = month();
Expand All @@ -364,7 +365,7 @@ class Day {
} else if (unit == Unit.m || unit == 'M') {
final d = clone();

final int result = month() + val;
final int result = month() + (!opposite ? val : -val);

if (result > 0) {
d.setValue(Unit.m, result);
Expand Down Expand Up @@ -423,39 +424,11 @@ class Day {
/// subtract(1, 'date');
/// subtract(1, 'd');
/// ```
dynamic subtract(int val, String unit) {
final processedUnit = Unit.fromShorthand(unit);
final duration = u.durationFromUnit(val, processedUnit);

if (duration != null) {
final d = clone();

d._time = d._time.subtract(duration);
d._parseTime();

return d;
} else {
if (unit == Unit.y || unit == 'y') {
return _cloneAndSetSingleValue(Unit.y, year() - val);
} else if (unit == Unit.m || unit == 'M') {
final int result = month() - val;

final d = clone();
if (result > 0) {
d.setValue(Unit.m, result);
} else {
d
..setValue(Unit.y, d.year() - (result.abs() ~/ 12 + 1))
..setValue(Unit.m, 12 - result.abs() % 12);
}
d.finished();
Day? subtract(int val, String unit) =>
_add(val: val, unit: unit, opposite: true);

return d;
}
}

return null;
}
Day? subtractRound(int val, String unit) =>
_add(val: val, unit: unit, opposite: true, rounded: true);

/// Alias of [add].
dynamic inc(int val, String unit) => add(val, unit);
Expand Down
22 changes: 22 additions & 0 deletions test/day_subtract_round_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import 'package:test/test.dart';
import 'package:day/day.dart';

void main() {
test(
'.subtractRound(1, \'M\') returns a date not exceeding the current month',
() {
final d = Day.fromString('2022-03-31T15:52:50.000Z').subtractRound(1, 'M')!;

expect(d.month(), equals(2));
expect(d.date(), 28);
});

test(
'.subtractRound(1, \'y\') returns a date not exceeding the current month',
() {
final d = Day.fromString('2020-02-29T15:52:50.000Z').subtractRound(1, 'y')!;

expect(d.month(), equals(2));
expect(d.date(), 28);
});
}
32 changes: 16 additions & 16 deletions test/day_subtract_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,31 +6,31 @@ void main() {

group('Subtract Method:', () {
test('1 year', () {
final Day dClone = d.subtract(1, 'year');
final dClone = d.subtract(1, 'year')!;

expect(d.year(), equals(2019));

expect(dClone.year(), equals(2018));
});

test('-1 year', () {
final Day dClone = d.subtract(-1, 'year');
final dClone = d.subtract(-1, 'year')!;

expect(d.year(), equals(2019));

expect(dClone.year(), equals(2020));
});

test('2 months', () {
final Day dClone = d.subtract(2, 'month');
final dClone = d.subtract(2, 'month')!;

expect(d.month(), equals(4));

expect(dClone.month(), equals(3));
});

test('4 months', () {
final Day dClone = d.subtract(4, 'month');
final dClone = d.subtract(4, 'month')!;

expect(d.year(), equals(2019));
expect(d.month(), equals(4));
Expand All @@ -40,7 +40,7 @@ void main() {
});

test('28 months', () {
final Day dClone = d.subtract(28, 'month');
final dClone = d.subtract(28, 'month')!;

expect(d.year(), equals(2019));
expect(d.month(), equals(4));
Expand All @@ -50,7 +50,7 @@ void main() {
});

test('-8 months', () {
final Day dClone = d.subtract(-8, 'month');
final dClone = d.subtract(-8, 'month')!;

expect(d.year(), equals(2019));
expect(d.month(), equals(4));
Expand All @@ -60,7 +60,7 @@ void main() {
});

test('-9 months', () {
final Day dClone = d.subtract(-9, 'month');
final dClone = d.subtract(-9, 'month')!;

expect(d.year(), equals(2019));
expect(d.month(), equals(4));
Expand All @@ -70,7 +70,7 @@ void main() {
});

test('1 day', () {
final Day dClone = d.subtract(1, 'date');
final dClone = d.subtract(1, 'date')!;

expect(d.month(), equals(4));
expect(d.date(), equals(30));
Expand All @@ -80,63 +80,63 @@ void main() {
});

test('1 hour', () {
final Day dClone = d.subtract(1, 'hour');
final dClone = d.subtract(1, 'hour')!;

expect(d.hour(), equals(10));

expect(dClone.hour(), equals(9));
});

test('-1 hour', () {
final Day dClone = d.subtract(-1, 'hour');
final dClone = d.subtract(-1, 'hour')!;

expect(d.hour(), equals(10));

expect(dClone.hour(), equals(11));
});

test('1 minute', () {
final Day dClone = d.subtract(1, 'minute');
final dClone = d.subtract(1, 'minute')!;

expect(d.minute(), equals(30));

expect(dClone.minute(), equals(29));
});

test('-1 minute', () {
final Day dClone = d.subtract(-1, 'minute');
final dClone = d.subtract(-1, 'minute')!;

expect(d.minute(), equals(30));

expect(dClone.minute(), equals(31));
});

test('1 second', () {
final Day dClone = d.subtract(1, 'second');
final dClone = d.subtract(1, 'second')!;

expect(d.second(), equals(30));

expect(dClone.second(), equals(29));
});

test('-1 second', () {
final Day dClone = d.subtract(-1, 'second');
final dClone = d.subtract(-1, 'second')!;

expect(d.second(), equals(30));

expect(dClone.second(), equals(31));
});

test('1 ms', () {
final Day dClone = d.subtract(1, 'ms');
final dClone = d.subtract(1, 'ms')!;

expect(d.millisecond(), equals(0));

expect(dClone.millisecond(), equals(999));
});

test('-1 ms', () {
final Day dClone = d.subtract(-1, 'ms');
final dClone = d.subtract(-1, 'ms')!;

expect(d.millisecond(), equals(0));

Expand Down

0 comments on commit 9226606

Please sign in to comment.