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