UNPKG

calcdate

Version:

Evalate a date expression calc`now + 3 days`)!

663 lines (516 loc) 35.4 kB
# Date Calculator ## TL;DR ### ES6 ``` import { calc } from "calcdate"; // import { datefnscalc } from "calcdate"; // with date-fns // import { luxoncalc } from "calcdate"; // with luxon // import { luxonsimplecalc } from "calcdate"; // with luxon // import { momentcalc } from "calcdate"; // with moment // import moment from "moment"; const dval = calc(); // const dval = momentcalc(moment); dval`now + 3 days + 5 hours`; ``` ### Node ``` const calc = require("calcdate").default; // const luxoncalc = require("calcdate").luxoncalc; // import luxon from "luxon"; const dval = calc(); // const dval = luxoncalc(luxon); dval`now + 3 days + 5 hours`; ``` ### runkit api ``` https://embed-sw29njl68eg5.runkit.sh/P1d // https://embed-sw29njl68eg5.runkit.sh/datefns/now+5d // https://embed-sw29njl68eg5.runkit.sh/moment/now+5d // https://embed-sw29njl68eg5.runkit.sh/luxon/now+5d ``` ## Install ``` yarn add calcdate ``` ``` npm i calcdate ``` ## git repo [Find source code on git](https://github.com/Zyclotrop-j/calcdate) ![Bundle size](https://badgen.net/bundlephobia/minzip/react "Bundle size") [![CircleCI](https://circleci.com/gh/Zyclotrop-j/calcdate/tree/master.svg?style=svg)](https://circleci.com/gh/Zyclotrop-j/calcdate/tree/master) ## Dependencies There are **no direct dependencies**! We recommend using this lib with your favourite date-time lib, use the bindings provided. | import | required dependency | import | | --------------------- | ---------------------------------------- | --------------------------------------------------- | | datefnsCalculator | [date-fns](https://date-fns.org) | `import { datefnsCalculator } from "calcdate";` | | luxonCalculator | [luxon](https://moment.github.io/luxon/) | `import { luxonCalculator } from "calcdate";` | | simpleluxonCalculator | [luxon](https://moment.github.io/luxon/) | `import { simpleluxonCalculator } from "calcdate";` | | momentCalculator | [moment](https://momentjs.com/) | `import { momentCalculator } from "calcdate";` | **Note** You need to initialize the calculator with your library: ``` import { datefnsCalculator } from "calcdate" import datefns from "datefns"; const calculator = datefnsCalculator(datefns); ``` ## Api docs Calling the calculator is easy: ``` calculator`<expression>` ``` **Example** ``` // Imports import { datefnsCalculator } from "calcdate" import datefns from "datefns"; // Setup const calculator = datefnsCalculator(datefns); // Examples: calculator`2009-12T12:34`; calculator`P0002--10-15T10:+30:20`; calculator`NOW + 7days`; calculator`2009-12T12:00 - 2019-12T12:00`; ``` where calculator is your imported calculator and expression is what you want calculated. The following section outlines what is permitted in expressions. ### Initializing The calculator has to be initialized by passing it the library you are usigng it with with. ``` const luxon = require("luxon"); const calculator = require("calcdate").luxoncalc(luxon); ``` ### Types Being a date-calculator the primary types used in expressions are date-times and the differences in between them (being durations and intervals). #### Date-Time A datetime is an exact point in time. It can be expressed as a ISO-8601-date-time (see [w3](https://www.w3.org/TR/NOTE-datetime) and [wikipedia](https://en.wikipedia.org/wiki/ISO_8601#Time_zone_designators)). Simply put, use the format `YYYY-MM-DDThh:mm:ss.sss` ("extended format"). All parts (but the year) are optional. If a part is not present, its default is used (0 for times and 1 for dates; `2019` = `2019-01-01T00:00:00.000`). You can also use the normal form `YYYYMMDD hhmmsssss`. You can also add a time-zone using `YYYY-MM-DDThh:mm:ss.sss+-hh:mm` or `YYYY-MM-DDThh:mm:ss.sssZ` for utc. **Examples** ``` 2009-12T12:34 // Tue Dec 01 2009 12:34:00 GMT+1100 (Australian Eastern Daylight Time) 2009 // Thu Jan 01 2009 11:00:00 GMT+1100 (Australian Eastern Daylight Time) 2009-05-19 // Tue May 19 2009 10:00:00 GMT+1000 (Australian Eastern Standard Time) 2009-05-19 // Tue May 19 2009 00:00:00 GMT+1000 (Australian Eastern Standard Time) 2009-05 // Fri May 01 2009 10:00:00 GMT+1000 (Australian Eastern Standard Time) 2009-001 // Thu Jan 01 2009 00:00:00 GMT+1100 (Australian Eastern Daylight Time) 2009-05-19 // Tue May 19 2009 10:00:00 GMT+1000 (Australian Eastern Standard Time) 2009-05-19T00:00 // Tue May 19 2009 00:00:00 GMT+1000 (Australian Eastern Standard Time) 2009-05-19T14:31 // Tue May 19 2009 14:31:00 GMT+1000 (Australian Eastern Standard Time) 2009-05-19T14:39:22 // Tue May 19 2009 14:39:22 GMT+1000 (Australian Eastern Standard Time) 2009-05-19T14:39Z // Wed May 20 2009 00:39:00 GMT+1000 (Australian Eastern Standard Time) 2009-05-19T14:39:22-06:00 // Wed May 20 2009 06:39:22 GMT+1000 (Australian Eastern Standard Time) 2009-05-19T14:39:22+0600 // Tue May 19 2009 18:39:22 GMT+1000 (Australian Eastern Standard Time) 2007-04-06T00:00 // Fri Apr 06 2007 00:00:00 GMT+1000 (Australian Eastern Standard Time) 200912T1234 // Tue Dec 01 2009 12:34:00 GMT+1100 (Australian Eastern Daylight Time) 2009 // Thu Jan 01 2009 11:00:00 GMT+1100 (Australian Eastern Daylight Time) 20090519 // Tue May 19 2009 10:00:00 GMT+1000 (Australian Eastern Standard Time) 20090519 // Tue May 19 2009 00:00:00 GMT+1000 (Australian Eastern Standard Time) 200905 // Fri May 01 2009 10:00:00 GMT+1000 (Australian Eastern Standard Time) 2009001 // Thu Jan 01 2009 00:00:00 GMT+1100 (Australian Eastern Daylight Time) 20090519 // Tue May 19 2009 10:00:00 GMT+1000 (Australian Eastern Standard Time) 20090519 0000 // Tue May 19 2009 00:00:00 GMT+1000 (Australian Eastern Standard Time) 20090519 1431 // Tue May 19 2009 14:31:00 GMT+1000 (Australian Eastern Standard Time) 20090519 143922 // Tue May 19 2009 14:39:22 GMT+1000 (Australian Eastern Standard Time) 20090519 1439Z // Wed May 20 2009 00:39:00 GMT+1000 (Australian Eastern Standard Time) 20090519 143922-06:00 // Wed May 20 2009 06:39:22 GMT+1000 (Australian Eastern Standard Time) 20090519 143922+0600 // Tue May 19 2009 18:39:22 GMT+1000 (Australian Eastern Standard Time) 20070406 0000 // Fri Apr 06 2007 00:00:00 GMT+1000 (Australian Eastern Standard Time) ``` ##### Binding depended Each parser may provide its own parsing-from-string mechanism using `{....}`-notation. **Example** `{"2012 juillet", "YYYY MMM", "fr"}` + moment-bindings `{"12/11/2000", "MM/dd/yyyy"}` + luxon-bindings #### Duration A duration expresses a time-period, aka "how long". A duration may be expressed using an iso-duration or the short-hand notation as follows. **Note** Without a start- or end-date (see Interval) the units in a duration are hard to compare. For example, a duration of `1 month` can be either anywhere from 28 days (2019-02-01/2019-03-01) to 31 days (2019-12-01/2020-01-01). Therefore some operations might be unsafe to perform, such as `1 month / 1 days` (interpreted as "how many days fit into a month"). Depending on the bindings a loss of information and accuracy may occurs. (Also see [luxon-notes](https://moment.github.io/luxon/docs/manual/math.html#duration-math).) ##### Short-hand notation Each short-hand notation has three different forms which can be used synonymously: spelled-out singular, plural and shorthand (which makes it a shorthand-shorthand, I guess?). Whitespace is irrelevant. So `1 day`, `1 days`, `1 d`, `1day`, `1days`, `1d` all mean "1 day". | singular | plural | shorthand | example | notes | | ----------- | ------------ | --------- | ------- | ------------------ | | millisecond | milliseconds | ms | `5ms` | | | second | seconds | s | `1 s` | alias: ss, sec | | minute | minutes | m | `1 min` | alias: min, mm, Tm | | hour | hours | h | `1 h` | alias: hh | | day | days | d | `1 d` | | | weekday | weekdays | wd | `1 wd` | | | week | weeks | w | `1 w` | | | fortnight | fortnights | fn | `1 fn` | = two weeks | | month | months | M | `1 M` | alias: l, L | | quarter | quarters | q | `1 q` | | | year | years | y | `1 y` | alias: a | In general these notation are **caseinsensetive** and can be pluralized, with the following exceptions: - `M`, months, not to be confused with `m`, minutes - `m`, minutes, see above - `ms`, milliseconds, not to be confused `Ms`, plural of `M`, months ##### Iso-Notation Durations may be written in iso as `PnYnMnDTnHnMnS` (where `n` is a any number). From [wikipedia](https://en.wikipedia.org/wiki/ISO_8601#Durations): > P is the duration designator (for period) placed at the start of the duration representation. > > Y is the year designator that follows the value for the number of years. > > M is the month designator that follows the value for the number of months. > > W is the week designator that follows the value for the number of weeks. > > D is the day designator that follows the value for the number of days. > > T is the time designator that precedes the time components of the representation. > > H is the hour designator that follows the value for the number of hours. > > M is the minute designator that follows the value for the number of minutes. > > S is the second designator that follows the value for the number of seconds. "+" and "-" are allowed for the entire expression and parts individually. Thus `+P1Y` (1 year), `-P1Y` (minus 1 year) and `-P-1y` (minus minus 1 year = 1 year) are valid. **Examples** ``` // Iso extended form, any number of digits allowed 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 // 1 year P2M // 2 month P3D // 3 days PT4H // 4 hours PT05M // 5 minutes; padding with 0s is allowed PT600S // 600 seconds; more than 2 digits are allowed P1y2m3dT4h5m6s // 1 year, 2 months, 3 days, 4 hours, 5 minutes, 6 seconds; case-insensitive // Iso-short-form, 4 digits for year, 2 for each other component P00021015T103020 // 2 years, 10 months, 15 days, 10 hours, 30 minutes, 20 seconds P00021015 // 2 years, 10 months, 15 days P0002-10-15T10:30:20 // 2 years, 10 months, 15 days, 10 hours, 30 minutes, 20 seconds P0002-10-15 // 2 years, 10 months, 15 days +P00021015T103020 +P00021015 +P0002-10-15T10:30:20 +P0002-10-15 -P00021015T103020 // -2 years, -10 months, -15 days, -10 hours, -30 minutes, -20 seconds -P00021015 -P0002-10-15T10:30:20 -P0002-10-15 P+00021015T103020 P0002-1015 P0002--10-15T10:+30:20 // 2 years, -10 month, 15 days, 10 hours, 30 minutes, 20 seconds P0002-10--15 // 2 years, 10 months, -15 days -P0002-10--15 // -2 years, -10 months, --15 days = 15 days ``` **Note** The time designator is **mandatory** when denoting times, so `P1H` would be _invalid_ while `PT1H` would be fine. ##### Binding depended Each parser may provide its own parsing-from-string mechanism using `[....]`-notation. **Example** `[ {"years": 1, "quarters"": 3, "milliseconds": 27} ]` + luxon-bindings - uses `luxon.Duration.fromObject` #### Interval An interval expresses the duration between a start- and an end-date. It can be understood as a box for two dates and the duration in between. Hence an interval can be constructed by providing a start- and an end-date, or a start-date and a duration (end-date = start-date + duration), or an end-date and a duration (start-date = end-date - duration). Intervals may be written as Iso-intervals. The three options are: - Iso-Date-Time/Iso-Date-Time - Iso-Date-Time/Iso-Duration - Iso-Duration/Iso-Date-Time Iso-Date-Time and Iso-Duration use the same parsing mechanisms described above and hence allow the notations outlined above. **Examples** ``` 2009-12T12:34/20090519 143922+0600 P1Y2M3DT4H05M600S/2009-12T12:34 2009-12T12:34/P1Y2M3DT4H05M600S ``` For more examples, combine any date-time example with another date-time-example or any duration-example. **Note** Not all bindings support intervals! ##### Binding depended Each parser may provide its own parsing-from-string mechanism using `~....~`-notation. **Example** `~2007-03-01T13:00:00Z/P1Y2M10DT2H30M~` + luxon-bindings - uses `luxon.Interval.fromISO` #### Unitless You may enter "bare" numbers, such as `2`. They are treated as such. This might be useful for scalar operations such as `2 * 2d` (`= 4 d`). **Examples** ``` 1 0 100 -10 -5 0 -09 1 + 1 // 2 10 + 15 - 25 // 0 3 * 5 // 15 3d * -1 // -3d 88 / 11 // 8 1 / 2 // 0.5 2.5 * 2 // 5 2d * 5 // 10d 7 - 8 // -1 ``` **Warning** Longer number are going to be interpreted as Iso-dates and thus might fail parsing! If you need to use numbers with more digits than 3, consider using interpolation instead. ``` 2000 // 2000-01-01T00:00:00 `${2000}` // 'number' 2000 ``` #### Custom / Existing values Use interpolation to insert custom type: ``` calculator`${any_thing_here}` ``` This allows you to use your existing Date/luxon-Date-Times/moments/luxon-Intervals/... directly in the calculator. **The bindings define what custom types are supported!** That means, if you interpolate a datefnsCalculator with a luxon-Date-Time it will likely throw an error, as date-fns can't make sense of the luxon-object. **Examples** ``` import DateTime from 'luxon/src/datetime.js'; luxonCalculator`${DateTime.fromSQL(...)} + ${{ hours: 3, minutes: 13 }}` ``` ``` import moment from 'moment'; momentCalculator`${moment()} + ${moment.duration(2, 'seconds');}` ``` ### Operations #### Add ("plus", "+") Adds two "things". The binding implementation defines what "add" means and if it has a meaning at all! **Example** `1d + 1h` | Binding | Type a | Type b | Result | Notes | | ------------ | -------- | -------- | --------------- | --------------------------------- | | simple | Date | Date | Error | | | simple | Date | Duration | Timestamp (Int) | Loses accuracy due to conversion | | simple | Duration | Date | Timestamp (Int) | Loses accuracy due to conversion | | simple | Duration | Duration | Duration | | | simple | Unitless | Unitless | Unitless | | | simple | Unitless | \* | Error | | | simple | any | any | any | Cast to date/duration; else error | | ------- | -------- | -------- | --------------- | -------------------------------- | | date-fns | Date | Date | Error | | | date-fns | Date | Duration | Date | | | date-fns | Duration | Date | Date | | | date-fns | Duration | Duration | Duration | | | date-fns | Unitless | Unitless | Unitless | | | date-fns | \* | \* | Error | | | ------- | -------- | -------- | --------------- | -------------------------------- | | luxon | Date | Date | Error | | | luxon | Date | Duration | Date | | | luxon | Date | Interval | Date | Date + Duration(Interval) | | luxon | Duration | Date | Date | | | luxon | Duration | Duration | Duration | | | luxon | Duration | Interval | Interval | Shifts interval by duration | | luxon | Interval | Date | Interval | Interval extended to Date | | luxon | Interval | Duration | Interval | Shifts interval by duration | | luxon | Interval | Interval | Interval | Union of intervals | | luxon | Unitless | Unitless | Unitless | | | luxon | \* | \* | Error | | | ------- | -------- | -------- | --------------- | -------------------------------- | | simple-luxon | Date | Date | Error | | | simple-luxon | Date | Duration | Date | | | simple-luxon | Duration | Date | Date | | | simple-luxon | Duration | Duration | Duration | | | simple-luxon | Unitless | Unitless | Unitless | | | simple-luxon | \* | \* | Error | | | ------- | -------- | -------- | --------------- | -------------------------------- | | moment | Date | Date | Error | | | moment | Date | Duration | Date | | | moment | Duration | Date | Date | | | moment | Duration | Duration | Duration | | | moment | Unitless | Unitless | Unitless | | | moment | \* | \* | Error | | #### Subtract ("minus", "-") Subtracts two "things" - binding defines the meaning. Can also be interpreted as a "until", as in "2019 - 2020" yielding an interval between those in some implementations. **Example** `1d - 5h` | Binding | Type a | Type b | Result | Notes | | ------------ | -------- | -------- | --------------- | ------------------------------------- | | simple | Date | Date | Number | Difference of times in milliseconds | | simple | Date | Duration | Timestamp (Int) | Loses accuracy due to conversion | | simple | Duration | Date | Timestamp (Int) | Same as Date - Duration | | simple | Duration | Duration | Duration | | | simple | Unitless | Unitless | Unitless | | | simple | \* | \* | \* | Cast to date/duration; else error | | ------- | -------- | -------- | --------------- | -------------------------------- | | date-fns | Date | Date | Duration | Difference between the two dates | | date-fns | Date | Duration | Date | | | date-fns | Duration | Date | Date | Same as Date - Duration | | date-fns | Duration | Duration | Duration | | | date-fns | Unitless | Unitless | Unitless | | | date-fns | \* | \* | Error | | | ------- | -------- | -------- | --------------- | -------------------------------- | | luxon | Date | Date | Interval | Interval(start: Date a, end: Date b) | | luxon | Date | Duration | Date | Puts date into the past by duration | | luxon | Date | Interval | Date | Date - Duration(Interval) | | luxon | Duration | Date | Date | Same as Date - Duration | | luxon | Duration | Duration | Duration | | | luxon | Duration | Interval | Interval | Same as Interval - Duration | | luxon | Interval | Date | Interval | Limits Interval by Date | | luxon | Interval | Duration | Interval | Shifts interval by duration | | luxon | Interval | Interval | Interval | Intersection or Interval between both | | luxon | Unitless | Unitless | Unitless | | | luxon | \* | \* | Error | | | ------- | -------- | -------- | --------------- | -------------------------------- | | simple-luxon | Date | Date | Error | | | simple-luxon | Date | Duration | Date | | | simple-luxon | Duration | Date | Error | | | simple-luxon | Duration | Duration | Duration | | | simple-luxon | Unitless | Unitless | Unitless | | | simple-luxon | \* | \* | Error | | | ------- | -------- | -------- | --------------- | -------------------------------- | | moment | Date | Date | Error | | | moment | Date | Duration | Date | | | moment | Duration | Date | Error | | | moment | Duration | Duration | Duration | | | moment | Unitless | Unitless | Unitless | | | moment | \* | \* | Error | | #### Multiply ("\*") **Example** `5d * 3` | Binding | Type a | Type b | Result | Notes | | ------------ | -------- | -------- | --------------- | -------------------------------- | | simple | Duration | Unitless | Duration | | | simple | Unitless | Duration | Duration | | | simple | Unitless | Unitless | Unitless | | | simple | \* | \* | Error | | | ------- | -------- | -------- | --------------- | -------------------------------- | | date-fns | Duration | Unitless | Duration | | | date-fns | Unitless | Duration | Duration | | | date-fns | Unitless | Unitless | Unitless | | | date-fns | \* | \* | Error | | | ------- | -------- | -------- | --------------- | -------------------------------- | | luxon | Unitless | Interval | Interval | Shifts Interval.start back | | luxon | Interval | Unitless | Interval | Shifts Interval.start forward | | luxon | Duration | Unitless | Duration | | | luxon | Unitless | Duration | Duration | | | luxon | Unitless | Unitless | Unitless | | | luxon | \* | \* | Error | | | ------- | -------- | -------- | --------------- | -------------------------------- | | simple-luxon | Duration | Unitless | Duration | | | simple-luxon | Unitless | Duration | Duration | | | simple-luxon | Unitless | Unitless | Unitless | | | simple-luxon | \* | \* | Error | | | ------- | -------- | -------- | --------------- | -------------------------------- | | moment | Duration | Unitless | Duration | | | moment | Unitless | Duration | Duration | | | moment | Unitless | Unitless | Unitless | | | moment | \* | \* | Error | | #### Divide ("/") Divide things Split "things" into `n` equal parts. | Binding | Type a | Type b | Result | Notes | | ------------ | -------- | -------- | --------------- | -------------------------------------------- | | simple | Duration | Unitless | Duration | | | simple | Unitless | Unitless | Unitless | | | simple | \* | \* | Error | | | ------- | -------- | -------- | --------------- | -------------------------------- | | date-fns | Duration | Unitless | Duration | | | date-fns | Unitless | Duration | Duration | Inverts each duration part | | date-fns | Duration | Duration | Unitless | Loses accuracy due to conversion | | date-fns | Unitless | Unitless | Unitless | | | date-fns | \* | \* | Error | | | ------- | -------- | -------- | --------------- | -------------------------------- | | luxon | Date | Date | Interval | Interval(start: Date a, end: Date b) | | luxon | Interval | Unitless | Duration | Duration c fits Unitless times into Interval | | luxon | Interval | Duration | Unitless | Duration b fits Unitless times into Interval | | luxon | Interval | Unitless | Duration | | | luxon | Duration | Duration | Unitless | Loses accuracy due to conversion | | luxon | Duration | Unitless | Duration | | | luxon | Unitless | Duration | Duration | Inverts each duration part | | luxon | Interval | 1u | Interval | Swops the interval (start->end, end->start) | | luxon | Unitless | Unitless | Unitless | | | luxon | \* | \* | Error | | | ------- | -------- | -------- | --------------- | -------------------------------- | | simple-luxon | Duration | Unitless | Duration | | | simple-luxon | Unitless | Unitless | Unitless | | | simple-luxon | \* | \* | Error | | | ------- | -------- | -------- | --------------- | -------------------------------- | | moment | Duration | Unitless | Duration | | | moment | Unitless | Unitless | Unitless | | | moment | \* | \* | Error | | ### Other Additionally `(` + `)` is permitted to group any expression and give its evaluation priority. Nesting is allowed. (Or expressed differently: `(...)` works as you would expect!) **Example** `( 1d - 5h ) * 2` On top there is the keywords "now" (alias "today", both case-insensitive), which creates a Date-Time with the value of "now". ### Operator precedence | Priority | Expression | Example | | -------- | ------------------ | ---------------------------------- | | 1 | Interval | 2009-12T12:34/20090519 143922+0600 | | 2 | now, today | now, now(), Today | | 2 | Custom Constructor | {....}, [....], \~....\~ | | 2 | Duration | P1D | | 2 | Date-Time | 2019 | | 2 | Duration shorthand | 1 day | | 3 | Unitless | 1 | | 4 | Brackets | ( .... ) | | 5 | Multiply | .. \* .. | | 5 | Divide | .. / .. | | 6 | Plus | .. + .. | | 6 | Minus | .. - .. | This order insures that `2019/P1D` is an interval while `2019 / P1D` means "divide 2019 by P1D". It also care to interpret `2019-08` as "August of 2019", while `2019 - 08` means "The date 2019 minus unitless 8". ## Bring your own lib date-lib The date-calculator itself is not bound to any library. You can 'teach' it to work with any library by implementing 'bindings'. To create a new calculator type import the calculatorFactory (aka "parser") and call it with your bindings (see below). ``` import calculatorFactory from "./calcdate"; const yourCalculator = calculatorFactory({ makeDate: ..., makeDuration: ..., makeInterval: ..., add: ..., subtract: ..., multiply: ..., divide: ... }); ``` You will need to implement the following methods: ### makeDate You function to create a new date. It can take the following two signatures: - `makeDate(date: Native_Date, { type: calculatorFactory.NATIVEDATE }) : YourDateType` - `makeDate(date: any, { type: calculatorFactory.DATEXPRESION }) : YourDateType`, created by calculator`{any_string}` ### makeDuration - `makeDuration({ milliseconds, seconds, minutes, hours, days, weekdays, weeks, months, years } : { milliseoncds: Number?, seconds: Number?, minutes: Number?, hours: Number?, days: Number?, weekdays: Number?, weeks: Number?, months: Number?, years: Number? }, { type: calculatorFactory.DURATIONOBJECT }) : YourDurationType` - `makeDuration(duration: any, { type: calculatorFactory.DURATIONEXPRESSION }) : YourDurationType`, created by calculator`[any_string]` ### makeInterval - `makeInterval([from: YourDateType, to: YourDateType], { type: calculatorFactory.INTERVALOBJECT }) : YourIntervalType` - `makeInterval([from: YourDateType, to: YourDurationType], { type: calculatorFactory.INTERVALOBJECT }) : YourIntervalType` - `makeInterval([from: YourDurationType, to: YourDateType], { type: calculatorFactory.INTERVALOBJECT }) : YourIntervalType` - `makeInterval(interval: any, { type: calculatorFactory.DURATIONEXPRESSION }) : INTERVALEXPRESION`, created by calculator`~any_string~` ### add `add(a, b) : c`, where `a, b, c` are `YourDateType | YourDurationType | YourIntervalType | { unitless: Number } | any` **Examples** - `now + 1 day` - `add(a: YourDateType, b: YourDurationType)` - `now + 1` - `add(a: YourDateType, { unitless: 1 } : { unitless: Number })` - `P3Y6M4DT12H30M5S + 1 day` - `add(a: YourDurationType, b: YourDurationType)` - `2019-01-01/2019-01-02 + now` - `add(a: YourIntervalType, b: YourDateType)` - `${new RegExp("foobar")} + ~hello world~` - `add(a: any, b: YourIntervalType)` - `1d + 1h + 1m` - `add(add(a: YourDurationType, b: YourDurationType), x: YourDurationType)` **Note** You **should** throw (helpful) errors when you can't make sense of the arguments. For example adding up two duration makes sense - adding up two dates might not! The same applies for all the operations! ### subtract `subtract(a, b) : c`, where `a, b, c` are `YourDateType | YourDurationType | YourIntervalType | { unitless: Number } | any` - `now - 1 day` - `subtract(a: YourDateType, b: YourDurationType)` - `now - 1` - `subtract(a: YourDateType, { unitless: 1 } : { unitless: Number })` - `P3Y6M4DT12H30M5S - 1 day` - `subtract(a: YourDurationType, b: YourDurationType)` - `2019-01-01/2019-01-02 - now` - `subtract(a: YourIntervalType, b: YourDateType)` - `${new RegExp("foobar")} - ~hello world~` - `subtract(a: any, b: YourIntervalType)` - `1d - 1h - 1m` - `subtract(add(a: YourDurationType, b: YourDurationType), x: YourDurationType)` **Note** You **should** throw (helpful) errors when you can't make sense of the arguments. For example substracting a duration from a date makes sense - substracting a date from a duration might not! ### multiply `multiply(a, b) : c`, where `a, b, c` are `YourDateType | YourDurationType | YourIntervalType | { unitless: Number } | any` - `now * 1 day` - `multiply(a: YourDateType, b: YourDurationType)` - `now * 1` - `multiply(a: YourDateType, { unitless: 1 } : { unitless: Number })` - `P3Y6M4DT12H30M5S * 1 day` - `multiply(a: YourDurationType, b: YourDurationType)` - `2019-01-01/2019-01-02 * now` - `multiply(a: YourIntervalType, b: YourDateType)` - `${new RegExp("foobar")} * ~hello world~` - `multiply(a: any, b: YourIntervalType)` - `1d * 1h * 1m` - `multiply(add(a: YourDurationType, b: YourDurationType), x: YourDurationType)` **Note** You **should** throw (helpful) errors when you can't make sense of the arguments. For example multiplying a duration by a unitless makes sense - multiplying a duration by another might not! ### divide `divide(a, b) : c`, where `a, b, c` are `YourDateType | YourDurationType | YourIntervalType | { unitless: Number } | any` - `now / 1 day` - `divide(a: YourDateType, b: YourDurationType)` - `now / 1` - `divide(a: YourDateType, { unitless: 1 } : { unitless: Number })` - `P3Y6M4DT12H30M5S / 1 day` - `divide(a: YourDurationType, b: YourDurationType)` - `2019-01-01/2019-01-02 / now` - `divide(a: YourIntervalType, b: YourDateType)` - `${new RegExp("foobar")} / ~hello world~` - `divide(a: any, b: YourIntervalType)` - `1d / 1h / 1m` - `divide(add(a: YourDurationType, b: YourDurationType), x: YourDurationType)` **Note** You **should** throw (helpful) errors when you can't make sense of the arguments. For example dividing a duration by another might make sense (could be "how many durations x fit into duration y") - dividing a unitless by an interval might not!