spreadsheet
typeScript/javascript spreadsheet parser, with formulas.
git clone https://git.vogt.world/spreadsheet.git
Log | Files | README.md
← Commit log
commit
message
[EOMONTH, README.md] formula written and tested, adding testing best-practices for readme
author
Ben Vogt <[email protected]>
date
2017-04-02 18:56:53
stats
4 file(s) changed, 85 insertions(+), 10 deletions(-)
files
README.md
src/RawFormulas/Date.ts
tests/DateFormulasTest.ts
tests/FormulasTest.ts
  1diff --git a/README.md b/README.md
  2index 8b7774b..f3512bf 100644
  3--- a/README.md
  4+++ b/README.md
  5@@ -64,3 +64,13 @@ Right now we're just using the number of days since 1900, but we should check th
  6 * Verify that all white-space wild cards are implemented properly
  7 
  8 * Verify that all N-times ({2,9}) are correct, and we're not parsing numbers too big.
  9+
 10+
 11+# Testing Guidelines
 12+
 13+All formulas should test for:
 14+1) One *less* argument than the formula expects, and one *more* argument than the formula expects.
 15+2) If it accepts a number, test with false as 0, and true as 1.
 16+3) If it accepts a number, test with string parsing to number.
 17+4) If it accepts a date, test with number, number as string, date as string.
 18+5) Individual arguments as ranges with single values (eg: `[1]`), and ranges as multiple values (eg: `[1, "str"]`).
 19diff --git a/src/RawFormulas/Date.ts b/src/RawFormulas/Date.ts
 20index 137b65d..a782a89 100644
 21--- a/src/RawFormulas/Date.ts
 22+++ b/src/RawFormulas/Date.ts
 23@@ -83,13 +83,29 @@ var EDATE = function (...values) : ExcelDate {
 24 };
 25 
 26 
 27+/**
 28+ * Returns a date representing the last day of a month which falls a specified number of months before or after another
 29+ * date.
 30+ * @param values[0] start_date - The date from which to calculate the the result.
 31+ * @param values[1] months - The number of months before (negative) or after (positive) start_date to consider. The last
 32+ * calendar day of the calculated month is returned.
 33+ * @returns {ExcelDate} the last day of a month
 34+ * @constructor
 35+ */
 36+var EOMONTH = function (...values) : ExcelDate {
 37+  ArgsChecker.checkLength(values, 2);
 38+  var startDate = TypeCaster.firstValueAsExcelDate(values[0]);
 39+  var months = Math.floor(TypeCaster.firstValueAsNumber(values[1]));
 40+  // While ExcelDate.toNumber() will return an inclusive count of days since 1900/1/1, moment.Moment.add assumes
 41+  // exclusive count of days.
 42+  return new ExcelDate(moment.utc(ORIGIN_MOMENT).add(startDate.toNumber() - 2, "days").add(months, "months").endOf("month"));
 43+};
 44+
 45+
 46 var DAY = Formula["DAY"];
 47 var DAYS = Formula["DAYS"];
 48 var DAYS360 = Formula["DAYS360"];
 49-var EOMONTH = function (start_date, months) {
 50-  var edate = moment(start_date).add(months, 'months');
 51-  return new Date(edate.year(), edate.month(), edate.daysInMonth());
 52-};
 53+
 54 var YEARFRAC = Formula["YEARFRAC"];
 55 
 56 // Functions unimplemented.
 57diff --git a/tests/DateFormulasTest.ts b/tests/DateFormulasTest.ts
 58index 6b6ba10..be9d600 100644
 59--- a/tests/DateFormulasTest.ts
 60+++ b/tests/DateFormulasTest.ts
 61@@ -1,5 +1,5 @@
 62 
 63-import { DATE, DATEVALUE, EDATE } from "../src/RawFormulas/RawFormulas"
 64+import { DATE, DATEVALUE, EDATE, EOMONTH } from "../src/RawFormulas/RawFormulas"
 65 import * as ERRORS from "../src/Errors"
 66 import {assertEquals} from "./utils/Asserts"
 67 import moment = require("moment");
 68@@ -19,25 +19,61 @@ function catchAndAssertEquals(toExecute, expected) {
 69   }
 70 }
 71 
 72-// // Test EDATE
 73+// Test EDATE
 74 assertEquals(EDATE(DATE(1992, 6, 24), 1), DATE(1992, 7, 24));
 75 assertEquals(EDATE(DATE(1992, 5, 24), 2), DATE(1992, 7, 24));
 76 assertEquals(EDATE(DATE(1992, 5, 24), 2.2), DATE(1992, 7, 24));
 77+assertEquals(EDATE(DATE(1992, 6, 24), 0), DATE(1992, 6, 24));
 78+assertEquals(EDATE(DATE(1992, 6, 24), false), DATE(1992, 6, 24));
 79 assertEquals(EDATE("1992, 5, 24", 2), DATE(1992, 7, 24));
 80 assertEquals(EDATE("6/24/92", 1), DATE(1992, 7, 24));
 81+assertEquals(EDATE([DATE(1992, 6, 24), "str"], [1, "str"]), DATE(1992, 7, 24));
 82 catchAndAssertEquals(function() {
 83   EDATE("str", 2);
 84 }, ERRORS.VALUE_ERROR);
 85+catchAndAssertEquals(function() {
 86+  EDATE(DATE(1992, 6, 24));
 87+}, ERRORS.NA_ERROR);
 88+catchAndAssertEquals(function() {
 89+  EDATE(DATE(1992, 6, 24), 4, 4);
 90+}, ERRORS.NA_ERROR);
 91+
 92+
 93+// Test EOMONTH
 94+assertEquals(EOMONTH(DATE(1992, 6, 24), 0), DATE(1992, 6, 30));
 95+assertEquals(EOMONTH(DATE(1992, 6, 24), false), DATE(1992, 6, 30));
 96+assertEquals(EOMONTH(DATE(1992, 6, 24), 1), DATE(1992, 7, 31));
 97+assertEquals(EOMONTH(DATE(1992, 6, 24), 2), DATE(1992, 8, 31));
 98+assertEquals(EOMONTH(DATE(2012, 6, 24), 2), DATE(2012, 8, 31));
 99+assertEquals(EOMONTH(DATE(2049, 1, 1), 2), DATE(2049, 3, 31));
