Method Chaining
Changelog
All notable changes to this project will be documented in this file.
3.1.0 - 2025-09-15
Added
- Method chaining and immutability support in
Kenat
:add(amount, 'days'|'months'|'years')
subtract(amount, 'days'|'months'|'years')
startOf('day'|'month'|'year')
endOf('day'|'month'|'year')
setTime(hour, minute, 'day'|'night')
now returns a new instance
- New test suite
tests/methodChaining.test.js
covering chaining, immutability, time preservation, error cases, leap-year handling, and boundaries. - Type definitions updated in
types/Kenat.d.ts
to include new chainable APIs.
Changed
- Existing arithmetic methods now delegate to the new chainable API while preserving backward compatibility:
addDays(days)
,addMonths(months)
,addYears(years)
startOfMonth()
,endOfMonth()
Fixed
addDays
insrc/dayArithmetic.js
now correctly handles negative day offsets (moving backward across months/years).
Docs
- Inline JSDoc improvements around new methods (chainability and immutability).
Performance/Behavioral Notes
- All date operations are immutable—no mutation of the original
Kenat
instance. - Time component is preserved across date arithmetic by default.
Migration Notes
- No breaking changes. Existing APIs continue to work.
- Prefer new chainable methods for more fluent and readable code.
Examples
- Basic chaining
const date1 = new Kenat('2017/1/1');
const future = date1.add(7, 'days').add(1, 'months').add(1, 'years');
console.log('Original:', date1.format());
console.log('After chaining:', future.format());
console.log('Result:', future.getEthiopian());
Output:
Original: መስከረም 1 2017
After chaining: ጥቅምት 8 2018
Result: { year: 2018, month: 2, day: 8 }
- Subtract operations
const date2 = new Kenat('2017/1/1');
const past = date2.subtract(7, 'days').subtract(1, 'months').subtract(1, 'years');
console.log('Original:', date2.format());
console.log('After subtracting:', past.format());
console.log('Result:', past.getEthiopian());
Output:
Original: መስከረም 1 2017
After subtracting: ሀምሌ 29 2015
Result: { year: 2015, month: 11, day: 29 }
- Mixed add and subtract
const date3 = new Kenat('2017/1/1');
const mixed = date3.add(7, 'days').subtract(1, 'months').add(1, 'years');
console.log('Original:', date3.format());
console.log('After mixed operations:', mixed.format());
console.log('Result:', mixed.getEthiopian());
Output:
Original: መስከረም 1 2017
After mixed operations: ጳጉሜ 5 2017
Result: { year: 2017, month: 13, day: 5 }
- Time preservation
const date4 = new Kenat('2017/1/1', { hour: 3, minute: 30, period: 'day' });
const withTime = date4.add(7, 'days').add(1, 'months');
console.log('Original:', date4.toString());
console.log('After operations:', withTime.toString());
console.log('Time preserved:', withTime.time);
Output:
Original: መስከረም 1 2017 03:30 ጠዋት
After operations: ጥቅምት 8 2017 03:30 ጠዋት
Time preserved: { hour: 3, minute: 30, period: 'day' }
- startOf and endOf chaining
const date5 = new Kenat('2017/6/15');
const res = date5.startOf('month').add(7, 'days').endOf('day');
console.log('Original:', date5.format());
console.log('After startOf/endOf:', res.format());
console.log('Time set to:', res.time);
Output:
Original: የካቲት 15 2017
After startOf/endOf: የካቲት 8 2017
Time set to: { hour: 12, minute: 0, period: 'night' }
- Complex chaining
const date6 = new Kenat('2017/1/1');
const complex = date6
.startOf('month')
.add(14, 'days')
.setTime(12, 0, 'day')
.add(1, 'months')
.endOf('day')
.add(1, 'years');
console.log('Original:', date6.format());
console.log('After complex chaining:', complex.format());
console.log('Final result:', complex.getEthiopian());
Output:
Original: መስከረም 1 2017
After complex chaining: ጥቅምት 15 2018
Final result: { year: 2018, month: 2, day: 15 }
- Leap year handling
const leapDate = new Kenat('2015/13/6');
const leapResult = leapDate.add(1, 'days').add(1, 'months');
console.log('Original (leap year):', leapDate.format());
console.log('After operations:', leapResult.format());
console.log('Result:', leapResult.getEthiopian());
Output:
Original (leap year): ጳጉሜ 6 2015
After operations: ጥቅምት 1 2016
Result: { year: 2016, month: 2, day: 1 }