Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add businessDiff method #45

Open
wants to merge 16 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 13 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,13 @@ dt.isHoliday('middle-america', {some: 'stuff'});
</dd>
</dl>

## Typedefs

<dl>
<dt><a href="#DiffBusinessConfig">DiffBusinessConfig</a></dt>
<dd></dd>
</dl>

<a name="DateTime"></a>

## DateTime ⇐ [<code>DateTime</code>](#DateTime)
Expand All @@ -264,6 +271,7 @@ dt.isHoliday('middle-america', {some: 'stuff'});
* [.isBusinessDay()](#DateTime+isBusinessDay) ⇒ <code>boolean</code>
* [.plusBusiness([days])](#DateTime+plusBusiness) ⇒ [<code>DateTime</code>](#DateTime)
* [.minusBusiness([days])](#DateTime+minusBusiness) ⇒ [<code>DateTime</code>](#DateTime)
* [.diffBusiness(targetDate, config)](#DateTime+diffBusiness) ⇒ <code>number</code>

<a name="DateTime+availableHolidayMatchers"></a>

Expand Down Expand Up @@ -362,6 +370,18 @@ Subtracts business days to an existing DateTime instance.
| --- | --- | --- | --- |
| [days] | <code>number</code> | <code>1</code> | The number of business days to subtract. |

<a name="DateTime+diffBusiness"></a>

### dateTime.diffBusiness(targetDate, config) ⇒ <code>number</code>
Returns the difference in business days.

**Kind**: instance method of [<code>DateTime</code>](#DateTime)

| Param | Type |
| --- | --- |
| targetDate | [<code>DateTime</code>](#DateTime) |
| config | [<code>DiffBusinessConfig</code>](#DiffBusinessConfig) |

<a name="getEasterMonthAndDay"></a>

## getEasterMonthAndDay(year) ⇒ <code>Array.&lt;number&gt;</code>
Expand All @@ -374,3 +394,14 @@ Returns the month and day of Easter for a given year.
| --- | --- |
| year | <code>number</code> |

<a name="DiffBusinessConfig"></a>

## DiffBusinessConfig
**Kind**: global typedef
**Properties**

| Name | Type | Default | Description |
| --- | --- | --- | --- |
| [includeEndDate] | <code>boolean</code> | <code>false</code> | include the end date in the calculation |
| [relative] | <code>boolean</code> | <code>false</code> | signs the return value as negative if end date is in the past |

44 changes: 44 additions & 0 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -146,4 +146,48 @@ DateTime.prototype.minusBusiness = function({ days = ONE_DAY } = {}) {
return this.plusBusiness({ days: -days });
};

/**
* @typedef DiffBusinessConfig
* @property {boolean} [includeEndDate=false] - include the end date in the calculation
amaidah marked this conversation as resolved.
Show resolved Hide resolved
* @property {boolean} [relative=false] - signs the return value as negative if end date is in the past
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I think about how I use a calendar, I say things like 2 days ago (-2) so it doesn't make total sense to me that a difference would be absolute by default. Is there a reason for this? I remember being confused with the moment version of this plugin when I first saw that too.

Both diff and diffNow are relative and I'd like to to keep this plugin similar to Luxon core concepts

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the rationale is that you already have methods for determining whether a date is in the past and it is probably a less common scenario to need a negative value for a business day calculation.

That being said, consistency is a really strong argument so if you think it would be better defaulting relative to true I will support that.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok cool, let's go with relative as default

*/

/**
* Returns the difference in business days.
* @param {DateTime} targetDate
* @param {DiffBusinessConfig} config
* @returns {number}
*/
DateTime.prototype.diffBusiness = function(
targetDate,
{ includeEndDate = false, relative = false } = {}
) {
let dt = this;
let start = dt < targetDate ? dt : targetDate;
let end = dt < targetDate ? targetDate : dt;
let daysDiff = includeEndDate ? 1 : 0;
let isSameDay =
dt.hasSame(targetDate, 'day') &&
dt.hasSame(targetDate, 'month') &&
dt.hasSame(targetDate, 'year');

if (isSameDay) {
return daysDiff;
}

while (start < end) {
if (start.isBusinessDay() && !start.isHoliday()) {
daysDiff += 1;
}

start = start.plus({ days: 1 });
}

if (relative) {
return dt <= targetDate ? daysDiff : -daysDiff;
}

return daysDiff;
};

export { DateTime };
54 changes: 54 additions & 0 deletions src/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -324,3 +324,57 @@ describe('time zone is carried over after a business-day operation', () => {
expect(nyPlusTwo.zoneName).toBe('America/New_York');
});
});

describe('diffBusiness()', () => {
it('knows two identical DateTimes have a business day diff of 0', () => {
const targetDate = DateTime.local().plus({ hours: 2 });
kristremblay marked this conversation as resolved.
Show resolved Hide resolved
amaidah marked this conversation as resolved.
Show resolved Hide resolved

expect(DateTime.local().diffBusiness(targetDate)).toEqual(0);
});

it('knows there are 3 business days between two dates that are 3 business days apart', () => {
const myCompanyTakesNoHolidays = [];
const startDate = DateTime.local();
const futureDate = startDate.plusBusiness({ days: 3 });
const pastDate = startDate.minusBusiness({ days: 3 });

startDate.setupBusiness({
holidayMatchers: myCompanyTakesNoHolidays,
});

expect(startDate.diffBusiness(futureDate)).toEqual(3);
expect(startDate.diffBusiness(pastDate)).toEqual(3);
});

it('knows diff is negative for the past and positive for the future if relative is specified', () => {
const myCompanyTakesNoHolidays = [];
const startDate = DateTime.local();
const futureDate = startDate.plusBusiness({ days: 3 });
const pastDate = startDate.minusBusiness({ days: 3 });

startDate.setupBusiness({
holidayMatchers: myCompanyTakesNoHolidays,
});

const config = { relative: true };

expect(startDate.diffBusiness(futureDate, config)).toEqual(3);
expect(startDate.diffBusiness(pastDate, config)).toEqual(-3);
});

it('knows there are 4 business days between two dates that are 3 business days apart but include the end date', () => {
const myCompanyTakesNoHolidays = [];
const startDate = DateTime.local();
const futureDate = startDate.plusBusiness({ days: 3 });
const pastDate = startDate.minusBusiness({ days: 3 });

startDate.setupBusiness({
holidayMatchers: myCompanyTakesNoHolidays,
});

const config = { includeEndDate: true };

expect(startDate.diffBusiness(futureDate, config)).toEqual(4);
expect(startDate.diffBusiness(pastDate, config)).toEqual(4);
});
});