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

Commit

Permalink
✨ Add closestToArray and closestToList
Browse files Browse the repository at this point in the history
  • Loading branch information
mobily committed Feb 9, 2019
1 parent f29a923 commit c2a384b
Show file tree
Hide file tree
Showing 4 changed files with 209 additions and 0 deletions.
87 changes: 87 additions & 0 deletions __tests__/closestToArray_test.re
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
open Jest;

open Js.Date;

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

test(
"returns the date from the given array closest to the given date #1", () => {
let date = makeWithYMD(~year=2018., ~month=0., ~date=1., ());

let a = makeWithYMD(~year=1999., ~month=0., ~date=1., ());
let b = makeWithYMD(~year=2018., ~month=2., ~date=1., ());
let c = makeWithYMD(~year=2020., ~month=4., ~date=1., ());
let d = makeWithYMD(~year=2022., ~month=12., ~date=1., ());

let dates = [|a, b, c, d|];

date |> ReDate.closestToArray(dates) |> expect |> toEqual(Some(b));
});

test(
"returns the date from the given array closest to the given date #2", () => {
let date =
makeWithYMDHMS(
~year=2019.,
~month=0.,
~date=1.,
~hours=8.,
~minutes=45.,
~seconds=15.,
(),
);

let a =
makeWithYMDHMS(
~year=2019.,
~month=0.,
~date=1.,
~hours=8.,
~minutes=50.,
~seconds=0.,
(),
);
let b =
makeWithYMDHMS(
~year=2019.,
~month=0.,
~date=1.,
~hours=8.,
~minutes=45.,
~seconds=20.,
(),
);
let c =
makeWithYMDHMS(
~year=2019.,
~month=0.,
~date=1.,
~hours=8.,
~minutes=45.,
~seconds=19.,
(),
);
let d =
makeWithYMDHMS(
~year=2019.,
~month=0.,
~date=1.,
~hours=8.,
~minutes=45.,
~seconds=13.,
(),
);

let dates = [|a, b, c, d|];

date |> ReDate.closestToArray(dates) |> expect |> toEqual(Some(d));
});

test("returns `None` if the given array is empty", () => {
let date = makeWithYMD(~year=2018., ~month=0., ~date=2., ());
let dates = [||];

date |> ReDate.closestToArray(dates) |> expect |> toEqual(None);
});
});
85 changes: 85 additions & 0 deletions __tests__/closestToList_test.re
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
open Jest;

open Js.Date;

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

test("returns the date from the given list closest to the given date #1", () => {
let date = makeWithYMD(~year=2018., ~month=0., ~date=1., ());

let a = makeWithYMD(~year=1999., ~month=0., ~date=1., ());
let b = makeWithYMD(~year=2018., ~month=2., ~date=1., ());
let c = makeWithYMD(~year=2020., ~month=4., ~date=1., ());
let d = makeWithYMD(~year=2022., ~month=12., ~date=1., ());

let dates = [a, b, c, d];

date |> ReDate.closestToList(dates) |> expect |> toEqual(Some(b));
});

test("returns the date from the given list closest to the given date #2", () => {
let date =
makeWithYMDHMS(
~year=2019.,
~month=0.,
~date=1.,
~hours=8.,
~minutes=45.,
~seconds=15.,
(),
);

let a =
makeWithYMDHMS(
~year=2019.,
~month=0.,
~date=1.,
~hours=8.,
~minutes=50.,
~seconds=0.,
(),
);
let b =
makeWithYMDHMS(
~year=2019.,
~month=0.,
~date=1.,
~hours=8.,
~minutes=45.,
~seconds=20.,
(),
);
let c =
makeWithYMDHMS(
~year=2019.,
~month=0.,
~date=1.,
~hours=8.,
~minutes=45.,
~seconds=19.,
(),
);
let d =
makeWithYMDHMS(
~year=2019.,
~month=0.,
~date=1.,
~hours=8.,
~minutes=45.,
~seconds=13.,
(),
);

let dates = [a, b, c, d];

date |> ReDate.closestToList(dates) |> expect |> toEqual(Some(d));
});

test("returns `None` if the given list is empty", () => {
let date = makeWithYMD(~year=2018., ~month=0., ~date=2., ());
let dates = [];

date |> ReDate.closestToList(dates) |> expect |> toEqual(None);
});
});
33 changes: 33 additions & 0 deletions src/ReDate.re
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@ type differenceIn =
| Years
| CalendarYears;

type closestTo = {
distance: option(float),
date: option(Js.Date.t),
};

module Milliseconds = {
let second = 1000;

Expand Down Expand Up @@ -268,6 +273,22 @@ module Internal = {

let lastDayOfMonth = date =>
date |> makeLastDayOfMonth |> makeDateWithStartOfDayHours;

let closestTo = (date, acc, dateToCompare) => {
let distance =
Js.Math.abs_float(
(date |> Js.Date.getTime) -. (dateToCompare |> Js.Date.getTime),
);
let result = {date: Some(dateToCompare), distance: Some(distance)};

Belt.Option.mapWithDefault(acc.distance, result, minDistance =>
distance < minDistance ? result : acc
);
};

let defaultClosestToDate = {date: None, distance: None};

let retrieveClosestToDate = currentDate => currentDate.date;
};

/* β€”β€”[Common helpers]β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€” */
Expand Down Expand Up @@ -335,6 +356,18 @@ let endOfSecond = date =>
let isSameSecond = (fst, snd) =>
fst |> startOfSecond |> isEqual(snd |> startOfSecond);

let closestToArray = (datesToCompare, date) =>
Internal.(
Belt.Array.reduce(datesToCompare, defaultClosestToDate, closestTo(date))
|> retrieveClosestToDate
);

let closestToList = (datesToCompare, date) =>
Internal.(
Belt.List.reduce(datesToCompare, defaultClosestToDate, closestTo(date))
|> retrieveClosestToDate
);

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

let addMinutes = (minutes, date) =>
Expand Down
4 changes: 4 additions & 0 deletions src/ReDate.rei
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@ let isValid:
) =>
bool;

let closestToArray: (array(Js.Date.t), Js.Date.t) => option(Js.Date.t);

let closestToList: (list(Js.Date.t), Js.Date.t) => option(Js.Date.t);

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

let addSeconds: (int, Js.Date.t) => Js.Date.t;
Expand Down

0 comments on commit c2a384b

Please sign in to comment.