Skip to content
This repository has been archived by the owner on Mar 27, 2024. It is now read-only.

Commit

Permalink
Add differenceInBusinessDays helper
Browse files Browse the repository at this point in the history
  • Loading branch information
mobily committed Feb 1, 2020
1 parent 89e3ff5 commit 11a83d1
Show file tree
Hide file tree
Showing 5 changed files with 119 additions and 15 deletions.
2 changes: 1 addition & 1 deletion STATUS.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@
- [x] `addBusinessDays`
- [x] `addDays`
- [x] `subDays`
- [ ] `differenceInBusinessDays`
- [x] `differenceInBusinessDays`
- [x] `differenceInDays`
- [x] `differenceInCalendarDays`
- [x] `startOfDay`
Expand Down
72 changes: 72 additions & 0 deletions __tests__/differenceInBusinessDays_test.re
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
open Jest;

open Js.Date;

describe("differenceInBusinessDays", () => {
open ExpectJs;

test("returns 0 if the given dates are the same", () => {
let fstDate = makeWithYMD(~year=2018., ~month=0., ~date=1., ());
let sndDate = makeWithYMD(~year=2018., ~month=0., ~date=1., ());

fstDate
|> ReDate.differenceInBusinessDays(sndDate)
|> expect
|> toEqual(0);
});

test(
"returns the number of business days between the given dates, excluding weekends",
() => {
let fstDate = makeWithYMD(~year=2018., ~month=0., ~date=10., ());
let sndDate = makeWithYMD(~year=2018., ~month=0., ~date=2., ());

fstDate
|> ReDate.differenceInBusinessDays(sndDate)
|> expect
|> toEqual(6);
},
);

test(
"returns a negative number if the time value of the first date is smaller",
() => {
let fstDate = makeWithYMD(~year=2018., ~month=0., ~date=2., ());
let sndDate = makeWithYMD(~year=2018., ~month=0., ~date=10., ());

fstDate
|> ReDate.differenceInBusinessDays(sndDate)
|> expect
|> toEqual(-6);
});

test("returns a correct number when the first date falls on a weekend", () => {
let fstDate = makeWithYMD(~year=2019., ~month=6., ~date=20., ());
let sndDate = makeWithYMD(~year=2019., ~month=6., ~date=18., ());

fstDate
|> ReDate.differenceInBusinessDays(sndDate)
|> expect
|> toEqual(2);
});

test("returns a correct number when the second date falls on a weekend", () => {
let fstDate = makeWithYMD(~year=2019., ~month=6., ~date=23., ());
let sndDate = makeWithYMD(~year=2019., ~month=6., ~date=20., ());

fstDate
|> ReDate.differenceInBusinessDays(sndDate)
|> expect
|> toEqual(1);
});

test("returns a correct number when both dates fall on a weekend", () => {
let fstDate = makeWithYMD(~year=2019., ~month=6., ~date=28., ());
let sndDate = makeWithYMD(~year=2019., ~month=6., ~date=20., ());

fstDate
|> ReDate.differenceInBusinessDays(sndDate)
|> expect
|> toEqual(5);
});
});
13 changes: 13 additions & 0 deletions docs/day.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,19 @@ let sndDate = Js.Date.makeWithYMDHMS(~year=2018., ~month=0., ~date=2., ~hours=20
fstDate |> ReDate.differenceInDays(sndDate);
```

#### differenceInBusinessDays

> Get the number of full day periods between the given dates.
`let differenceInBusinessDays: (Js.Date.t, Js.Date.t) => int`

```reason
let fstDate = Js.Date.makeWithYMD(~year=2018., ~month=0., ~date=10., ());
let sndDate = Js.Date.makeWithYMD(~year=2018., ~month=0., ~date=2., ());
fstDate |> ReDate.differenceInBusinessDays(sndDate);
```

#### getDayOfYear

> Get the day of the year of the given date.
Expand Down
45 changes: 31 additions & 14 deletions src/ReDate.re
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ type differenceIn =
| Hours
| Minutes
| Days
| BusinessDays(helper)
| CalendarDays(helper)
| Weeks
| CalendarWeeks(helper)
Expand Down Expand Up @@ -151,6 +152,11 @@ module Internal = {
| _ => failwith("error")
);

let is = (day, date) =>
date |> Js.Date.getDay === (day |> dayToJs |> float_of_int);

let isWeekend = date => date |> is(Saturday) || date |> is(Sunday);

let rec differenceIn = (differenceType, snd, fst) =>
Js.Date.(
switch (differenceType) {
Expand All @@ -163,6 +169,17 @@ module Internal = {
((fst |> getTime) -. (snd |> getTime))
/. (differenceType |> getMillisecondsOf |> float_of_int);
diff > 0. ? diff |> Js.Math.floor_int : diff |> Js.Math.ceil_int;
| BusinessDays(startOf) =>
let diff = differenceIn(CalendarDays(startOf), snd, fst);
let date = diff < 0 ? fst : snd;
let result = ref(0);

for (index in 0 to diff |> Js.Math.abs_int |> pred) {
let day = date |> addDays(index);
result := isWeekend(day) ? result^ : result^ |> succ;
};

diff < 0 ? - result^ : result^;
| Months =>
let diff =
(fst |> getMonth)
Expand Down Expand Up @@ -256,9 +273,6 @@ module Internal = {
)
|> succ;

let is = (day, date) =>
date |> Js.Date.getDay === (day |> dayToJs |> float_of_int);

let minOrMaxOfArray = (fn, dates) =>
Belt.Array.reduce(dates, None, fn |> reduceMinOrMax) |> retrieveMinOrMax;

Expand Down Expand Up @@ -408,14 +422,14 @@ let roundToNearestMinute = (~nearestTo=1, date) => {
let closestTo = (date |> Js.Date.getSeconds) /. 60. |> Js.Math.round;
let closestMinute = (date |> Js.Date.getMinutes) +. closestTo;
let nearestRoundedMinute =
nearestTo !== 1 ?
(
(date |> Js.Date.getMinutes)
/. (nearestTo |> float_of_int)
|> Js.Math.round
)
*. (nearestTo |> float_of_int) :
closestMinute;
nearestTo !== 1
? (
(date |> Js.Date.getMinutes)
/. (nearestTo |> float_of_int)
|> Js.Math.round
)
*. (nearestTo |> float_of_int)
: closestMinute;

Js.Date.(
setMinutes(date |> Internal.makeDate, nearestRoundedMinute)
Expand Down Expand Up @@ -494,6 +508,9 @@ let differenceInCalendarDays =

let differenceInDays = Internal.differenceIn(Days);

let differenceInBusinessDays =
Internal.differenceIn(BusinessDays(startOfDay));

let getDayOfYear = date =>
date |> differenceInCalendarDays(date |> Internal.startOfYear) |> succ;

Expand Down Expand Up @@ -547,8 +564,8 @@ let getWeekOfMonth = (~weekStartsOn=Sunday, date) => {
let startWeekDay = date |> Internal.startOfMonth |> Js.Date.getDay;
let weekStartsOn' = weekStartsOn |> Internal.dayToJs |> float_of_int;
let diff =
startWeekDay < weekStartsOn' ?
7. -. weekStartsOn' +. startWeekDay : startWeekDay -. weekStartsOn';
startWeekDay < weekStartsOn'
? 7. -. weekStartsOn' +. startWeekDay : startWeekDay -. weekStartsOn';

((date |> Js.Date.getDate) +. diff) /. 7. |> Js.Math.ceil_int;
};
Expand Down Expand Up @@ -579,7 +596,7 @@ let isFriday = Internal.is(Friday);

let isSaturday = Internal.is(Saturday);

let isWeekend = date => date |> isSaturday || date |> isSunday;
let isWeekend = Internal.isWeekend;

/* β€”β€”[Month helpers]β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€” */

Expand Down
2 changes: 2 additions & 0 deletions src/ReDate.rei
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,8 @@ let differenceInCalendarDays: (Js.Date.t, Js.Date.t) => int;

let differenceInDays: (Js.Date.t, Js.Date.t) => int;

let differenceInBusinessDays: (Js.Date.t, Js.Date.t) => int;

let getDayOfYear: Js.Date.t => int;

let isSameDay: (Js.Date.t, Js.Date.t) => bool;
Expand Down

0 comments on commit 11a83d1

Please sign in to comment.