@almadar/evaluator 2.37.0 → 2.39.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1780,6 +1780,104 @@ var MS_PER_MINUTE = 60 * MS_PER_SECOND;
1780
1780
  var MS_PER_HOUR = 60 * MS_PER_MINUTE;
1781
1781
  var MS_PER_DAY = 24 * MS_PER_HOUR;
1782
1782
  var MS_PER_WEEK = 7 * MS_PER_DAY;
1783
+ var TIME_UNIT_ALIASES = {
1784
+ ms: "ms",
1785
+ millisecond: "ms",
1786
+ milliseconds: "ms",
1787
+ s: "second",
1788
+ second: "second",
1789
+ seconds: "second",
1790
+ m: "minute",
1791
+ minute: "minute",
1792
+ minutes: "minute",
1793
+ h: "hour",
1794
+ hour: "hour",
1795
+ hours: "hour",
1796
+ d: "day",
1797
+ day: "day",
1798
+ days: "day",
1799
+ w: "week",
1800
+ week: "week",
1801
+ weeks: "week",
1802
+ month: "month",
1803
+ months: "month",
1804
+ year: "year",
1805
+ years: "year"
1806
+ };
1807
+ var TIME_UNIT_VOCABULARY = "ms|millisecond(s), s|second(s), m|minute(s), h|hour(s), d|day(s), w|week(s), month(s), year(s)";
1808
+ function parseTimeUnit(unit) {
1809
+ const resolved = TIME_UNIT_ALIASES[String(unit)];
1810
+ if (resolved === void 0) {
1811
+ throw new TypeError(
1812
+ `Type mismatch: expected time unit (${TIME_UNIT_VOCABULARY}), got ${String(unit)}`
1813
+ );
1814
+ }
1815
+ return resolved;
1816
+ }
1817
+ var FIXED_UNIT_MS = {
1818
+ ms: 1,
1819
+ second: MS_PER_SECOND,
1820
+ minute: MS_PER_MINUTE,
1821
+ hour: MS_PER_HOUR,
1822
+ day: MS_PER_DAY,
1823
+ week: MS_PER_WEEK
1824
+ };
1825
+ function daysInMonth(year, month) {
1826
+ return new Date(Date.UTC(year, month + 1, 0)).getUTCDate();
1827
+ }
1828
+ function addCalendarMonths(ts, months) {
1829
+ const date = new Date(ts);
1830
+ const y = date.getUTCFullYear();
1831
+ const m = date.getUTCMonth();
1832
+ const total = y * 12 + m + months;
1833
+ const ny = Math.floor(total / 12);
1834
+ const nm = (total % 12 + 12) % 12;
1835
+ const nd = Math.min(date.getUTCDate(), daysInMonth(ny, nm));
1836
+ const shifted = new Date(ts);
1837
+ shifted.setUTCFullYear(ny, nm, nd);
1838
+ return shifted.getTime();
1839
+ }
1840
+ function shiftTime(ts, amount, unit) {
1841
+ const fixed = FIXED_UNIT_MS[unit];
1842
+ if (fixed !== void 0) return ts + amount * fixed;
1843
+ return addCalendarMonths(ts, unit === "year" ? Math.trunc(amount) * 12 : Math.trunc(amount));
1844
+ }
1845
+ function startOf(ts, unit) {
1846
+ switch (unit) {
1847
+ case "ms":
1848
+ return Math.floor(ts);
1849
+ case "second":
1850
+ return Math.floor(ts / MS_PER_SECOND) * MS_PER_SECOND;
1851
+ case "minute":
1852
+ return Math.floor(ts / MS_PER_MINUTE) * MS_PER_MINUTE;
1853
+ case "hour":
1854
+ return Math.floor(ts / MS_PER_HOUR) * MS_PER_HOUR;
1855
+ case "day":
1856
+ return Math.floor(ts / MS_PER_DAY) * MS_PER_DAY;
1857
+ case "week": {
1858
+ const days = Math.floor(ts / MS_PER_DAY);
1859
+ const dow = ((days + 3) % 7 + 7) % 7;
1860
+ return (days - dow) * MS_PER_DAY;
1861
+ }
1862
+ case "month": {
1863
+ const d = new Date(ts);
1864
+ return Date.UTC(d.getUTCFullYear(), d.getUTCMonth(), 1);
1865
+ }
1866
+ case "year":
1867
+ return Date.UTC(new Date(ts).getUTCFullYear(), 0, 1);
1868
+ }
1869
+ }
1870
+ function wholeMonthsBetween(from, to) {
1871
+ const lo = new Date(Math.min(from, to));
1872
+ const hi = new Date(Math.max(from, to));
1873
+ let months = (hi.getUTCFullYear() - lo.getUTCFullYear()) * 12 + (hi.getUTCMonth() - lo.getUTCMonth());
1874
+ const loRest = [lo.getUTCDate(), lo.getTime() - startOf(lo.getTime(), "day")];
1875
+ const hiRest = [hi.getUTCDate(), hi.getTime() - startOf(hi.getTime(), "day")];
1876
+ if (hiRest[0] < loRest[0] || hiRest[0] === loRest[0] && hiRest[1] < loRest[1]) {
1877
+ months -= 1;
1878
+ }
1879
+ return to < from ? -months : months;
1880
+ }
1783
1881
  function evalTimeNow() {
1784
1882
  return Date.now();
1785
1883
  }
