calcdate
Version:
Evalate a date expression calc`now + 3 days`)!
830 lines (798 loc) • 27.6 kB
JavaScript
import parser from "../dateCalculator";
import { test as testbinding } from "../bindings/testbindings";
const it = test;
describe("Timezones", () => {
it("should always be UTC", () => {
expect(new Date().getTimezoneOffset()).toBe(0);
});
});
it("Instanciation works", () => {
expect(testbinding()({}, {})).toEqual({});
expect(parser(testbinding()(parser, {}))).toBeInstanceOf(Function);
});
describe("Parsing without a binding", () => {
const RealDate = Date;
let calculator;
const operations = {};
beforeAll(() => {
const DATE_TO_USE = new Date();
global.Date = jest.fn((str, ...args) => {
if (!str) return DATE_TO_USE;
return new RealDate(str, ...args);
});
global.Date.UTC = RealDate.UTC;
global.Date.parse = RealDate.parse;
global.Date.now = RealDate.now;
});
beforeEach(() => {
operations.makeInterval = jest.fn(interval => ({ interval }));
operations.makeDuration = jest.fn(duration => ({ duration }));
operations.makeDate = jest.fn(date => ({ date }));
operations.add = jest.fn((a, b) => ({ add: [a, b] }));
operations.subtract = jest.fn((a, b) => ({ subtract: [a, b] }));
operations.multiply = jest.fn((a, b) => ({ multiply: [a, b] }));
operations.divide = jest.fn((a, b) => ({ divide: [a, b] }));
calculator = parser(testbinding()(parser, operations));
/*
const xcalc = parser(testbinding()(parser, operations));
calculator = (a, ...args) => {
try {
return xcalc(a, ...args);
} catch (e) {
console.error(
`Failed on ${args.map((i, idx) => `${a[idx]}${i}`).join("")}${
args[args.length - 1]
}`
);
throw e;
}
};
*/
});
afterEach(() => {
calculator = null;
});
afterAll(() => {
global.Date = RealDate;
});
it(" returns new date for 'now'", () => {
expect(calculator`now`).toEqual({ date: new Date() });
expect(calculator("now")).toEqual({ date: new Date() });
});
it(" returns string-interpolations literally", () => {
expect(calculator`${"now"}`).toEqual({ date: new Date() });
});
it(" returns other interpolations as-is", () => {
expect(calculator`${["Hello World"]}`).toEqual(["Hello World"]);
});
it(" throw when invalid input is supplied", () => {
expect(() => calculator``).toThrow();
expect(() => calculator`Hello World`).toThrow();
expect(() => calculator()).toThrow();
expect(() => calculator("Hello World")).toThrow();
});
it(" parses unitless numbers", () => {
expect(calculator`1`).toEqual({ unitless: 1 });
expect(calculator`1u`).toEqual({ unitless: 1 });
});
const durationIdentifiers = {
millisecond: ["ms"],
second: ["s", "S", "ss", "SS", "sec", "SEC"],
minute: ["min", "tm", "mm", "MIN", "TM"],
hour: ["h", "H"],
day: ["d", "D"],
weekday: ["wd", "WD"],
week: ["w", "W"],
month: ["M", "MM", "l", "L"],
quarter: ["q", "Q"],
year: ["y", "a", "Y", "A"]
};
describe("Singular long-form duration identifiers", () => {
Object.keys(durationIdentifiers).forEach(key => {
["", " ", "\n", "\r", "\t", " \n\r\t"].forEach(whitespace => {
const whitespaceDescription = whitespace
.split("")
.map(
i =>
({
" ": "_",
"\t": "\\t",
"\n": "\\n",
"\r": "\\r"
}[i])
)
.join("");
it(` parses "${key}" with whitespace "${whitespaceDescription}" correctly`, () => {
expect(calculator`1${whitespace}${key}`).toEqual({
duration: {
[`${key}s`]: 1
}
});
expect(calculator`0${whitespace}${key}`).toEqual({
duration: {
[`${key}s`]: 0
}
});
expect(calculator`2${whitespace}${key}`).toEqual({
duration: {
[`${key}s`]: 2
}
});
expect(calculator`10000${whitespace}${key}`).toEqual({
duration: {
[`${key}s`]: 10000
}
});
expect(() => calculator`-1${whitespace}${key}`).toThrow();
expect(() => calculator`n${whitespace}${key}`).toThrow();
});
});
});
});
describe("Plural long-form duration identifiers", () => {
Object.keys(durationIdentifiers).forEach(key => {
["", " ", " ", "\t", "\t\t", "\t \t ", "\n", " \n \t"].forEach(
whitespace => {
const whitespaceDescription = whitespace
.split("")
.map(
i =>
({
" ": "_",
"\t": "\\t",
"\n": "\\n"
}[i])
)
.join("");
it(` parses "${key}" with whitespace "${whitespaceDescription}" correctly`, () => {
expect(calculator`1${whitespace}${key}s`).toEqual({
duration: {
[`${key}s`]: 1
}
});
expect(calculator`0${whitespace}${key}s`).toEqual({
duration: {
[`${key}s`]: 0
}
});
expect(calculator`2${whitespace}${key}s`).toEqual({
duration: {
[`${key}s`]: 2
}
});
expect(calculator`10000${whitespace}${key}s`).toEqual({
duration: {
[`${key}s`]: 10000
}
});
expect(() => calculator`-1${whitespace}${key}s`).toThrow();
expect(() => calculator`n${whitespace}${key}s`).toThrow();
});
}
);
});
});
describe("Singular short-form duration identifiers", () => {
Object.entries(durationIdentifiers).forEach(([ident, keys]) => {
["", " ", " ", "\t", "\t\t", "\t \t ", "\n", " \n \t"].forEach(
whitespace => {
const whitespaceDescription = whitespace
.split("")
.map(
i =>
({
" ": "_",
"\t": "\\t",
"\n": "\\n"
}[i])
)
.join("");
keys.forEach(key => {
it(` parses "${key}" (${ident}) with whitespace "${whitespaceDescription}" correctly`, () => {
expect(calculator`1${whitespace}${key}`).toEqual({
duration: {
[`${ident}s`]: 1
}
});
expect(calculator`0${whitespace}${key}`).toEqual({
duration: {
[`${ident}s`]: 0
}
});
expect(calculator`2${whitespace}${key}`).toEqual({
duration: {
[`${ident}s`]: 2
}
});
expect(calculator`10000${whitespace}${key}`).toEqual({
duration: {
[`${ident}s`]: 10000
}
});
expect(() => calculator`-1${whitespace}${key}`).toThrow();
expect(() => calculator`n${whitespace}${key}`).toThrow();
});
});
}
);
});
});
describe("Recognizes '+'", () => {
const cop = "add";
it(" calls binding callbacks for two operands", () => {
const mockCallback = operations[cop];
const duration = operations.makeDuration;
const result = calculator`1d + 1d`;
expect(mockCallback.mock.calls.length).toBe(1);
expect(duration.mock.calls.length).toBe(2);
expect(duration.mock.calls[0][0]).toEqual({ days: 1 });
expect(duration.mock.calls[0][1]).toEqual({
type: parser.DURATIONOBJECT
});
expect(duration.mock.calls[1][0]).toEqual({ days: 1 });
expect(duration.mock.calls[1][1]).toEqual({
type: parser.DURATIONOBJECT
});
expect(mockCallback.mock.calls[0][0]).toBe(
duration.mock.results[0].value
);
expect(mockCallback.mock.calls[0][1]).toBe(
duration.mock.results[1].value
);
expect(result).toEqual({
[cop]: [duration.mock.results[0].value, duration.mock.results[1].value]
});
});
it(" calls binding callbacks for many operands", () => {
const mockCallback = operations[cop];
const duration = operations.makeDuration;
const result = calculator`1min + 1s + 1d + 1h`;
expect(mockCallback.mock.calls.length).toBe(3);
expect(duration.mock.calls.length).toBe(4);
// Left-to-right evaluation
expect(mockCallback.mock.calls[0][0]).toBe(
duration.mock.results[0].value
);
expect(mockCallback.mock.calls[0][1]).toBe(
duration.mock.results[1].value
);
expect(mockCallback.mock.calls[1][0]).toBe(
mockCallback.mock.results[0].value
);
expect(mockCallback.mock.calls[1][1]).toBe(
duration.mock.results[2].value
);
expect(mockCallback.mock.calls[2][0]).toBe(
mockCallback.mock.results[1].value
);
expect(mockCallback.mock.calls[2][1]).toBe(
duration.mock.results[3].value
);
expect(result).toEqual({
[cop]: [
mockCallback.mock.results[1].value,
duration.mock.results[3].value
]
});
});
});
describe("Recognizes '-'", () => {
const cop = "subtract";
it(" calls binding callbacks for two operands", () => {
const mockCallback = operations[cop];
const duration = operations.makeDuration;
const result = calculator`1d - 1d`;
expect(mockCallback.mock.calls.length).toBe(1);
expect(duration.mock.calls.length).toBe(2);
expect(duration.mock.calls[0][0]).toEqual({ days: 1 });
expect(duration.mock.calls[0][1]).toEqual({
type: parser.DURATIONOBJECT
});
expect(duration.mock.calls[1][0]).toEqual({ days: 1 });
expect(duration.mock.calls[1][1]).toEqual({
type: parser.DURATIONOBJECT
});
expect(mockCallback.mock.calls[0][0]).toBe(
duration.mock.results[0].value
);
expect(mockCallback.mock.calls[0][1]).toBe(
duration.mock.results[1].value
);
expect(result).toEqual({
[cop]: [duration.mock.results[0].value, duration.mock.results[1].value]
});
});
it(" calls binding callbacks for many operands", () => {
const mockCallback = operations[cop];
const duration = operations.makeDuration;
const result = calculator`1min - 1s - 1d - 1h`;
expect(mockCallback.mock.calls.length).toBe(3);
expect(duration.mock.calls.length).toBe(4);
// Left-to-right evaluation
expect(mockCallback.mock.calls[0][0]).toBe(
duration.mock.results[0].value
);
expect(mockCallback.mock.calls[0][1]).toBe(
duration.mock.results[1].value
);
expect(mockCallback.mock.calls[1][0]).toBe(
mockCallback.mock.results[0].value
);
expect(mockCallback.mock.calls[1][1]).toBe(
duration.mock.results[2].value
);
expect(mockCallback.mock.calls[2][0]).toBe(
mockCallback.mock.results[1].value
);
expect(mockCallback.mock.calls[2][1]).toBe(
duration.mock.results[3].value
);
expect(result).toEqual({
[cop]: [
mockCallback.mock.results[1].value,
duration.mock.results[3].value
]
});
});
});
describe("Recognizes '*'", () => {
const cop = "multiply";
it(" calls binding callbacks for two operands", () => {
const mockCallback = operations[cop];
const duration = operations.makeDuration;
const result = calculator`1d * 1d`;
expect(mockCallback.mock.calls.length).toBe(1);
expect(duration.mock.calls.length).toBe(2);
expect(duration.mock.calls[0][0]).toEqual({ days: 1 });
expect(duration.mock.calls[0][1]).toEqual({
type: parser.DURATIONOBJECT
});
expect(duration.mock.calls[1][0]).toEqual({ days: 1 });
expect(duration.mock.calls[1][1]).toEqual({
type: parser.DURATIONOBJECT
});
expect(mockCallback.mock.calls[0][0]).toBe(
duration.mock.results[0].value
);
expect(mockCallback.mock.calls[0][1]).toBe(
duration.mock.results[1].value
);
expect(result).toEqual({
[cop]: [duration.mock.results[0].value, duration.mock.results[1].value]
});
});
it(" calls binding callbacks for many operands", () => {
const mockCallback = operations[cop];
const duration = operations.makeDuration;
const result = calculator`1min * 1s * 1d * 1h`;
expect(mockCallback.mock.calls.length).toBe(3);
expect(duration.mock.calls.length).toBe(4);
// Left-to-right evaluation
expect(mockCallback.mock.calls[0][0]).toBe(
duration.mock.results[0].value
);
expect(mockCallback.mock.calls[0][1]).toBe(
duration.mock.results[1].value
);
expect(mockCallback.mock.calls[1][0]).toBe(
mockCallback.mock.results[0].value
);
expect(mockCallback.mock.calls[1][1]).toBe(
duration.mock.results[2].value
);
expect(mockCallback.mock.calls[2][0]).toBe(
mockCallback.mock.results[1].value
);
expect(mockCallback.mock.calls[2][1]).toBe(
duration.mock.results[3].value
);
expect(result).toEqual({
[cop]: [
mockCallback.mock.results[1].value,
duration.mock.results[3].value
]
});
});
});
describe("Recognizes '/'", () => {
const cop = "divide";
it(" calls binding callbacks for two operands", () => {
const mockCallback = operations[cop];
const duration = operations.makeDuration;
const result = calculator`1d / 1d`;
expect(mockCallback.mock.calls.length).toBe(1);
expect(duration.mock.calls.length).toBe(2);
expect(duration.mock.calls[0][0]).toEqual({ days: 1 });
expect(duration.mock.calls[0][1]).toEqual({
type: parser.DURATIONOBJECT
});
expect(duration.mock.calls[1][0]).toEqual({ days: 1 });
expect(duration.mock.calls[1][1]).toEqual({
type: parser.DURATIONOBJECT
});
expect(mockCallback.mock.calls[0][0]).toBe(
duration.mock.results[0].value
);
expect(mockCallback.mock.calls[0][1]).toBe(
duration.mock.results[1].value
);
expect(result).toEqual({
[cop]: [duration.mock.results[0].value, duration.mock.results[1].value]
});
});
it(" calls binding callbacks for many operands", () => {
const mockCallback = operations[cop];
const duration = operations.makeDuration;
const result = calculator`1min / 1s / 1d / 1h`;
expect(mockCallback.mock.calls.length).toBe(3);
expect(duration.mock.calls.length).toBe(4);
// Left-to-right evaluation
expect(mockCallback.mock.calls[0][0]).toBe(
duration.mock.results[0].value
);
expect(mockCallback.mock.calls[0][1]).toBe(
duration.mock.results[1].value
);
expect(mockCallback.mock.calls[1][0]).toBe(
mockCallback.mock.results[0].value
);
expect(mockCallback.mock.calls[1][1]).toBe(
duration.mock.results[2].value
);
expect(mockCallback.mock.calls[2][0]).toBe(
mockCallback.mock.results[1].value
);
expect(mockCallback.mock.calls[2][1]).toBe(
duration.mock.results[3].value
);
expect(result).toEqual({
[cop]: [
mockCallback.mock.results[1].value,
duration.mock.results[3].value
]
});
});
});
describe("Recognizes '()'", () => {
const cop = "add";
it(" calls binding callbacks for two operands", () => {
const mockCallback = operations[cop];
const duration = operations.makeDuration;
const result = calculator`1s + (1min + 1d)`;
expect(mockCallback.mock.calls.length).toBe(2);
expect(duration.mock.calls.length).toBe(3);
// right first, then left-to-right
expect(mockCallback.mock.calls[0][0]).toBe(
duration.mock.results[1].value
);
expect(mockCallback.mock.calls[0][1]).toBe(
duration.mock.results[2].value
);
expect(mockCallback.mock.calls[1][0]).toBe(
duration.mock.results[0].value
);
expect(mockCallback.mock.calls[1][1]).toBe(
mockCallback.mock.results[0].value
);
expect(result).toEqual({
add: [
duration.mock.results[0].value,
mockCallback.mock.results[0].value
]
});
});
it(" applys '*' and '/' before '+' and '-'", () => {
const result1 = calculator`1s + 1min * 1d`;
expect(result1).toEqual({
add: [
operations.makeDuration.mock.results[0].value,
operations.multiply.mock.results[0].value
]
});
const result2 = calculator`1s - 1min / 1d`;
expect(result2).toEqual({
subtract: [
operations.makeDuration.mock.results[0].value,
operations.divide.mock.results[0].value
]
});
});
it(" applys '()' first", () => {
const result1 = calculator`(1s + 1min) * 1d`;
expect(result1).toEqual({
multiply: [
operations.add.mock.results[0].value,
operations.makeDuration.mock.results[2].value
]
});
const result2 = calculator`(1s - 1min) / 1d`;
expect(result2).toEqual({
divide: [
operations.subtract.mock.results[0].value,
operations.makeDuration.mock.results[2].value
]
});
});
});
describe("Parses iso-dates", () => {
const extended = [
"2009-12T12:34",
"2009",
"2009-05-19",
" 2009-05-19 ",
"2009-05",
"2009-001",
"2009-05-19",
"2009-05-19T00:00",
"2009-05-19T14:31",
"2009-05-19T14:39:22",
"2009-05-19T14:39Z",
"2009-05-19T14:39:22-06:00",
"2009-05-19T14:39:22+0600",
"2007-04-06T00:00"
];
const iso = [
"200912T1234",
"2009",
"20090519",
" 20090519 ",
"200905",
"2009001",
"20090519",
"20090519 0000",
"20090519 1431",
"20090519 143922",
"20090519 1439Z",
"20090519 143922-06:00",
"20090519 143922+0600",
"20070406 0000"
];
extended.forEach(i =>
it(` parse "${i}" successfully`, () => {
const result = calculator`${i}`;
expect(result).toBeDefined();
expect(`${i} = ${result.date.getTime()}`).toMatchSnapshot();
})
);
iso.forEach((i, idx) =>
it(` parse "${i}" successfully`, () => {
const result = calculator`${i}`;
expect(result).toBeDefined();
expect(`${i} = ${result.date.getTime()}`).toMatchSnapshot();
})
);
const invalidisos = [
"200913",
"2009367",
"2009-",
"20070405T24:50",
// "2009-000", // subtract operation!! -> valid input
"2009-M511",
"2009M511",
"2009-05-19T14a39r",
"2009-05-1914:39",
"2009-05-19 14:",
"2009-05-19r14:39",
"2009-05-19 14a39a22",
"2009-05-19 14:39:22+06a00",
"2009-05-19 146922.500",
"2010-02-18T16.5:23.35:48",
"2010-02-18T16:23.35:48",
"2010-02-18T16:23.35:48.45",
"2009-05-19 14.5.44",
"2010-02-18T16:23.33.600",
"2010-02-18T16,25:23:48,444"
];
invalidisos.forEach((i, idx) =>
it(` throws on "${i}"`, () => {
const result = () => calculator`${i}`;
expect(result).toThrow();
})
);
});
describe("Parses iso-durations", () => {
const durations = [
"P1Y2M3DT4H05M600S", // 1 year, 2 months, 3 days, 4 hours, 5 minutes, 600 seconds
"PT3H5M", // 3 hours, 5 minus
"P1Y", // 1 year
"P-1Y1M", // -1 year, 1 month -> effectively 11 month
"P1DT-30S", // 1 day, -30 seconds
"P1Y",
"P2M",
"P3D",
"PT4H",
"PT05M",
"PT600S",
"P1y2m3dT4h5m6s",
"P00021015T103020",
"P00021015",
"P0002-10-15T10:30:20",
"P0002-10-15",
"+P00021015T103020",
"+P00021015",
"+P0002-10-15T10:30:20",
"+P0002-10-15",
"-P00021015T103020",
"-P00021015",
"-P0002-10-15T10:30:20",
"-P0002-10-15",
"P+00021015T103020",
"P0002-1015",
"P0002--10-15T10:+30:20",
"P0002-10--15",
"-P0002-10--15"
];
durations.forEach(i =>
it(` parse "${i}" successfully`, () => {
const result = calculator`${i}`;
expect(result).toBeDefined();
expect(`${i} = ${JSON.stringify(result.duration)}`).toMatchSnapshot();
})
);
});
describe("Parses iso-intervals", () => {
const durations = [
"P1Y2M3DT4H05M600S", // 1 year, 2 months, 3 days, 4 hours, 5 minutes, 600 seconds
"PT3H5M", // 3 hours, 5 minus
"P1Y", // 1 year
"P-1Y1M", // -1 year, 1 month -> effectively 11 month
"P1DT-30S", // 1 day, -30 seconds
"P1Y",
"P2M",
"P3D",
"PT4H",
"PT05M",
"PT600S",
"P1y2m3dT4h5m6s",
"P00021015T103020",
"P00021015",
"P0002-10-15T10:30:20",
"P0002-10-15",
"+P00021015T103020",
"+P00021015",
"+P0002-10-15T10:30:20",
"+P0002-10-15",
"-P00021015T103020",
"-P00021015",
"-P0002-10-15T10:30:20",
"-P0002-10-15",
"P+00021015T103020",
"P0002-1015",
"P0002--10-15T10:+30:20",
"P0002-10--15",
"-P0002-10--15"
];
const dates = [
"2009-12T12:34",
"2009",
"2009-05-19",
"2009-05",
"2009-001",
"2009-05-19",
"2009-05-19T00:00",
"2009-05-19T14:31",
"2009-05-19T14:39:22",
"2009-05-19T14:39Z",
"2009-05-19T14:39:22-06:00",
"2009-05-19T14:39:22+0600",
"2007-04-06T00:00",
"200912T1234",
"2009",
"20090519",
"200905",
"2009001",
"20090519",
"20090519 0000",
"20090519 1431",
"20090519 143922",
"20090519 1439Z",
"20090519 143922-06:00",
"20090519 143922+0600",
"20070406 0000"
];
// durations
// dates
dates.forEach(a => {
it(` parse "${a}/date" successfully`, () => {
dates.forEach(b => {
if (a === b) return;
const result = calculator`${a}/${b}`;
expect(result).toBeDefined();
expect(result.interval[0].date).toBeDefined();
expect(result.interval[1].date).toBeDefined();
expect(
`${a}/${b} = ${result.interval[0].date.getTime()}/${result.interval[1].date.getTime()}`
).toMatchSnapshot();
});
});
});
durations.forEach(duration => {
it(` parse "date/${duration}" and "${duration}/date" successfully`, () => {
dates.forEach(date => {
const result = calculator`${date}/${duration}`;
expect(result).toBeDefined();
expect(result.interval[0].date).toBeDefined();
expect(result.interval[1].duration).toBeDefined();
expect(
`${date}/${duration} = ${result.interval[0].date.getTime()}/${JSON.stringify(
result.interval[1].duration
)}`
).toMatchSnapshot();
const result2 = calculator`${duration}/${date}`;
expect(result2).toBeDefined();
expect(result2.interval[0].duration).toBeDefined();
expect(result2.interval[1].date).toBeDefined();
expect(
`${duration}/${date} = ${JSON.stringify(
result2.interval[0].duration
)}/${result2.interval[1].date.getTime()}`
).toMatchSnapshot();
});
});
});
});
describe("can handle 'unitless' numbers", () => {
it("Can parse unitless", () => {
expect(calculator`1`).toEqual({ unitless: 1 });
expect(calculator`2`).toEqual({ unitless: 2 });
expect(calculator`0`).toEqual({ unitless: 0 });
expect(calculator`5`).toEqual({ unitless: 5 });
expect(calculator`100`).toEqual({ unitless: 100 });
expect(calculator`-1`).toEqual({ unitless: -1 });
expect(calculator`-0`).toEqual({ unitless: -0 });
expect(calculator`-100`).toEqual({ unitless: -100 });
expect(calculator`01`).toEqual({ unitless: 1 });
expect(calculator`-01`).toEqual({ unitless: -1 });
expect(calculator`1`).toEqual({ unitless: 1 });
expect(calculator`0`).toEqual({ unitless: 0 });
expect(calculator`100`).toEqual({ unitless: 100 });
// expect(calculator`70000`).toEqual({ unitless: 70000 });
expect(calculator`-10`).toEqual({ unitless: -10 });
expect(calculator`-5`).toEqual({ unitless: -5 });
expect(calculator`0`).toEqual({ unitless: 0 });
// expect(calculator`00001`).toEqual({ unitless: 1 });
// expect(calculator`00123901`).toEqual({ unitless: 123901 });
expect(calculator`-09`).toEqual({ unitless: -9 });
expect(calculator`2.5`).toEqual({ unitless: 2.5 });
expect(calculator`-2.5`).toEqual({ unitless: -2.5 });
expect(calculator`1.0`).toEqual({ unitless: 1 });
expect(calculator`-1.0`).toEqual({ unitless: -1 });
expect(calculator`06.6`).toEqual({ unitless: 6.6 });
expect(calculator`-006.089`).toEqual({ unitless: -6.089 });
});
});
describe("Parses dates, durations and intervals in all combinations and operations", () => {
const typemix = [
"P20080915T155300",
"-P20080915T155300",
"P2008-09-15T15:53:00",
"-P2008-09-15T15:53:00",
"P2y10m14dT20h13m45s",
"-P2y10m14dT20h13m45s",
"P6w",
"20080915T155300/20101113T000000",
"P2y10M14dT20h13m45s/20080915T155300",
"20080915T155300/P2y10M14dT20h13m45s",
"2008-09-15T15:53:00/2010-11-13T00:00:00",
"P2y10M14dT20h13m45s/2008-09-15T15:53:00",
"2008-09-15T15:53:00/P2y10M14dT20h13m45s",
"20080915T155300",
"2008-09-15T15:53:00+04:30"
];
typemix.forEach(t1 => {
it(` parses ${t1}`, () => {
expect(calculator(t1)).toBeDefined();
typemix.forEach(t2 => {
expect(calculator(`${t1} + ${t2}`)).toBeDefined();
expect(calculator(`${t1} - ${t2}`)).toBeDefined();
expect(calculator(`${t1} * ${t2}`)).toBeDefined();
expect(calculator(`${t1} / ${t2}`)).toBeDefined();
expect(calculator(`${t2} / (${t1} + ${t2})`)).toBeDefined();
expect(calculator(`${t2} * (${t1} - ${t2})`)).toBeDefined();
expect(calculator(`(${t2} + ${t1}) * ${t2}`)).toBeDefined();
expect(calculator(`(${t2} - ${t1}) / ${t2}`)).toBeDefined();
});
});
});
});
});