@ztimson/utils 0.26.25 → 0.27.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.mjs CHANGED
@@ -122,10 +122,11 @@ function applyDeltas(target, deltas) {
122
122
  for (const [key, value] of Object.entries(delta)) {
123
123
  if (value === null) {
124
124
  delete target[key];
125
- } else if (typeof value === "object" && !Array.isArray(value)) {
126
- if (typeof target[key] !== "object" || Array.isArray(target[key])) {
125
+ } else if (Array.isArray(value)) {
126
+ target[key] = [...value];
127
+ } else if (typeof value === "object") {
128
+ if (typeof target[key] !== "object" || Array.isArray(target[key]) || !target[key])
127
129
  target[key] = {};
128
- }
129
130
  applyDeltas(target[key], [value]);
130
131
  } else {
131
132
  target[key] = value;
@@ -144,7 +145,9 @@ function calcDelta(old, target) {
144
145
  delta[key] = val1;
145
146
  } else if (!(key in old)) {
146
147
  delta[key] = null;
147
- } else if (typeof val1 === "object" && typeof val2 === "object" && val1 && val2 && !Array.isArray(val1)) {
148
+ } else if (Array.isArray(val1) || Array.isArray(val2)) {
149
+ if (JSON.stringify(val1) !== JSON.stringify(val2)) delta[key] = val1;
150
+ } else if (typeof val1 === "object" && typeof val2 === "object" && val1 && val2) {
148
151
  const nested = calcDelta(val1, val2);
149
152
  if (Object.keys(nested).length) delta[key] = nested;
150
153
  } else if (val1 !== val2) {
@@ -893,6 +896,33 @@ function toCsv(target, flatten = true) {
893
896
  }).join(","))
894
897
  ].join("\n");
895
898
  }
