spreadsheet
typeScript/javascript spreadsheet parser, with formulas.
git clone https://git.vogt.world/spreadsheet.git
Log | Files | README.md
← Commit log
commit
message
[DATEDIF] formula added and tested
author
Ben Vogt <[email protected]>
date
2017-04-15 18:33:53
stats
3 file(s) changed, 157 insertions(+), 24 deletions(-)
files
src/RawFormulas/Date.ts
src/RawFormulas/RawFormulas.ts
tests/DateFormulasTest.ts
  1diff --git a/src/RawFormulas/Date.ts b/src/RawFormulas/Date.ts
  2index 988f4c0..fdfff34 100644
  3--- a/src/RawFormulas/Date.ts
  4+++ b/src/RawFormulas/Date.ts
  5@@ -362,9 +362,79 @@ var WEEKNUM = function (...values) {
  6 };
  7 
  8 
  9+/**
 10+ * Calculates the number of days, months, or years between two dates.
 11+ * @param values[0] start_date - The start date to consider in the calculation. Must be a reference to a cell containing
 12+ * a DATE, a function returning a DATE type, or a number.
 13+ * @param values[1] end_date - The end date to consider in the calculation. Must be a reference to a cell containing a
 14+ * DATE, a function returning a DATE type, or a number.
 15+ * @param values[2] unit - A text abbreviation for unit of time. For example,"M" for month. Accepted values are "Y": the
 16+ * number of whole years between start_date and end_date, "M": the number of whole months between start_date and
 17+ * end_date, "D": the number of days between start_date and end_date, "MD": the number of days between start_date and
 18+ * end_date after subtracting whole months, "YM": the number of whole months between start_date and end_date after
 19+ * subtracting whole years, "YD": the number of days between start_date and end_date, assuming start_date and end_date
 20+ * were no more than one year apart.
 21+ * @returns {number} number of days, months, or years between two dates.
 22+ * @constructor
 23+ */
 24+var DATEDIF = function (...values) {
 25+  ArgsChecker.checkLength(values, 3);
 26+  var start = TypeCaster.firstValueAsExcelDate(values[0], true);
 27+  var end = TypeCaster.firstValueAsExcelDate(values[1], true);
 28+  var unit = TypeCaster.firstValueAsString(values[2]);
 29+  var unitClean = unit.toUpperCase();
 30+
 31+  if (start.toNumber() > end.toNumber()) {
 32+    throw new NumError("Function DATEDIF parameter 1 (" + start.toString() +
 33+        ") should be on or before Function DATEDIF parameter 2 (" + end.toString() + ").");
 34+  }
 35+
 36+  if (unitClean === "Y") {
 37+    return Math.floor(end.toMoment().diff(start.toMoment(), "years"));
 38+  } else if (unitClean === "M") {
 39+    return Math.floor(end.toMoment().diff(start.toMoment(), "months"));
 40+  } else if (unitClean === "D") {
 41+    return end.toNumber() - start.toNumber();
 42+  } else if (unitClean === "MD") {
 43+    var s = start.toMoment();
 44+    var e = end.toMoment();
 45+    while(s.isBefore(e)) {
 46+      s.add(1, "month");
 47+    }
 48+    s.subtract(1, "month");
 49+    var days = e.diff(s, "days");
 50+    return s.date() === e.date() ? 0 : days;
 51+  } else if (unitClean === "YM") {
 52+    var s = start.toMoment();
 53+    var e = end.toMoment();
 54+    while(s.isBefore(e)) {
 55+      s.add(1, "year");
 56+    }
 57+    s.subtract(1, "year");
 58+    var months = Math.floor(e.diff(s, "months"));
 59+    return months === 12 ? 0 : months;
 60+  } else if (unitClean === "YD") {
 61+    // var s = start.toMoment();
 62+    // var e = end.toMoment();
 63+    // var days = e.diff(s, "days");
 64+    // return days
 65+    var s = start.toMoment();
 66+    var e = end.toMoment();
 67+    while(s.isBefore(e)) {
 68+      s.add(1, "year");
 69+    }
 70+    s.subtract(1, "year");
 71+    var days = Math.floor(e.diff(s, "days"));
 72+    return days >= 365 ? 0 : days;
 73+  } else {
 74+    throw new NumError("Function DATEDIF parameter 3 value is " + unit +
 75+        ". It should be one of: 'Y', 'M', 'D', 'MD', 'YM', 'YD'.");
 76+  }
 77+};
 78+
 79+
 80 var YEARFRAC = Formula["YEARFRAC"];
 81 // Functions unimplemented.
 82-var DATEDIF;
 83 var HOUR;
 84 var MINUTE;
 85 var NETWORKDAYS;
 86@@ -382,6 +452,7 @@ var WORKDAY;
 87 export {
 88   DATE,
 89   DATEVALUE,
 90+  DATEDIF,
 91   DAYS,
 92   DAY,
 93   DAYS360,
 94diff --git a/src/RawFormulas/RawFormulas.ts b/src/RawFormulas/RawFormulas.ts
 95index f884677..96491c0 100644
 96--- a/src/RawFormulas/RawFormulas.ts
 97+++ b/src/RawFormulas/RawFormulas.ts
 98@@ -111,6 +111,7 @@ import {
 99 import {
100   DATE,
101   DATEVALUE,
102+  DATEDIF,
103   DAYS,
104   DAY,
105   DAYS360,
106@@ -244,5 +245,6 @@ export {
107   MONTH,
108   YEAR,
109   WEEKDAY,
110-  WEEKNUM
111+  WEEKNUM,
112+  DATEDIF
113 }
114\ No newline at end of file
115diff --git a/tests/DateFormulasTest.ts b/tests/DateFormulasTest.ts
116index 80d0056..15c8a05 100644
117--- a/tests/DateFormulasTest.ts
118+++ b/tests/DateFormulasTest.ts
119@@ -2,6 +2,7 @@
120 import {
121   DATE,
122   DATEVALUE,
123+  DATEDIF,
124   EDATE,
125   EOMONTH,
126   DAY,
127@@ -32,6 +33,84 @@ function catchAndAssertEquals(toExecute, expected) {
128 }
129 
130 
131+// Test DATEDIF
132+assertEquals(DATEDIF("1992-6-19", "1996-6-19", "Y"), 4);
133+assertEquals(DATEDIF("1992-6-19", "1996-6-0", "Y"), 3);
134+assertEquals(DATEDIF("1992-6-19", "1992-8-1", "Y"), 0);
135+assertEquals(DATEDIF("1992-6-19", "2199-8-1", "Y"), 207);
136+assertEquals(DATEDIF("1992-6-19", "1996-6-19", "M"), 48);
137+assertEquals(DATEDIF("1992-6-19", "1996-6-1", "M"), 47);
138+assertEquals(DATEDIF("1992-6-19", "1992-8-1", "M"), 1);
139+assertEquals(DATEDIF("1992-6-19", "2199-8-1", "M"), 2485);
140+assertEquals(DATEDIF("1992-6-19", "1996-6-19", "D"), 1461);
141+assertEquals(DATEDIF("1992-6-19", "1996-6-1", "D"), 1443);
142+assertEquals(DATEDIF("1992-6-19", "1992-8-1", "D"), 43);
143+assertEquals(DATEDIF("1992-6-19", "2199-8-1", "D"), 75648);
144+assertEquals(DATEDIF("1992-6-19", "2199-8-1", "MD"), 13);
145+assertEquals(DATEDIF("1992-6-19", "2012-7-22", "MD"), 3);
146+assertEquals(DATEDIF("1992-6-19", "1993-8-1", "MD"), 13);
147+assertEquals(DATEDIF("1992-6-19", "2000-1-19", "MD"), 0);
148+assertEquals(DATEDIF("1992-6-19", "2000-1-20", "MD"), 1);
149+assertEquals(DATEDIF("1992-6-19", "2000-1-21", "MD"), 2);
150+assertEquals(DATEDIF("1992-6-19", "2000-1-22", "MD"), 3);
151+assertEquals(DATEDIF("1992-6-19", "2000-1-23", "MD"), 4);
152+assertEquals(DATEDIF("1992-6-19", "2000-1-24", "MD"), 5);
153+assertEquals(DATEDIF("1992-6-19", "2000-1-25", "MD"), 6);
154+assertEquals(DATEDIF("1992-6-20", "2000-1-25", "MD"), 5);
155+assertEquals(DATEDIF("1992-6-19", "2199-8-1", "YM"), 1);
156+assertEquals(DATEDIF("1992-6-19", "2012-7-22", "YM"), 1);
157+assertEquals(DATEDIF("1992-6-19", "1993-8-1", "YM"), 1);
158+assertEquals(DATEDIF("1992-6-19", "2000-1-19", "YM"), 7);
159+assertEquals(DATEDIF("1992-6-19", "2000-1-20", "YM"), 7);
160+assertEquals(DATEDIF("1992-6-19", "2000-1-21", "YM"), 7);
161+assertEquals(DATEDIF("1992-6-19", "2000-1-22", "YM"), 7);
162+assertEquals(DATEDIF("1992-6-19", "2000-1-23", "YM"), 7);
163+assertEquals(DATEDIF("1992-6-19", "2000-1-24", "YM"), 7);
164+assertEquals(DATEDIF("1992-6-19", "2000-1-25", "YM"), 7);
165+assertEquals(DATEDIF("1992-6-20", "2000-1-25", "YM"), 7);
166+assertEquals(DATEDIF("1992-6-19", "1992-6-19", "YM"), 0);
167+assertEquals(DATEDIF("1992-6-19", "1992-7-19", "YM"), 1);
168+assertEquals(DATEDIF("1992-6-19", "1993-7-19", "YM"), 1);
169+assertEquals(DATEDIF("1992-6-19", "1993-6-19", "YM"), 0);
170+assertEquals(DATEDIF("1992-6-19", "2199-8-1", "YD"), 43);
171+assertEquals(DATEDIF("1992-6-19", "2012-7-22", "YD"), 33);
172+assertEquals(DATEDIF("1992-6-19", "1993-8-1", "YD"), 43);
173+assertEquals(DATEDIF("1992-6-19", "2000-1-19", "YD"), 214);
174+assertEquals(DATEDIF("1992-6-19", "2000-1-20", "YD"), 215);
175+assertEquals(DATEDIF("1992-6-19", "2000-1-21", "YD"), 216);
176+assertEquals(DATEDIF("1992-6-19", "2000-1-22", "YD"), 217);
177+assertEquals(DATEDIF("1992-6-19", "2000-1-23", "YD"), 218);
178+assertEquals(DATEDIF("1992-6-19", "2000-1-24", "YD"), 219);
179+assertEquals(DATEDIF("1992-6-19", "2000-1-25", "YD"), 220);
180+assertEquals(DATEDIF("1992-6-19", "1992-6-19", "YD"), 0);
181+assertEquals(DATEDIF("1992-6-19", "1992-7-19", "YD"), 30);
182+assertEquals(DATEDIF("1992-6-19", "1993-7-19", "YD"), 30);
183+assertEquals(DATEDIF("1992-6-19", "1993-6-19", "YD"), 0);
184+assertEquals(DATEDIF("1992-6-19", "1993-6-19", "yd"), 0);
185+assertEquals(DATEDIF(["1992-6-19", "str"], ["1993-6-19", []], ["yd"]), 0);
186+catchAndAssertEquals(function() {
187+  DATEDIF("1996-6-19", "1992-6-19", "Y");
188+}, ERRORS.NUM_ERROR);
189+catchAndAssertEquals(function() {
190+  DATEDIF("1992-6-19", "1995-6-19", "Y ");
191+}, ERRORS.NUM_ERROR);
192+catchAndAssertEquals(function() {
193+  DATEDIF("1992-6-19", "1995-6-19", "mm");
194+}, ERRORS.NUM_ERROR);
195+catchAndAssertEquals(function() {
196+  DATEDIF();
197+}, ERRORS.NA_ERROR);
198+catchAndAssertEquals(function() {
199+  DATEDIF("1992-6-19", "1995-6-19", "mm", 0);
200+}, ERRORS.NA_ERROR);
201+catchAndAssertEquals(function() {
202+  DATEDIF("str", "1995-6-19", "mm");
203+}, ERRORS.VALUE_ERROR);
204+catchAndAssertEquals(function() {
205+  DATEDIF([], "1995-6-19", "mm");
206+}, ERRORS.REF_ERROR);
207+
208+
209 // Test WEEKNUM
210 assertEquals(WEEKNUM(DATE(1992, 6, 19)), 25);
211 assertEquals(WEEKNUM(DATE(1992, 6, 20)), 25);
212@@ -576,29 +655,6 @@ catchAndAssertEquals(function() {
213 }, ERRORS.NUM_ERROR);
214 
215 
216-
217-
218-
219-
220-
221-
222-
223-
224-
225-
226-
227-
228-
229-
230-
231-
232-
233-
234-
235-
236-
237-
238-
239 // Test WEEKDAY
240 assertEquals(WEEKDAY(DATE(1992, 6, 20)), 7);
241 assertEquals(WEEKDAY(DATE(1992, 6, 21)), 1);