@@ -1862,136 +1960,39 @@ function evalTimeSecond(args, evaluate2, ctx) {
1862
1960
  const timestamp = evaluate2(args[0], ctx);
1863
1961
  return new Date(timestamp).getSeconds();
1864
1962
  }
1865
- function addTime(date, amount, unit) {
1866
- const result = new Date(date);
1867
- switch (unit) {
1868
- case "year":
1869
- result.setFullYear(result.getFullYear() + amount);
1870
- break;
1871
- case "month":
1872
- result.setMonth(result.getMonth() + amount);
1873
- break;
1874
- case "week":
1875
- result.setDate(result.getDate() + amount * 7);
1876
- break;
1877
- case "day":
1878
- result.setDate(result.getDate() + amount);
1879
- break;
1880
- case "hour":
1881
- result.setHours(result.getHours() + amount);
1882
- break;
1883
- case "minute":
1884
- result.setMinutes(result.getMinutes() + amount);
1885
- break;
1886
- case "second":
1887
- result.setSeconds(result.getSeconds() + amount);
1888
- break;
1889
- case "ms":
1890
- result.setMilliseconds(result.getMilliseconds() + amount);
1891
- break;
1892
- }
1893
- return result;
1894
- }
1895
1963
  function evalTimeAdd(args, evaluate2, ctx) {
1896
1964
  const timestamp = evaluate2(args[0], ctx);
1897
1965
  const amount = evaluate2(args[1], ctx);
1898
- const unit = evaluate2(args[2], ctx);
1899
- const date = new Date(timestamp);
1900
- return addTime(date, amount, unit).getTime();
1966
+ const unit = parseTimeUnit(evaluate2(args[2], ctx));
1967
+ return shiftTime(timestamp, amount, unit);
1901
1968
  }
1902
1969
  function evalTimeSubtract(args, evaluate2, ctx) {
1903
1970
  const timestamp = evaluate2(args[0], ctx);
1904
1971
  const amount = evaluate2(args[1], ctx);
1905
- const unit = evaluate2(args[2], ctx);
1906
- const date = new Date(timestamp);
1907
- return addTime(date, -amount, unit).getTime();
1972
+ const unit = parseTimeUnit(evaluate2(args[2], ctx));
1973
+ return shiftTime(timestamp, -amount, unit);
1908
1974
  }
1909
1975
  function evalTimeDiff(args, evaluate2, ctx) {
1910
1976
  const a = evaluate2(args[0], ctx);
1911
1977
  const b = evaluate2(args[1], ctx);
1912
- const unit = args.length > 2 ? evaluate2(args[2], ctx) : "ms";
1913
1978
  const diffMs = a - b;
1914
- switch (unit) {
1915
- case "year":
1916
- return Math.floor(diffMs / (MS_PER_DAY * 365.25));
1917
- case "month":
1918
- return Math.floor(diffMs / (MS_PER_DAY * 30.44));
1919
- case "week":
1920
- return Math.floor(diffMs / MS_PER_WEEK);
1921
- case "day":
1922
- return Math.floor(diffMs / MS_PER_DAY);
1923
- case "hour":
1924
- return Math.floor(diffMs / MS_PER_HOUR);
1925
- case "minute":
1926
- return Math.floor(diffMs / MS_PER_MINUTE);
1927
- case "second":
1928
- return Math.floor(diffMs / MS_PER_SECOND);
1929
- case "ms":
1930
- default:
1931
- return diffMs;
1932
- }
1979
+ if (args.length <= 2) return diffMs;
1980
+ const unit = parseTimeUnit(evaluate2(args[2], ctx));
1981
+ const fixed = FIXED_UNIT_MS[unit];
1982
+ if (fixed !== void 0) return Math.trunc(diffMs / fixed);
1983
+ const months = wholeMonthsBetween(b, a);
1984
+ return unit === "year" ? Math.trunc(months / 12) : months;
1933
1985
  }