100+assertEquals(EOMONTH(DATE(1990, 2, 24), 400), DATE(2023, 6, 30));
101+assertEquals(EOMONTH("1992, 6, 24", 2), DATE(1992, 8, 31));
102+//leap years
103+assertEquals(EOMONTH(DATE(2004, 2, 24), 0), DATE(2004, 2, 29));
104+assertEquals(EOMONTH(DATE(2008, 2, 24), 0), DATE(2008, 2, 29));
105+// misc.
106+assertEquals(EOMONTH([DATE(1992, 6, 24), "str"], [2, "str"]), DATE(1992, 8, 31));
107+catchAndAssertEquals(function() {
108+  EOMONTH("str", 2);
109+}, ERRORS.VALUE_ERROR);
110+catchAndAssertEquals(function() {
111+  EOMONTH(false, 2);
112+}, ERRORS.VALUE_ERROR);
113 
114 
115 // Test DATE
116 assertEquals(DATE(1900, 1, 2).toNumber(), 3);
117 assertEquals(DATE(1900, 1, 1).toNumber(), 2);
118 assertEquals(DATE(1900, 1, 4).toNumber(), 5);
119-
120 catchAndAssertEquals(function() {
121   DATE(1900, 0, 5);
122 }, ERRORS.NUM_ERROR);
123+catchAndAssertEquals(function() {
124+  DATE(1900, 0, 5, 22);
125+}, ERRORS.NA_ERROR);
126+catchAndAssertEquals(function() {
127+  DATE(1900, 0);
128+}, ERRORS.NA_ERROR);
129 assertEquals(DATE(1992, 6, 24).toNumber(), 33779);
130 assertEquals(DATE(2017, 2, 26).toNumber(), 42792);
131 assertEquals(DATE(1999, 1, 13).toNumber(), 36173);
132diff --git a/tests/FormulasTest.ts b/tests/FormulasTest.ts
133index 8acbc14..d49c1d6 100644
134--- a/tests/FormulasTest.ts
135+++ b/tests/FormulasTest.ts
136@@ -2,12 +2,12 @@ import { ABS, ACCRINT, ACOS, ACOSH, ACOTH, AND, ARABIC, ASIN, ASINH, ATAN, ATAN2
137     AVERAGEA, AVERAGEIF, BIN2DEC, BIN2HEX, BIN2OCT, CEILING,
138     CHAR, CODE, COMBIN, CONCATENATE, CONVERT, PEARSON,
139     CORREL, COS, PI, COSH, COT, COTH, COUNT, COUNTA, COUNTIF, COUNTIFS, COUNTUNIQUE,
140-    CUMIPMT, CUMPRINC, DATE, DATEVALUE, DAY, DAYS, DAYS360,
141-    DB, DDB, DEC2BIN, DEC2HEX, DEC2OCT, DEGREES, DELTA, DEVSQ, DOLLAR, DOLLARDE, DOLLARFR, EDATE,
142-    EFFECT, EOMONTH, ERF, ERFC, EVEN, EXACT, EXPONDIST, FINV, FALSE, FLOOR, __COMPLEX, FISHER, FISHERINV, IF,
143+    CUMIPMT, CUMPRINC,
144+    DB, DDB, DEC2BIN, DEC2HEX, DEC2OCT, DEGREES, DELTA, DEVSQ, DOLLAR, DOLLARDE, DOLLARFR,
145+    EFFECT, ERF, ERFC, EVEN, EXACT, EXPONDIST, FINV, FALSE, FLOOR, __COMPLEX, FISHER, FISHERINV, IF,
146     INT, ISEVEN, ISODD, LN, LOG, LOG10, MAX, MAXA, MEDIAN, MIN, MINA, MOD, NOT, TRUE, ODD, OR,
147     POWER, ROUND, ROUNDDOWN, ROUNDUP, SIN, SINH, SPLIT, SQRT, SQRTPI, SUM, SUMIF, SUMPRODUCT, RADIANS,
148-    SUMSQ, SUMX2MY2, SUMX2PY2, TAN, TANH, TRUNC, XOR, YEARFRAC } from "../src/RawFormulas/RawFormulas"
149+    SUMSQ, SUMX2MY2, SUMX2PY2, TAN, TANH, TRUNC, XOR } from "../src/RawFormulas/RawFormulas"
150 import * as ERRORS from "../src/Errors"
151 import {assertEquals, assertArrayEquals} from "./utils/Asserts"
152