899
+ function dec2Frac(num, maxDen = 1e3) {
900
+ let sign = Math.sign(num);
901
+ num = Math.abs(num);
902
+ if (Number.isInteger(num)) return sign * num + "";
903
+ let closest = { n: 0, d: 1, diff: Math.abs(num) };
904
+ for (let d = 1; d <= maxDen; d++) {
905
+ let n = Math.round(num * d);
906
+ let diff = Math.abs(num - n / d);
907
+ if (diff < closest.diff) {
908
+ closest = { n, d, diff };
909
+ if (diff < 1e-8) break;
910
+ }
911
+ }
912
+ let integer = Math.floor(closest.n / closest.d);
913
+ let numerator = closest.n - integer * closest.d;
914
+ return (sign < 0 ? "-" : "") + (integer ? integer + " " : "") + (numerator ? numerator + "/" + closest.d : "");
915
+ }
916
+ function fracToDec(frac) {
917
+ let split = frac.split(" ");
918
+ const whole = split.length == 2 ? Number(split[0]) : 0;
919
+ split = split.pop().split("/");
920
+ return whole + Number(split[0]) / Number(split[1]);
921
+ }
922
+ function numSuffix(n) {
923
+ const s = ["th", "st", "nd", "rd"], v = n % 100;
924
+ return `${n}${s[(v - 20) % 10] || s[v] || s[0]}`;
925
+ }
896
926
  function adjustedInterval(cb, ms) {
897
927
  let cancel = false, timeout = null;
898
928
  const p = async () => {
@@ -908,103 +938,101 @@ function adjustedInterval(cb, ms) {
908
938
  if (timeout) clearTimeout(timeout);
909
939
  };
910
940
  }
911
- function formatDate(format = "YYYY-MM-DD H:mm", date = /* @__PURE__ */ new Date(), tz) {
912
- const timezones = [
913
- ["IDLW", -12],
914
- ["SST", -11],
915
- ["HST", -10],
916
- ["AKST", -9],
917
- ["PST", -8],
918
- ["MST", -7],
919
- ["CST", -6],
920
- ["EST", -5],
921
- ["AST", -4],
922
- ["BRT", -3],
923
- ["MAT", -2],
924
- ["AZOT", -1],
925
- ["UTC", 0],
926
- ["CET", 1],
927
- ["EET", 2],
928
- ["MSK", 3],
929
- ["AST", 4],
930
- ["PKT", 5],
931
- ["IST", 5.5],
932
- ["BST", 6],
933
- ["ICT", 7],
934
- ["CST", 8],
935
- ["JST", 9],
936
- ["AEST", 10],
937
- ["SBT", 11],
938
- ["FJT", 12],
939
- ["TOT", 13],
940
- ["LINT", 14]
941
- ];
942
- function adjustTz(date2, gmt) {
943
- const currentOffset = date2.getTimezoneOffset();
944
- const adjustedOffset = gmt * 60;
945
- return new Date(date2.getTime() + (adjustedOffset + currentOffset) * 6e4);
946
- }
947
- function day(num) {
948
- return ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"][num] || "Unknown";
949
- }
950
- function doy(date2) {
951
- const start = /* @__PURE__ */ new Date(`${date2.getFullYear()}-01-01 0:00:00`);
952
- return Math.ceil((date2.getTime() - start.getTime()) / (1e3 * 60 * 60 * 24));
953
- }
954
- function month(num) {
955
- return ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"][num] || "Unknown";
956
- }
957
- function suffix(num) {
958
- if (num % 100 >= 11 && num % 100 <= 13) return `${num}th`;
959
- switch (num % 10) {
960
- case 1:
961
- return `${num}st`;
962
- case 2:
963
- return `${num}nd`;
964
- case 3:
965
- return `${num}rd`;
966
- default:
967
- return `${num}th`;
941
+ function dayOfWeek(d) {
942
+ return ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"][d];
943
+ }
944
+ function dayOfYear(date) {
945
+ const start = new Date(Date.UTC(date.getUTCFullYear(), 0, 1));
946
+ return Math.ceil((date.getTime() - start.getTime()) / (1e3 * 60 * 60 * 24));
947
+ }
948
+ function formatDate(format = "YYYY-MM-DD H:mm", date = /* @__PURE__ */ new Date(), tz = "local") {
949
+ var _a;
950
+ if (typeof date === "number" || typeof date === "string") date = new Date(date);
951
+ if (isNaN(date.getTime())) throw new Error("Invalid date input");
952
+ const numericTz = typeof tz === "number";
953
+ const localTz = tz === "local" || !numericTz && ((_a = tz.toLowerCase) == null ? void 0 : _a.call(tz)) === "local";
954
+ const tzName = localTz ? Intl.DateTimeFormat().resolvedOptions().timeZone : numericTz ? "UTC" : tz;
955
+ if (!numericTz && tzName !== "UTC") {
956
+ try {
957
+ new Intl.DateTimeFormat("en-US", { timeZone: tzName }).format();
958
+ } catch {
959
+ throw new Error(`Invalid timezone: ${tzName}`);
960
+ }
961
+ }
962
+ let zonedDate = new Date(date);
963
+ if (!numericTz && tzName !== "UTC") {
964
+ const parts = new Intl.DateTimeFormat("en-US", {
965
+ timeZone: tzName,
966
+ year: "numeric",
967
+ month: "2-digit",
968
+ day: "2-digit",
969
+ hour: "2-digit",
970
+ minute: "2-digit",
971
+ second: "2-digit",
972
+ hour12: false
973
+ }).formatToParts(date);
974
+ const get2 = (type) => {
975
+ var _a2;
976
+ return (_a2 = parts.find((p) => p.type === type)) == null ? void 0 : _a2.value;
977
+ };
978
+ const build = `${get2("year")}-${get2("month")}-${get2("day")}T${get2("hour")}:${get2("minute")}:${get2("second")}Z`;
979
+ zonedDate = new Date(build);
980
+ } else if (numericTz || tzName === "UTC") {
981
+ const offset = numericTz ? tz : 0;
982
+ zonedDate = new Date(date.getTime() + offset * 60 * 60 * 1e3);
983
+ }
984
+ const get = (fn2) => numericTz || tzName === "UTC" ? zonedDate[`getUTC${fn2}`]() : zonedDate[`get${fn2}`]();
985
+ function getTZOffset() {
986
+ var _a2, _b;
987
+ if (numericTz) {
988
+ const total = tz * 60;
989
+ const hours = Math.floor(Math.abs(total) / 60);
990
+ const mins = Math.abs(total) % 60;
991
+ return `${tz >= 0 ? "+" : "-"}${String(hours).padStart(2, "0")}:${String(mins).padStart(2, "0")}`;
992
+ }
993
+ try {
994
+ const offset = (_b = (_a2 = new Intl.DateTimeFormat("en-US", { timeZone: tzName, timeZoneName: "longOffset", hour: "2-digit", minute: "2-digit" }).formatToParts(date).find((p) => p.type === "timeZoneName")) == null ? void 0 : _a2.value.match(/([+-]\d{2}:\d{2})/)) == null ? void 0 : _b[1];
995
+ if (offset) return offset;
996
+ } catch {
997
+ }
998
+ return "+00:00";
999
+ }
1000
+ function getTZAbbr() {
1001
+ var _a2;
1002
+ if (numericTz && tz === 0) return "UTC";
1003
+ try {
1004
+ return ((_a2 = new Intl.DateTimeFormat("en-US", { timeZone: tzName, timeZoneName: "short" }).formatToParts(date).find((p) => p.type === "timeZoneName")) == null ? void 0 : _a2.value) || "";
1005
+ } catch {
1006
+ return tzName;
968
1007
  }
969
1008
  }
970
- function tzOffset(offset) {
971
- const hours = ~~(offset / 60);
972
- const minutes = offset % 60;
973
- return (offset > 0 ? "-" : "") + `${hours}:${minutes.toString().padStart(2, "0")}`;
974
- }
975
- if (typeof date == "number" || typeof date == "string" || date == null) date = new Date(date);
976
- let t;
977
- if (tz == null) tz = -(date.getTimezoneOffset() / 60);
978
- t = timezones.find((t2) => isNaN(tz) ? t2[0] == tz : t2[1] == tz);
979
- if (!t) throw new Error(`Unknown timezone: ${tz}`);
980
- date = adjustTz(date, t[1]);
981
1009
  const tokens = {
982
- "YYYY": date.getFullYear().toString(),
983
- "YY": date.getFullYear().toString().slice(2),
984
- "MMMM": month(date.getMonth()),
985
- "MMM": month(date.getMonth()).slice(0, 3),
986
- "MM": (date.getMonth() + 1).toString().padStart(2, "0"),
987
- "M": (date.getMonth() + 1).toString(),
988
- "DDD": doy(date).toString(),
989
- "DD": date.getDate().toString().padStart(2, "0"),
990
- "Do": suffix(date.getDate()),
991
- "D": date.getDate().toString(),
992
- "dddd": day(date.getDay()),
993
- "ddd": day(date.getDay()).slice(0, 3),
994
- "HH": date.getHours().toString().padStart(2, "0"),
995
- "H": date.getHours().toString(),
996
- "hh": (date.getHours() % 12 || 12).toString().padStart(2, "0"),
997
- "h": (date.getHours() % 12 || 12).toString(),
998
- "mm": date.getMinutes().toString().padStart(2, "0"),
999
- "m": date.getMinutes().toString(),
1000
- "ss": date.getSeconds().toString().padStart(2, "0"),
1001
- "s": date.getSeconds().toString(),
1002
- "SSS": date.getMilliseconds().toString().padStart(3, "0"),
1003
- "A": date.getHours() >= 12 ? "PM" : "AM",
1004
- "a": date.getHours() >= 12 ? "pm" : "am",
1005
- "ZZ": tzOffset(t[1] * 60).replace(":", ""),
1006
- "Z": tzOffset(t[1] * 60),
1007
- "z": typeof tz == "string" ? tz : t[0]
1010
+ YYYY: get("FullYear").toString(),
1011
+ YY: get("FullYear").toString().slice(2),
1012
+ MMMM: month(get("Month")),
1013
+ MMM: month(get("Month")).slice(0, 3),
1014
+ MM: (get("Month") + 1).toString().padStart(2, "0"),
1015
+ M: (get("Month") + 1).toString(),
1016
+ DDD: dayOfYear(zonedDate).toString(),
1017
+ DD: get("Date").toString().padStart(2, "0"),
1018
+ Do: numSuffix(get("Date")),
1019
+ D: get("Date").toString(),
1020
+ dddd: dayOfWeek(get("Day")),
1021
+ ddd: dayOfWeek(get("Day")).slice(0, 3),
1022
+ HH: get("Hours").toString().padStart(2, "0"),
1023
+ H: get("Hours").toString(),
1024
+ hh: (get("Hours") % 12 || 12).toString().padStart(2, "0"),
1025
+ h: (get("Hours") % 12 || 12).toString(),
1026
+ mm: get("Minutes").toString().padStart(2, "0"),
1027
+ m: get("Minutes").toString(),
1028
+ ss: get("Seconds").toString().padStart(2, "0"),
1029
+ s: get("Seconds").toString(),
1030
+ SSS: get("Milliseconds").toString().padStart(3, "0"),
1031
+ A: get("Hours") >= 12 ? "PM" : "AM",
1032
+ a: get("Hours") >= 12 ? "pm" : "am",
1033
+ ZZ: getTZOffset().replace(":", ""),
1034
+ Z: getTZOffset(),
1035
+ z: getTZAbbr()
1008
1036
  };
1009
1037
  return format.replace(/YYYY|YY|MMMM|MMM|MM|M|DDD|DD|Do|D|dddd|ddd|HH|H|hh|h|mm|m|ss|s|SSS|A|a|ZZ|Z|z/g, (token) => tokens[token]);
1010
1038
  }
@@ -1012,6 +1040,9 @@ function instantInterval(fn2, interval) {
1012
1040
  fn2();
1013
1041
  return setInterval(fn2, interval);
1014
1042
  }
1043
+ function month(m) {
1044
+ return ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"][m];
1045
+ }
1015
1046
  function sleep(ms) {
1016
1047
  return new Promise((res) => setTimeout(res, ms));
1017
1048
  }
@@ -1760,29 +1791,6 @@ const _Logger = class _Logger extends TypedEmitter {
1760
1791
  };
1761
1792
  __publicField(_Logger, "LOG_LEVEL", 4);
1762
1793
  let Logger = _Logger;
1763
- function dec2Frac(num, maxDen = 1e3) {
1764
- let sign = Math.sign(num);
1765
- num = Math.abs(num);
1766
- if (Number.isInteger(num)) return sign * num + "";
1767
- let closest = { n: 0, d: 1, diff: Math.abs(num) };
1768
- for (let d = 1; d <= maxDen; d++) {
1769
- let n = Math.round(num * d);
1770
- let diff = Math.abs(num - n / d);
1771
- if (diff < closest.diff) {
1772
- closest = { n, d, diff };
1773
- if (diff < 1e-8) break;
1774
- }
1775
- }
1776
- let integer = Math.floor(closest.n / closest.d);
1777
- let numerator = closest.n - integer * closest.d;
1778
- return (sign < 0 ? "-" : "") + (integer ? integer + " " : "") + (numerator ? numerator + "/" + closest.d : "");
1779
- }
1780
- function fracToDec(frac) {
1781
- let split = frac.split(" ");
1782
- const whole = split.length == 2 ? Number(split[0]) : 0;
1783
- split = split.pop().split("/");
1784
- return whole + Number(split[0]) / Number(split[1]);
1785
- }
1786
1794
  function compareVersions(target, vs) {
1787
1795
  const [tMajor, tMinor, tPatch] = target.split(".").map((v) => +v.replace(/[^0-9]/g, ""));
1788
1796
  const [vMajor, vMinor, vPatch] = vs.split(".").map((v) => +v.replace(/[^0-9]/g, ""));
@@ -2376,6 +2384,8 @@ export {
2376
2384
  compareVersions,
2377
2385
  contrast,
2378
2386
  createJwt,
2387
+ dayOfWeek,
2388
+ dayOfYear,
2379
2389
  dec2Frac,
2380
2390
  decodeJwt,
2381
2391
  deepCopy,
@@ -2412,6 +2422,8 @@ export {
2412
2422
  matchAll,
2413
2423
  md5,
2414
2424
  mixin,
2425
+ month,
2426
+ numSuffix,
2415
2427
  pad,
2416
2428
  parseUrl,
2417
2429
  pascalCase,