1934
1986
  function evalTimeStartOf(args, evaluate2, ctx) {
1935
1987
  const timestamp = evaluate2(args[0], ctx);
1936
- const unit = evaluate2(args[1], ctx);
1937
- const date = new Date(timestamp);
1938
- switch (unit) {
1939
- case "year":
1940
- date.setMonth(0, 1);
1941
- date.setHours(0, 0, 0, 0);
1942
- break;
1943
- case "month":
1944
- date.setDate(1);
1945
- date.setHours(0, 0, 0, 0);
1946
- break;
1947
- case "week": {
1948
- const day = date.getDay();
1949
- date.setDate(date.getDate() - day);
1950
- date.setHours(0, 0, 0, 0);
1951
- break;
1952
- }
1953
- case "day":
1954
- date.setHours(0, 0, 0, 0);
1955
- break;
1956
- case "hour":
1957
- date.setMinutes(0, 0, 0);
1958
- break;
1959
- case "minute":
1960
- date.setSeconds(0, 0);
1961
- break;
1962
- }
1963
- return date.getTime();
1988
+ const unit = parseTimeUnit(evaluate2(args[1], ctx));
1989
+ return startOf(timestamp, unit);
1964
1990
  }
1965
1991
  function evalTimeEndOf(args, evaluate2, ctx) {
1966
1992
  const timestamp = evaluate2(args[0], ctx);
1967
- const unit = evaluate2(args[1], ctx);
1968
- const date = new Date(timestamp);
1969
- switch (unit) {
1970
- case "year":
1971
- date.setMonth(11, 31);
1972
- date.setHours(23, 59, 59, 999);
1973
- break;
1974
- case "month":
1975
- date.setMonth(date.getMonth() + 1, 0);
1976
- date.setHours(23, 59, 59, 999);
1977
- break;
1978
- case "week": {
1979
- const day = date.getDay();
1980
- date.setDate(date.getDate() + (6 - day));
1981
- date.setHours(23, 59, 59, 999);
1982
- break;
1983
- }
1984
- case "day":
1985
- date.setHours(23, 59, 59, 999);
1986
- break;
1987
- case "hour":
1988
- date.setMinutes(59, 59, 999);
1989
- break;
1990
- case "minute":
1991
- date.setSeconds(59, 999);
1992
- break;
1993
- }
1994
- return date.getTime();
1993
+ const unit = parseTimeUnit(evaluate2(args[1], ctx));
1994
+ if (unit === "ms") return Math.floor(timestamp);
1995
+ return shiftTime(startOf(timestamp, unit), 1, unit) - 1;
1995
1996
  }
1996
1997
  function evalTimeIsBefore(args, evaluate2, ctx) {
1997
1998
  const a = evaluate2(args[0], ctx);
@@ -2012,28 +2013,11 @@ function evalTimeIsBetween(args, evaluate2, ctx) {
2012
2013
  function evalTimeIsSame(args, evaluate2, ctx) {
2013
2014
  const a = evaluate2(args[0], ctx);
2014
2015
  const b = evaluate2(args[1], ctx);
2015
- const unit = args.length > 2 ? evaluate2(args[2], ctx) : void 0;
2016
- if (!unit) {
2016
+ if (args.length <= 2) {
2017
2017
  return a === b;
2018
2018
  }
2019
- const dateA = new Date(a);
2020
- const dateB = new Date(b);
2021
- switch (unit) {
2022
- case "year":
2023
- return dateA.getFullYear() === dateB.getFullYear();
2024
- case "month":
2025
- return dateA.getFullYear() === dateB.getFullYear() && dateA.getMonth() === dateB.getMonth();
2026
- case "day":
2027
- return dateA.getFullYear() === dateB.getFullYear() && dateA.getMonth() === dateB.getMonth() && dateA.getDate() === dateB.getDate();
2028
- case "hour":
2029
- return dateA.getFullYear() === dateB.getFullYear() && dateA.getMonth() === dateB.getMonth() && dateA.getDate() === dateB.getDate() && dateA.getHours() === dateB.getHours();
2030
- case "minute":
2031
- return Math.floor(a / MS_PER_MINUTE) === Math.floor(b / MS_PER_MINUTE);
2032
- case "second":
2033
- return Math.floor(a / MS_PER_SECOND) === Math.floor(b / MS_PER_SECOND);
2034
- default:
2035
- return a === b;
2036
- }
2019
+ const unit = parseTimeUnit(evaluate2(args[2], ctx));
2020
+ return startOf(a, unit) === startOf(b, unit);
2037
2021
  }
2038
2022
  function evalTimeIsPast(args, evaluate2, ctx) {
2039
2023
  const timestamp = evaluate2(args[0], ctx);