@ztimson/utils 0.25.23 → 0.25.25
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/database.d.ts +4 -1
- package/dist/index.cjs +199 -175
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +199 -175
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -392,11 +392,179 @@ function makeUnique(arr) {
|
|
|
392
392
|
function makeArray(value) {
|
|
393
393
|
return Array.isArray(value) ? value : [value];
|
|
394
394
|
}
|
|
395
|
+
function adjustedInterval(cb, ms) {
|
|
396
|
+
let cancel = false, timeout = null;
|
|
397
|
+
const p = async () => {
|
|
398
|
+
if (cancel) return;
|
|
399
|
+
const start = (/* @__PURE__ */ new Date()).getTime();
|
|
400
|
+
await cb();
|
|
401
|
+
const end = (/* @__PURE__ */ new Date()).getTime();
|
|
402
|
+
timeout = setTimeout(() => p(), ms - (end - start) || 1);
|
|
403
|
+
};
|
|
404
|
+
p();
|
|
405
|
+
return () => {
|
|
406
|
+
cancel = true;
|
|
407
|
+
if (timeout) clearTimeout(timeout);
|
|
408
|
+
};
|
|
409
|
+
}
|
|
410
|
+
function formatDate(format = "YYYY-MM-DD H:mm", date = /* @__PURE__ */ new Date(), tz) {
|
|
411
|
+
const timezones = [
|
|
412
|
+
["IDLW", -12],
|
|
413
|
+
["SST", -11],
|
|
414
|
+
["HST", -10],
|
|
415
|
+
["AKST", -9],
|
|
416
|
+
["PST", -8],
|
|
417
|
+
["MST", -7],
|
|
418
|
+
["CST", -6],
|
|
419
|
+
["EST", -5],
|
|
420
|
+
["AST", -4],
|
|
421
|
+
["BRT", -3],
|
|
422
|
+
["MAT", -2],
|
|
423
|
+
["AZOT", -1],
|
|
424
|
+
["UTC", 0],
|
|
425
|
+
["CET", 1],
|
|
426
|
+
["EET", 2],
|
|
427
|
+
["MSK", 3],
|
|
428
|
+
["AST", 4],
|
|
429
|
+
["PKT", 5],
|
|
430
|
+
["IST", 5.5],
|
|
431
|
+
["BST", 6],
|
|
432
|
+
["ICT", 7],
|
|
433
|
+
["CST", 8],
|
|
434
|
+
["JST", 9],
|
|
435
|
+
["AEST", 10],
|
|
436
|
+
["SBT", 11],
|
|
437
|
+
["FJT", 12],
|
|
438
|
+
["TOT", 13],
|
|
439
|
+
["LINT", 14]
|
|
440
|
+
];
|
|
441
|
+
function adjustTz(date2, gmt) {
|
|
442
|
+
const currentOffset = date2.getTimezoneOffset();
|
|
443
|
+
const adjustedOffset = gmt * 60;
|
|
444
|
+
return new Date(date2.getTime() + (adjustedOffset + currentOffset) * 6e4);
|
|
445
|
+
}
|
|
446
|
+
function day(num) {
|
|
447
|
+
return ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"][num] || "Unknown";
|
|
448
|
+
}
|
|
449
|
+
function doy(date2) {
|
|
450
|
+
const start = /* @__PURE__ */ new Date(`${date2.getFullYear()}-01-01 0:00:00`);
|
|
451
|
+
return Math.ceil((date2.getTime() - start.getTime()) / (1e3 * 60 * 60 * 24));
|
|
452
|
+
}
|
|
453
|
+
function month(num) {
|
|
454
|
+
return ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"][num] || "Unknown";
|
|
455
|
+
}
|
|
456
|
+
function suffix(num) {
|
|
457
|
+
if (num % 100 >= 11 && num % 100 <= 13) return `${num}th`;
|
|
458
|
+
switch (num % 10) {
|
|
459
|
+
case 1:
|
|
460
|
+
return `${num}st`;
|
|
461
|
+
case 2:
|
|
462
|
+
return `${num}nd`;
|
|
463
|
+
case 3:
|
|
464
|
+
return `${num}rd`;
|
|
465
|
+
default:
|
|
466
|
+
return `${num}th`;
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
function tzOffset(offset) {
|
|
470
|
+
const hours = ~~(offset / 60);
|
|
471
|
+
const minutes = offset % 60;
|
|
472
|
+
return (offset > 0 ? "-" : "") + `${hours}:${minutes.toString().padStart(2, "0")}`;
|
|
473
|
+
}
|
|
474
|
+
if (typeof date == "number" || typeof date == "string" || date == null) date = new Date(date);
|
|
475
|
+
let t;
|
|
476
|
+
if (tz == null) tz = -(date.getTimezoneOffset() / 60);
|
|
477
|
+
t = timezones.find((t2) => isNaN(tz) ? t2[0] == tz : t2[1] == tz);
|
|
478
|
+
if (!t) throw new Error(`Unknown timezone: ${tz}`);
|
|
479
|
+
date = adjustTz(date, t[1]);
|
|
480
|
+
const tokens = {
|
|
481
|
+
"YYYY": date.getFullYear().toString(),
|
|
482
|
+
"YY": date.getFullYear().toString().slice(2),
|
|
483
|
+
"MMMM": month(date.getMonth()),
|
|
484
|
+
"MMM": month(date.getMonth()).slice(0, 3),
|
|
485
|
+
"MM": (date.getMonth() + 1).toString().padStart(2, "0"),
|
|
486
|
+
"M": (date.getMonth() + 1).toString(),
|
|
487
|
+
"DDD": doy(date).toString(),
|
|
488
|
+
"DD": date.getDate().toString().padStart(2, "0"),
|
|
489
|
+
"Do": suffix(date.getDate()),
|
|
490
|
+
"D": date.getDate().toString(),
|
|
491
|
+
"dddd": day(date.getDay()),
|
|
492
|
+
"ddd": day(date.getDay()).slice(0, 3),
|
|
493
|
+
"HH": date.getHours().toString().padStart(2, "0"),
|
|
494
|
+
"H": date.getHours().toString(),
|
|
495
|
+
"hh": (date.getHours() % 12 || 12).toString().padStart(2, "0"),
|
|
496
|
+
"h": (date.getHours() % 12 || 12).toString(),
|
|
497
|
+
"mm": date.getMinutes().toString().padStart(2, "0"),
|
|
498
|
+
"m": date.getMinutes().toString(),
|
|
499
|
+
"ss": date.getSeconds().toString().padStart(2, "0"),
|
|
500
|
+
"s": date.getSeconds().toString(),
|
|
501
|
+
"SSS": date.getMilliseconds().toString().padStart(3, "0"),
|
|
502
|
+
"A": date.getHours() >= 12 ? "PM" : "AM",
|
|
503
|
+
"a": date.getHours() >= 12 ? "pm" : "am",
|
|
504
|
+
"ZZ": tzOffset(t[1] * 60).replace(":", ""),
|
|
505
|
+
"Z": tzOffset(t[1] * 60),
|
|
506
|
+
"z": typeof tz == "string" ? tz : t[0]
|
|
507
|
+
};
|
|
508
|
+
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]);
|
|
509
|
+
}
|
|
510
|
+
function instantInterval(fn2, interval) {
|
|
511
|
+
fn2();
|
|
512
|
+
return setInterval(fn2, interval);
|
|
513
|
+
}
|
|
514
|
+
function sleep(ms) {
|
|
515
|
+
return new Promise((res) => setTimeout(res, ms));
|
|
516
|
+
}
|
|
517
|
+
async function sleepWhile(fn2, checkInterval = 100) {
|
|
518
|
+
while (await fn2()) await sleep(checkInterval);
|
|
519
|
+
}
|
|
520
|
+
function timeUntil(date) {
|
|
521
|
+
return (date instanceof Date ? date.getTime() : date) - (/* @__PURE__ */ new Date()).getTime();
|
|
522
|
+
}
|
|
523
|
+
function timezoneOffset(tz, date = /* @__PURE__ */ new Date()) {
|
|
524
|
+
const dtf = new Intl.DateTimeFormat("en-US", {
|
|
525
|
+
timeZone: tz,
|
|
526
|
+
hour12: false,
|
|
527
|
+
year: "numeric",
|
|
528
|
+
month: "2-digit",
|
|
529
|
+
day: "2-digit",
|
|
530
|
+
hour: "2-digit",
|
|
531
|
+
minute: "2-digit",
|
|
532
|
+
second: "2-digit"
|
|
533
|
+
});
|
|
534
|
+
const parts = dtf.formatToParts(date);
|
|
535
|
+
const get = (type) => {
|
|
536
|
+
var _a;
|
|
537
|
+
return Number((_a = parts.find((v) => v.type === type)) == null ? void 0 : _a.value);
|
|
538
|
+
};
|
|
539
|
+
const y = get("year");
|
|
540
|
+
const mo = get("month");
|
|
541
|
+
const d = get("day");
|
|
542
|
+
const h = get("hour");
|
|
543
|
+
const m = get("minute");
|
|
544
|
+
const s = get("second");
|
|
545
|
+
const asUTC = Date.UTC(y, mo - 1, d, h, m, s);
|
|
546
|
+
const asLocal = date.getTime();
|
|
547
|
+
return Math.round((asLocal - asUTC) / 6e4);
|
|
548
|
+
}
|
|
549
|
+
class AsyncLock {
|
|
550
|
+
constructor() {
|
|
551
|
+
__publicField(this, "p", Promise.resolve());
|
|
552
|
+
}
|
|
553
|
+
run(fn2) {
|
|
554
|
+
const res = this.p.then(fn2, fn2);
|
|
555
|
+
this.p = res.then(() => {
|
|
556
|
+
}, () => {
|
|
557
|
+
});
|
|
558
|
+
return res;
|
|
559
|
+
}
|
|
560
|
+
}
|
|
395
561
|
class Database {
|
|
396
562
|
constructor(database, tables, version) {
|
|
563
|
+
__publicField(this, "schemaLock", new AsyncLock());
|
|
564
|
+
__publicField(this, "upgrading", false);
|
|
397
565
|
__publicField(this, "connection");
|
|
398
|
-
__publicField(this, "ready", false);
|
|
399
566
|
__publicField(this, "tables");
|
|
567
|
+
__publicField(this, "waitForUpgrade", () => sleepWhile(() => this.upgrading));
|
|
400
568
|
this.database = database;
|
|
401
569
|
this.version = version;
|
|
402
570
|
this.connection = new Promise((resolve, reject) => {
|
|
@@ -423,9 +591,10 @@ class Database {
|
|
|
423
591
|
this.version = db.version;
|
|
424
592
|
resolve(db);
|
|
425
593
|
}
|
|
426
|
-
this.
|
|
594
|
+
this.upgrading = false;
|
|
427
595
|
};
|
|
428
596
|
req.onupgradeneeded = () => {
|
|
597
|
+
this.upgrading = true;
|
|
429
598
|
const db = req.result;
|
|
430
599
|
const existingTables = new ASet(Array.from(db.objectStoreNames));
|
|
431
600
|
if (tables) {
|
|
@@ -442,21 +611,30 @@ class Database {
|
|
|
442
611
|
};
|
|
443
612
|
});
|
|
444
613
|
}
|
|
614
|
+
get ready() {
|
|
615
|
+
return !this.upgrading;
|
|
616
|
+
}
|
|
445
617
|
async createTable(table) {
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
618
|
+
return this.schemaLock.run(async () => {
|
|
619
|
+
if (typeof table == "string") table = { name: table };
|
|
620
|
+
const conn = await this.connection;
|
|
621
|
+
if (!this.includes(table.name)) {
|
|
622
|
+
conn.close();
|
|
623
|
+
Object.assign(this, new Database(this.database, [...this.tables, table], (this.version ?? 0) + 1));
|
|
624
|
+
await this.connection;
|
|
625
|
+
}
|
|
626
|
+
return this.table(table.name);
|
|
627
|
+
});
|
|
453
628
|
}
|
|
454
629
|
async deleteTable(table) {
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
630
|
+
return this.schemaLock.run(async () => {
|
|
631
|
+
if (typeof table == "string") table = { name: table };
|
|
632
|
+
if (!this.includes(table.name)) return;
|
|
633
|
+
const conn = await this.connection;
|
|
634
|
+
conn.close();
|
|
635
|
+
Object.assign(this, new Database(this.database, this.tables.filter((t) => t.name != table.name), (this.version ?? 0) + 1));
|
|
636
|
+
await this.connection;
|
|
637
|
+
});
|
|
460
638
|
}
|
|
461
639
|
includes(name) {
|
|
462
640
|
return !!this.tables.find((t) => t.name == (typeof name == "object" ? name.name : name.toString()));
|
|
@@ -479,6 +657,7 @@ class Table {
|
|
|
479
657
|
});
|
|
480
658
|
}
|
|
481
659
|
async tx(table, fn2, readonly = false) {
|
|
660
|
+
await this.database.waitForUpgrade();
|
|
482
661
|
const db = await this.database.connection;
|
|
483
662
|
const tx = db.transaction(table, readonly ? "readonly" : "readwrite");
|
|
484
663
|
const store = tx.objectStore(table);
|
|
@@ -580,17 +759,16 @@ class Cache {
|
|
|
580
759
|
if (this.options.storage) {
|
|
581
760
|
if (this.options.storage instanceof Table) {
|
|
582
761
|
if (key == null) {
|
|
583
|
-
|
|
762
|
+
let rows = this.entries();
|
|
584
763
|
rows.forEach(([k, v]) => {
|
|
585
764
|
var _a;
|
|
586
765
|
return (_a = this.options.storage) == null ? void 0 : _a.put(k, v);
|
|
587
766
|
});
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
});
|
|
767
|
+
rows = rows.map(([k]) => k);
|
|
768
|
+
this.options.storage.getAllKeys().then((keys) => keys.filter((k) => !rows.includes(k)).forEach((k) => {
|
|
769
|
+
var _a;
|
|
770
|
+
return (_a = this.options.storage) == null ? void 0 : _a.delete(k);
|
|
771
|
+
}));
|
|
594
772
|
} else if (this.store[key] === void 0) this.options.storage.delete(key);
|
|
595
773
|
else this.options.storage.put(key, this.store[key]);
|
|
596
774
|
} else if (this.options.storageKey) {
|
|
@@ -993,160 +1171,6 @@ class PromiseProgress extends Promise {
|
|
|
993
1171
|
return this.from(super.finally(res));
|
|
994
1172
|
}
|
|
995
1173
|
}
|
|
996
|
-
function adjustedInterval(cb, ms) {
|
|
997
|
-
let cancel = false, timeout = null;
|
|
998
|
-
const p = async () => {
|
|
999
|
-
if (cancel) return;
|
|
1000
|
-
const start = (/* @__PURE__ */ new Date()).getTime();
|
|
1001
|
-
await cb();
|
|
1002
|
-
const end = (/* @__PURE__ */ new Date()).getTime();
|
|
1003
|
-
timeout = setTimeout(() => p(), ms - (end - start) || 1);
|
|
1004
|
-
};
|
|
1005
|
-
p();
|
|
1006
|
-
return () => {
|
|
1007
|
-
cancel = true;
|
|
1008
|
-
if (timeout) clearTimeout(timeout);
|
|
1009
|
-
};
|
|
1010
|
-
}
|
|
1011
|
-
function formatDate(format = "YYYY-MM-DD H:mm", date = /* @__PURE__ */ new Date(), tz) {
|
|
1012
|
-
const timezones = [
|
|
1013
|
-
["IDLW", -12],
|
|
1014
|
-
["SST", -11],
|
|
1015
|
-
["HST", -10],
|
|
1016
|
-
["AKST", -9],
|
|
1017
|
-
["PST", -8],
|
|
1018
|
-
["MST", -7],
|
|
1019
|
-
["CST", -6],
|
|
1020
|
-
["EST", -5],
|
|
1021
|
-
["AST", -4],
|
|
1022
|
-
["BRT", -3],
|
|
1023
|
-
["MAT", -2],
|
|
1024
|
-
["AZOT", -1],
|
|
1025
|
-
["UTC", 0],
|
|
1026
|
-
["CET", 1],
|
|
1027
|
-
["EET", 2],
|
|
1028
|
-
["MSK", 3],
|
|
1029
|
-
["AST", 4],
|
|
1030
|
-
["PKT", 5],
|
|
1031
|
-
["IST", 5.5],
|
|
1032
|
-
["BST", 6],
|
|
1033
|
-
["ICT", 7],
|
|
1034
|
-
["CST", 8],
|
|
1035
|
-
["JST", 9],
|
|
1036
|
-
["AEST", 10],
|
|
1037
|
-
["SBT", 11],
|
|
1038
|
-
["FJT", 12],
|
|
1039
|
-
["TOT", 13],
|
|
1040
|
-
["LINT", 14]
|
|
1041
|
-
];
|
|
1042
|
-
function adjustTz(date2, gmt) {
|
|
1043
|
-
const currentOffset = date2.getTimezoneOffset();
|
|
1044
|
-
const adjustedOffset = gmt * 60;
|
|
1045
|
-
return new Date(date2.getTime() + (adjustedOffset + currentOffset) * 6e4);
|
|
1046
|
-
}
|
|
1047
|
-
function day(num) {
|
|
1048
|
-
return ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"][num] || "Unknown";
|
|
1049
|
-
}
|
|
1050
|
-
function doy(date2) {
|
|
1051
|
-
const start = /* @__PURE__ */ new Date(`${date2.getFullYear()}-01-01 0:00:00`);
|
|
1052
|
-
return Math.ceil((date2.getTime() - start.getTime()) / (1e3 * 60 * 60 * 24));
|
|
1053
|
-
}
|
|
1054
|
-
function month(num) {
|
|
1055
|
-
return ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"][num] || "Unknown";
|
|
1056
|
-
}
|
|
1057
|
-
function suffix(num) {
|
|
1058
|
-
if (num % 100 >= 11 && num % 100 <= 13) return `${num}th`;
|
|
1059
|
-
switch (num % 10) {
|
|
1060
|
-
case 1:
|
|
1061
|
-
return `${num}st`;
|
|
1062
|
-
case 2:
|
|
1063
|
-
return `${num}nd`;
|
|
1064
|
-
case 3:
|
|
1065
|
-
return `${num}rd`;
|
|
1066
|
-
default:
|
|
1067
|
-
return `${num}th`;
|
|
1068
|
-
}
|
|
1069
|
-
}
|
|
1070
|
-
function tzOffset(offset) {
|
|
1071
|
-
const hours = ~~(offset / 60);
|
|
1072
|
-
const minutes = offset % 60;
|
|
1073
|
-
return (offset > 0 ? "-" : "") + `${hours}:${minutes.toString().padStart(2, "0")}`;
|
|
1074
|
-
}
|
|
1075
|
-
if (typeof date == "number" || typeof date == "string" || date == null) date = new Date(date);
|
|
1076
|
-
let t;
|
|
1077
|
-
if (tz == null) tz = -(date.getTimezoneOffset() / 60);
|
|
1078
|
-
t = timezones.find((t2) => isNaN(tz) ? t2[0] == tz : t2[1] == tz);
|
|
1079
|
-
if (!t) throw new Error(`Unknown timezone: ${tz}`);
|
|
1080
|
-
date = adjustTz(date, t[1]);
|
|
1081
|
-
const tokens = {
|
|
1082
|
-
"YYYY": date.getFullYear().toString(),
|
|
1083
|
-
"YY": date.getFullYear().toString().slice(2),
|
|
1084
|
-
"MMMM": month(date.getMonth()),
|
|
1085
|
-
"MMM": month(date.getMonth()).slice(0, 3),
|
|
1086
|
-
"MM": (date.getMonth() + 1).toString().padStart(2, "0"),
|
|
1087
|
-
"M": (date.getMonth() + 1).toString(),
|
|
1088
|
-
"DDD": doy(date).toString(),
|
|
1089
|
-
"DD": date.getDate().toString().padStart(2, "0"),
|
|
1090
|
-
"Do": suffix(date.getDate()),
|
|
1091
|
-
"D": date.getDate().toString(),
|
|
1092
|
-
"dddd": day(date.getDay()),
|
|
1093
|
-
"ddd": day(date.getDay()).slice(0, 3),
|
|
1094
|
-
"HH": date.getHours().toString().padStart(2, "0"),
|
|
1095
|
-
"H": date.getHours().toString(),
|
|
1096
|
-
"hh": (date.getHours() % 12 || 12).toString().padStart(2, "0"),
|
|
1097
|
-
"h": (date.getHours() % 12 || 12).toString(),
|
|
1098
|
-
"mm": date.getMinutes().toString().padStart(2, "0"),
|
|
1099
|
-
"m": date.getMinutes().toString(),
|
|
1100
|
-
"ss": date.getSeconds().toString().padStart(2, "0"),
|
|
1101
|
-
"s": date.getSeconds().toString(),
|
|
1102
|
-
"SSS": date.getMilliseconds().toString().padStart(3, "0"),
|
|
1103
|
-
"A": date.getHours() >= 12 ? "PM" : "AM",
|
|
1104
|
-
"a": date.getHours() >= 12 ? "pm" : "am",
|
|
1105
|
-
"ZZ": tzOffset(t[1] * 60).replace(":", ""),
|
|
1106
|
-
"Z": tzOffset(t[1] * 60),
|
|
1107
|
-
"z": typeof tz == "string" ? tz : t[0]
|
|
1108
|
-
};
|
|
1109
|
-
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]);
|
|
1110
|
-
}
|
|
1111
|
-
function instantInterval(fn2, interval) {
|
|
1112
|
-
fn2();
|
|
1113
|
-
return setInterval(fn2, interval);
|
|
1114
|
-
}
|
|
1115
|
-
function sleep(ms) {
|
|
1116
|
-
return new Promise((res) => setTimeout(res, ms));
|
|
1117
|
-
}
|
|
1118
|
-
async function sleepWhile(fn2, checkInterval = 100) {
|
|
1119
|
-
while (await fn2()) await sleep(checkInterval);
|
|
1120
|
-
}
|
|
1121
|
-
function timeUntil(date) {
|
|
1122
|
-
return (date instanceof Date ? date.getTime() : date) - (/* @__PURE__ */ new Date()).getTime();
|
|
1123
|
-
}
|
|
1124
|
-
function timezoneOffset(tz, date = /* @__PURE__ */ new Date()) {
|
|
1125
|
-
const dtf = new Intl.DateTimeFormat("en-US", {
|
|
1126
|
-
timeZone: tz,
|
|
1127
|
-
hour12: false,
|
|
1128
|
-
year: "numeric",
|
|
1129
|
-
month: "2-digit",
|
|
1130
|
-
day: "2-digit",
|
|
1131
|
-
hour: "2-digit",
|
|
1132
|
-
minute: "2-digit",
|
|
1133
|
-
second: "2-digit"
|
|
1134
|
-
});
|
|
1135
|
-
const parts = dtf.formatToParts(date);
|
|
1136
|
-
const get = (type) => {
|
|
1137
|
-
var _a;
|
|
1138
|
-
return Number((_a = parts.find((v) => v.type === type)) == null ? void 0 : _a.value);
|
|
1139
|
-
};
|
|
1140
|
-
const y = get("year");
|
|
1141
|
-
const mo = get("month");
|
|
1142
|
-
const d = get("day");
|
|
1143
|
-
const h = get("hour");
|
|
1144
|
-
const m = get("minute");
|
|
1145
|
-
const s = get("second");
|
|
1146
|
-
const asUTC = Date.UTC(y, mo - 1, d, h, m, s);
|
|
1147
|
-
const asLocal = date.getTime();
|
|
1148
|
-
return Math.round((asLocal - asUTC) / 6e4);
|
|
1149
|
-
}
|
|
1150
1174
|
function downloadFile(blob, name) {
|
|
1151
1175
|
if (!(blob instanceof Blob)) blob = new Blob(makeArray(blob));
|
|
1152
1176
|
const url = URL.createObjectURL(blob);
|