@push.rocks/smarttime 4.1.0 → 4.2.1
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_bundle/bundle.js +1 -1
- package/dist_bundle/bundle.js.map +2 -2
- package/dist_ts/00_commitinfo_data.js +1 -1
- package/dist_ts/smarttime.classes.cronjob.js +4 -2
- package/dist_ts/smarttime.classes.cronmanager.d.ts +6 -0
- package/dist_ts/smarttime.classes.cronmanager.js +44 -20
- package/dist_ts/smarttime.units.js +2 -2
- package/npmextra.json +8 -0
- package/package.json +18 -18
- package/readme.md +200 -64
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/smarttime.classes.cronjob.ts +3 -2
- package/ts/smarttime.classes.cronmanager.ts +47 -27
- package/ts/smarttime.units.ts +1 -1
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
export const commitinfo = {
|
|
5
5
|
name: '@push.rocks/smarttime',
|
|
6
|
-
version: '4.1
|
|
6
|
+
version: '4.2.1',
|
|
7
7
|
description: 'Provides utilities for advanced time handling including cron jobs, timestamps, intervals, and more.'
|
|
8
8
|
};
|
|
9
9
|
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMDBfY29tbWl0aW5mb19kYXRhLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvMDBfY29tbWl0aW5mb19kYXRhLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztHQUVHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sVUFBVSxHQUFHO0lBQ3hCLElBQUksRUFBRSx1QkFBdUI7SUFDN0IsT0FBTyxFQUFFLE9BQU87SUFDaEIsV0FBVyxFQUFFLHFHQUFxRztDQUNuSCxDQUFBIn0=
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import * as plugins from './smarttime.plugins.js';
|
|
2
2
|
import { CronManager } from './smarttime.classes.cronmanager.js';
|
|
3
|
-
import { CronParser } from './smarttime.classes.cronparser.js';
|
|
4
3
|
export class CronJob {
|
|
5
4
|
constructor(cronManager, cronExpressionArg, jobFunction) {
|
|
6
5
|
this.status = 'initial';
|
|
@@ -13,6 +12,9 @@ export class CronJob {
|
|
|
13
12
|
* checks wether the cronjob needs to be executed
|
|
14
13
|
*/
|
|
15
14
|
checkExecution() {
|
|
15
|
+
if (this.status === 'stopped') {
|
|
16
|
+
return this.nextExecutionUnix;
|
|
17
|
+
}
|
|
16
18
|
if (this.nextExecutionUnix === 0) {
|
|
17
19
|
this.getNextExecutionTime();
|
|
18
20
|
}
|
|
@@ -41,4 +43,4 @@ export class CronJob {
|
|
|
41
43
|
this.status = 'stopped';
|
|
42
44
|
}
|
|
43
45
|
}
|
|
44
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
46
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic21hcnR0aW1lLmNsYXNzZXMuY3JvbmpvYi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3RzL3NtYXJ0dGltZS5jbGFzc2VzLmNyb25qb2IudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLE9BQU8sTUFBTSx3QkFBd0IsQ0FBQztBQUNsRCxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sb0NBQW9DLENBQUM7QUFNakUsTUFBTSxPQUFPLE9BQU87SUFPbEIsWUFBWSxXQUF3QixFQUFFLGlCQUF5QixFQUFFLFdBQXlCO1FBTG5GLFdBQU0sR0FBc0MsU0FBUyxDQUFDO1FBR3JELHNCQUFpQixHQUFXLENBQUMsQ0FBQztRQUdwQyxJQUFJLENBQUMsY0FBYyxHQUFHLGlCQUFpQixDQUFDO1FBQ3hDLElBQUksQ0FBQyxXQUFXLEdBQUcsV0FBVyxDQUFDO1FBQy9CLElBQUksQ0FBQyxVQUFVLEdBQUcsSUFBSSxPQUFPLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDO0lBQy9ELENBQUM7SUFFRDs7T0FFRztJQUNJLGNBQWM7UUFDbkIsSUFBSSxJQUFJLENBQUMsTUFBTSxLQUFLLFNBQVMsRUFBRSxDQUFDO1lBQzlCLE9BQU8sSUFBSSxDQUFDLGlCQUFpQixDQUFDO1FBQ2hDLENBQUM7UUFDRCxJQUFJLElBQUksQ0FBQyxpQkFBaUIsS0FBSyxDQUFDLEVBQUUsQ0FBQztZQUNqQyxJQUFJLENBQUMsb0JBQW9CLEVBQUUsQ0FBQztRQUM5QixDQUFDO1FBQ0QsSUFBSSxJQUFJLENBQUMsR0FBRyxFQUFFLEdBQUcsSUFBSSxDQUFDLGlCQUFpQixFQUFFLENBQUM7WUFDeEMsTUFBTSxZQUFZLEdBQUcsSUFBSSxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsaUJBQWlCLENBQUMsQ0FBQztZQUM5RCxJQUFJLFlBQVksWUFBWSxPQUFPLEVBQUUsQ0FBQztnQkFDcEMsWUFBWSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQzVDLENBQUM7WUFDRCxJQUFJLENBQUMsaUJBQWlCLEdBQUcsSUFBSSxDQUFDLG9CQUFvQixFQUFFLENBQUM7UUFDdkQsQ0FBQztRQUNELE9BQU8sSUFBSSxDQUFDLGlCQUFpQixDQUFDO0lBQ2hDLENBQUM7SUFFTSxvQkFBb0I7UUFDekIsT0FBTyxDQUFDLElBQUksQ0FBQyxpQkFBaUIsR0FBRyxJQUFJLENBQUMsR0FBRyxFQUFFLEdBQUcsSUFBSSxDQUFDLHNCQUFzQixFQUFFLENBQUMsQ0FBQztJQUMvRSxDQUFDO0lBRUQ7O09BRUc7SUFDSSxzQkFBc0I7UUFDM0IsT0FBTyxJQUFJLENBQUMsVUFBVSxDQUFDLFFBQVEsRUFBRSxDQUFDO0lBQ3BDLENBQUM7SUFFTSxLQUFLO1FBQ1YsSUFBSSxDQUFDLE1BQU0sR0FBRyxTQUFTLENBQUM7SUFDMUIsQ0FBQztJQUVNLElBQUk7UUFDVCxJQUFJLENBQUMsTUFBTSxHQUFHLFNBQVMsQ0FBQztJQUMxQixDQUFDO0NBQ0YifQ==
|
|
@@ -4,7 +4,13 @@ export declare class CronManager {
|
|
|
4
4
|
executionTimeout: plugins.smartdelay.Timeout<void>;
|
|
5
5
|
status: 'started' | 'stopped';
|
|
6
6
|
cronjobs: plugins.lik.ObjectMap<CronJob>;
|
|
7
|
+
private cycleWakeDeferred;
|
|
7
8
|
constructor();
|
|
9
|
+
/**
|
|
10
|
+
* Resolves the current wake deferred, causing the sleeping cycle
|
|
11
|
+
* to immediately recalculate instead of waiting for its timeout.
|
|
12
|
+
*/
|
|
13
|
+
private wakeCycle;
|
|
8
14
|
addCronjob(cronIdentifierArg: string, cronFunctionArg: TJobFunction): CronJob;
|
|
9
15
|
removeCronjob(cronjobArg: CronJob): void;
|
|
10
16
|
/**
|
|
@@ -1,22 +1,35 @@
|
|
|
1
1
|
import * as plugins from './smarttime.plugins.js';
|
|
2
2
|
import { CronJob } from './smarttime.classes.cronjob.js';
|
|
3
|
-
import { getMilliSecondsAsHumanReadableString } from './smarttime.units.js';
|
|
4
3
|
export class CronManager {
|
|
5
4
|
constructor() {
|
|
6
5
|
this.status = 'stopped';
|
|
7
6
|
this.cronjobs = new plugins.lik.ObjectMap();
|
|
7
|
+
this.cycleWakeDeferred = null;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Resolves the current wake deferred, causing the sleeping cycle
|
|
11
|
+
* to immediately recalculate instead of waiting for its timeout.
|
|
12
|
+
*/
|
|
13
|
+
wakeCycle() {
|
|
14
|
+
if (this.cycleWakeDeferred && this.cycleWakeDeferred.status === 'pending') {
|
|
15
|
+
this.cycleWakeDeferred.resolve();
|
|
16
|
+
}
|
|
8
17
|
}
|
|
9
18
|
addCronjob(cronIdentifierArg, cronFunctionArg) {
|
|
10
19
|
const newCronJob = new CronJob(this, cronIdentifierArg, cronFunctionArg);
|
|
11
20
|
this.cronjobs.add(newCronJob);
|
|
12
21
|
if (this.status === 'started') {
|
|
13
22
|
newCronJob.start();
|
|
23
|
+
this.wakeCycle();
|
|
14
24
|
}
|
|
15
25
|
return newCronJob;
|
|
16
26
|
}
|
|
17
27
|
removeCronjob(cronjobArg) {
|
|
18
28
|
cronjobArg.stop();
|
|
19
29
|
this.cronjobs.remove(cronjobArg);
|
|
30
|
+
if (this.status === 'started') {
|
|
31
|
+
this.wakeCycle();
|
|
32
|
+
}
|
|
20
33
|
}
|
|
21
34
|
/**
|
|
22
35
|
* starts the cronjob
|
|
@@ -31,42 +44,53 @@ export class CronManager {
|
|
|
31
44
|
}
|
|
32
45
|
}
|
|
33
46
|
async runCronCycle() {
|
|
34
|
-
this.
|
|
35
|
-
|
|
36
|
-
|
|
47
|
+
while (this.status === 'started') {
|
|
48
|
+
// Create a fresh wake signal for this iteration
|
|
49
|
+
this.cycleWakeDeferred = new plugins.smartpromise.Deferred();
|
|
50
|
+
// Check all cronjobs and find the soonest next execution
|
|
51
|
+
let soonestMs = Infinity;
|
|
37
52
|
for (const cronJob of this.cronjobs.getArray()) {
|
|
38
53
|
cronJob.checkExecution();
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
54
|
+
const msToNext = cronJob.getTimeToNextExecution();
|
|
55
|
+
if (msToNext < soonestMs) {
|
|
56
|
+
soonestMs = msToNext;
|
|
42
57
|
}
|
|
43
58
|
}
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
59
|
+
// Sleep until the next job is due or until woken by a lifecycle event
|
|
60
|
+
if (soonestMs < Infinity && soonestMs > 0) {
|
|
61
|
+
this.executionTimeout = new plugins.smartdelay.Timeout(soonestMs);
|
|
62
|
+
await Promise.race([
|
|
63
|
+
this.executionTimeout.promise,
|
|
64
|
+
this.cycleWakeDeferred.promise,
|
|
65
|
+
]);
|
|
66
|
+
// Cancel the timeout to avoid lingering timers
|
|
67
|
+
this.executionTimeout.cancel();
|
|
68
|
+
}
|
|
69
|
+
else if (soonestMs <= 0) {
|
|
70
|
+
// Job is overdue, loop immediately to execute it
|
|
71
|
+
continue;
|
|
47
72
|
}
|
|
48
73
|
else {
|
|
49
|
-
|
|
50
|
-
|
|
74
|
+
// No jobs — wait indefinitely until woken by addCronjob or stop
|
|
75
|
+
await this.cycleWakeDeferred.promise;
|
|
51
76
|
}
|
|
52
|
-
|
|
53
|
-
|
|
77
|
+
}
|
|
78
|
+
this.cycleWakeDeferred = null;
|
|
54
79
|
}
|
|
55
|
-
;
|
|
56
80
|
/**
|
|
57
81
|
* stops all cronjobs
|
|
58
82
|
*/
|
|
59
83
|
stop() {
|
|
60
84
|
if (this.status === 'started') {
|
|
61
85
|
this.status = 'stopped';
|
|
62
|
-
this.executionTimeout
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
86
|
+
if (this.executionTimeout) {
|
|
87
|
+
this.executionTimeout.cancel();
|
|
88
|
+
}
|
|
89
|
+
this.wakeCycle();
|
|
66
90
|
}
|
|
67
91
|
for (const cron of this.cronjobs.getArray()) {
|
|
68
92
|
cron.stop();
|
|
69
93
|
}
|
|
70
94
|
}
|
|
71
95
|
}
|
|
72
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
96
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic21hcnR0aW1lLmNsYXNzZXMuY3Jvbm1hbmFnZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9zbWFydHRpbWUuY2xhc3Nlcy5jcm9ubWFuYWdlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLHdCQUF3QixDQUFDO0FBQ2xELE9BQU8sRUFBRSxPQUFPLEVBQXFCLE1BQU0sZ0NBQWdDLENBQUM7QUFFNUUsTUFBTSxPQUFPLFdBQVc7SUFRdEI7UUFMTyxXQUFNLEdBQTBCLFNBQVMsQ0FBQztRQUMxQyxhQUFRLEdBQUcsSUFBSSxPQUFPLENBQUMsR0FBRyxDQUFDLFNBQVMsRUFBVyxDQUFDO1FBRS9DLHNCQUFpQixHQUErQyxJQUFJLENBQUM7SUFFOUQsQ0FBQztJQUVoQjs7O09BR0c7SUFDSyxTQUFTO1FBQ2YsSUFBSSxJQUFJLENBQUMsaUJBQWlCLElBQUksSUFBSSxDQUFDLGlCQUFpQixDQUFDLE1BQU0sS0FBSyxTQUFTLEVBQUUsQ0FBQztZQUMxRSxJQUFJLENBQUMsaUJBQWlCLENBQUMsT0FBTyxFQUFFLENBQUM7UUFDbkMsQ0FBQztJQUNILENBQUM7SUFFTSxVQUFVLENBQUMsaUJBQXlCLEVBQUUsZUFBNkI7UUFDeEUsTUFBTSxVQUFVLEdBQUcsSUFBSSxPQUFPLENBQUMsSUFBSSxFQUFFLGlCQUFpQixFQUFFLGVBQWUsQ0FBQyxDQUFDO1FBQ3pFLElBQUksQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLFVBQVUsQ0FBQyxDQUFDO1FBQzlCLElBQUksSUFBSSxDQUFDLE1BQU0sS0FBSyxTQUFTLEVBQUUsQ0FBQztZQUM5QixVQUFVLENBQUMsS0FBSyxFQUFFLENBQUM7WUFDbkIsSUFBSSxDQUFDLFNBQVMsRUFBRSxDQUFDO1FBQ25CLENBQUM7UUFFRCxPQUFPLFVBQVUsQ0FBQztJQUNwQixDQUFDO0lBRU0sYUFBYSxDQUFDLFVBQW1CO1FBQ3RDLFVBQVUsQ0FBQyxJQUFJLEVBQUUsQ0FB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
|
|
@@ -54,6 +54,6 @@ export const getMilliSecondsAsHumanReadableString = (milliSecondsArg) => {
|
|
|
54
54
|
return plugins.prettyMs(milliSecondsArg);
|
|
55
55
|
};
|
|
56
56
|
export const getMilliSecondsAsHumanReadableAgoTime = (timeStampArg) => {
|
|
57
|
-
return plugins.dateFns.formatDistanceToNow(timeStampArg);
|
|
57
|
+
return plugins.dateFns.formatDistanceToNow(new Date(timeStampArg));
|
|
58
58
|
};
|
|
59
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
59
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic21hcnR0aW1lLnVuaXRzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvc21hcnR0aW1lLnVuaXRzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxPQUFPLE1BQU0sd0JBQXdCLENBQUM7QUFFbEQsTUFBTSxDQUFDLElBQUksS0FBSyxHQUFHO0lBQ2pCLEtBQUssRUFBRSxDQUFDLFFBQVEsR0FBRyxDQUFDLEVBQVUsRUFBRTtRQUM5QixPQUFPLFFBQVEsR0FBRyxRQUFRLENBQUM7SUFDN0IsQ0FBQztJQUNELE1BQU0sRUFBRSxDQUFDLFFBQVEsR0FBRyxDQUFDLEVBQVUsRUFBRTtRQUMvQixPQUFPLFFBQVEsR0FBRyxPQUFPLENBQUM7SUFDNUIsQ0FBQztJQUNELEtBQUssRUFBRSxDQUFDLFFBQVEsR0FBRyxDQUFDLEVBQUUsRUFBRTtRQUN0QixPQUFPLFFBQVEsR0FBRyxPQUFPLENBQUM7SUFDNUIsQ0FBQztJQUNELElBQUksRUFBRSxDQUFDLFFBQVEsR0FBRyxDQUFDLEVBQUUsRUFBRTtRQUNyQixPQUFPLFFBQVEsR0FBRyxNQUFNLENBQUM7SUFDM0IsQ0FBQztJQUNELEtBQUssRUFBRSxDQUFDLFFBQVEsR0FBRyxDQUFDLEVBQUUsRUFBRTtRQUN0QixPQUFPLFFBQVEsR0FBRyxLQUFLLENBQUM7SUFDMUIsQ0FBQztJQUNELE9BQU8sRUFBRSxDQUFDLFFBQVEsR0FBRyxDQUFDLEVBQUUsRUFBRTtRQUN4QixPQUFPLFFBQVEsR0FBRyxLQUFLLENBQUM7SUFDMUIsQ0FBQztJQUNELE9BQU8sRUFBRSxDQUFDLFFBQVEsR0FBRyxDQUFDLEVBQUUsRUFBRTtRQUN4QixPQUFPLFFBQVEsR0FBRyxJQUFJLENBQUM7SUFDekIsQ0FBQztDQUNGLENBQUM7QUFZRixNQUFNLENBQUMsSUFBSSx3QkFBd0IsR0FBRyxDQUFDLGNBQW1DLEVBQUUsRUFBRTtJQUM1RSxJQUFJLGtCQUFrQixHQUFHLENBQUMsQ0FBQztJQUMzQixJQUFJLGVBQWUsR0FBRyxDQUFDLGVBQXVCLEVBQUUsRUFBRTtRQUNoRCxrQkFBa0IsR0FBRyxrQkFBa0IsR0FBRyxlQUFlLENBQUM7SUFDNUQsQ0FBQyxDQUFDO0lBQ0YsSUFBSSxjQUFjLENBQUMsS0FBSyxFQUFFLENBQUM7UUFDekIsZUFBZSxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsY0FBYyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUM7SUFDckQsQ0FBQztJQUNELElBQUksY0FBYyxDQUFDLE1BQU0sRUFBRSxDQUFDO1FBQzFCLGVBQWUsQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLGNBQWMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDO0lBQ3ZELENBQUM7SUFDRCxJQUFJLGNBQWMsQ0FBQyxLQUFLLEVBQUUsQ0FBQztRQUN6QixlQUFlLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxjQUFjLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQztJQUNyRCxDQUFDO0lBQ0QsSUFBSSxjQUFjLENBQUMsSUFBSSxFQUFFLENBQUM7UUFDeEIsZUFBZSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsY0FBYyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7SUFDbkQsQ0FBQztJQUNELElBQUksY0FBYyxDQUFDLEtBQUssRUFBRSxDQUFDO1FBQ3pCLGVBQWUsQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLGNBQWMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDO0lBQ3JELENBQUM7SUFDRCxJQUFJLGNBQWMsQ0FBQyxPQUFPLEVBQUUsQ0FBQztRQUMzQixlQUFlLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxjQUFjLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQztJQUN6RCxDQUFDO0lBQ0QsSUFBSSxjQUFjLENBQUMsT0FBTyxFQUFFLENBQUM7UUFDM0IsZUFBZSxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsY0FBYyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUM7SUFDekQsQ0FBQztJQUVELE9BQU8sa0JBQWtCLENBQUM7QUFDNUIsQ0FBQyxDQUFDO0FBRUYsTUFBTSxDQUFDLE1BQU0sb0NBQW9DLEdBQUcsQ0FBQyxlQUF1QixFQUFVLEVBQUU7SUFDdEYsT0FBTyxPQUFPLENBQUMsUUFBUSxDQUFDLGVBQWUsQ0FBQyxDQUFDO0FBQzNDLENBQUMsQ0FBQztBQUVGLE1BQU0sQ0FBQyxNQUFNLHFDQUFxQyxHQUFHLENBQUMsWUFBb0IsRUFBVSxFQUFFO0lBQ3BGLE9BQU8sT0FBTyxDQUFDLE9BQU8sQ0FBQyxtQkFBbUIsQ0FBQyxJQUFJLElBQUksQ0FBQyxZQUFZLENBQUMsQ0FBQyxDQUFDO0FBQ3JFLENBQUMsQ0FBQSJ9
|
package/npmextra.json
CHANGED
|
@@ -25,5 +25,13 @@
|
|
|
25
25
|
},
|
|
26
26
|
"tsdoc": {
|
|
27
27
|
"legal": "\n## License and Legal Information\n\nThis repository contains open-source code that is licensed under the MIT License. A copy of the MIT License can be found in the [license](license) file within this repository. \n\n**Please note:** The MIT License does not grant permission to use the trade names, trademarks, service marks, or product names of the project, except as required for reasonable and customary use in describing the origin of the work and reproducing the content of the NOTICE file.\n\n### Trademarks\n\nThis project is owned and maintained by Task Venture Capital GmbH. The names and logos associated with Task Venture Capital GmbH and any related products or services are trademarks of Task Venture Capital GmbH and are not included within the scope of the MIT license granted herein. Use of these trademarks must comply with Task Venture Capital GmbH's Trademark Guidelines, and any usage must be approved in writing by Task Venture Capital GmbH.\n\n### Company Information\n\nTask Venture Capital GmbH \nRegistered at District court Bremen HRB 35230 HB, Germany\n\nFor any legal inquiries or if you require further information, please contact us via email at hello@task.vc.\n\nBy using this repository, you acknowledge that you have read this section, agree to comply with its terms, and understand that the licensing of the code does not imply endorsement by Task Venture Capital GmbH of any derivative works.\n"
|
|
28
|
+
},
|
|
29
|
+
"@git.zone/cli": {
|
|
30
|
+
"release": {
|
|
31
|
+
"registries": [
|
|
32
|
+
"https://registry.npmjs.org"
|
|
33
|
+
],
|
|
34
|
+
"accessLevel": "public"
|
|
35
|
+
}
|
|
28
36
|
}
|
|
29
37
|
}
|
package/package.json
CHANGED
|
@@ -1,29 +1,34 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@push.rocks/smarttime",
|
|
3
3
|
"private": false,
|
|
4
|
-
"version": "4.1
|
|
4
|
+
"version": "4.2.1",
|
|
5
5
|
"description": "Provides utilities for advanced time handling including cron jobs, timestamps, intervals, and more.",
|
|
6
6
|
"main": "dist_ts/index.js",
|
|
7
7
|
"typings": "dist_ts/index.d.ts",
|
|
8
8
|
"author": "Lossless GmbH",
|
|
9
9
|
"license": "MIT",
|
|
10
|
+
"scripts": {
|
|
11
|
+
"test": "(tstest ./test)",
|
|
12
|
+
"build": "(tsbuild --web && tsbundle npm)",
|
|
13
|
+
"buildDocs": "tsdoc"
|
|
14
|
+
},
|
|
10
15
|
"devDependencies": {
|
|
11
|
-
"@git.zone/tsbuild": "^
|
|
12
|
-
"@git.zone/tsbundle": "^2.
|
|
13
|
-
"@git.zone/tsrun": "^
|
|
14
|
-
"@git.zone/tstest": "^1.
|
|
15
|
-
"@push.rocks/tapbundle": "^
|
|
16
|
-
"@types/node": "^
|
|
16
|
+
"@git.zone/tsbuild": "^4.1.2",
|
|
17
|
+
"@git.zone/tsbundle": "^2.8.3",
|
|
18
|
+
"@git.zone/tsrun": "^2.0.1",
|
|
19
|
+
"@git.zone/tstest": "^3.1.8",
|
|
20
|
+
"@push.rocks/tapbundle": "^6.0.3",
|
|
21
|
+
"@types/node": "^25.2.3"
|
|
17
22
|
},
|
|
18
23
|
"dependencies": {
|
|
19
|
-
"@push.rocks/lik": "^6.
|
|
24
|
+
"@push.rocks/lik": "^6.2.2",
|
|
20
25
|
"@push.rocks/smartdelay": "^3.0.5",
|
|
21
|
-
"@push.rocks/smartpromise": "^4.
|
|
22
|
-
"croner": "^
|
|
26
|
+
"@push.rocks/smartpromise": "^4.2.3",
|
|
27
|
+
"croner": "^10.0.1",
|
|
23
28
|
"date-fns": "^4.1.0",
|
|
24
|
-
"dayjs": "^1.11.
|
|
29
|
+
"dayjs": "^1.11.19",
|
|
25
30
|
"is-nan": "^1.3.2",
|
|
26
|
-
"pretty-ms": "^9.
|
|
31
|
+
"pretty-ms": "^9.3.0"
|
|
27
32
|
},
|
|
28
33
|
"files": [
|
|
29
34
|
"ts/**/*",
|
|
@@ -54,10 +59,5 @@
|
|
|
54
59
|
"repository": {
|
|
55
60
|
"type": "git",
|
|
56
61
|
"url": "https://code.foss.global/push.rocks/smarttime.git"
|
|
57
|
-
},
|
|
58
|
-
"scripts": {
|
|
59
|
-
"test": "(tstest ./test)",
|
|
60
|
-
"build": "(tsbuild --web && tsbundle npm)",
|
|
61
|
-
"buildDocs": "tsdoc"
|
|
62
62
|
}
|
|
63
|
-
}
|
|
63
|
+
}
|
package/readme.md
CHANGED
|
@@ -1,147 +1,283 @@
|
|
|
1
1
|
# @push.rocks/smarttime
|
|
2
|
-
|
|
2
|
+
|
|
3
|
+
Handle time in smart ways — cron scheduling, extended dates, precise measurements, timers, intervals, and human-readable formatting. 🕐
|
|
4
|
+
|
|
5
|
+
## Issue Reporting and Security
|
|
6
|
+
|
|
7
|
+
For reporting bugs, issues, or security vulnerabilities, please visit [community.foss.global/](https://community.foss.global/). This is the central community hub for all issue reporting. Developers who sign and comply with our contribution agreement and go through identification can also get a [code.foss.global/](https://code.foss.global/) account to submit Pull Requests directly.
|
|
3
8
|
|
|
4
9
|
## Install
|
|
5
|
-
To install `@push.rocks/smarttime`, use the following npm command:
|
|
6
10
|
|
|
7
11
|
```bash
|
|
8
|
-
npm install @push.rocks/smarttime
|
|
12
|
+
npm install @push.rocks/smarttime
|
|
9
13
|
```
|
|
10
14
|
|
|
11
|
-
|
|
15
|
+
or with pnpm:
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
pnpm install @push.rocks/smarttime
|
|
19
|
+
```
|
|
12
20
|
|
|
13
21
|
## Usage
|
|
14
22
|
|
|
15
|
-
`@push.rocks/smarttime`
|
|
23
|
+
`@push.rocks/smarttime` is a comprehensive TypeScript-first toolkit for working with time. It covers everything from cron-based scheduling and extended date manipulation to high-resolution measurements, timers, intervals, and human-readable time formatting.
|
|
24
|
+
|
|
25
|
+
All examples below use ESM imports and TypeScript.
|
|
26
|
+
|
|
27
|
+
### ⏱️ Time Units & Calculations
|
|
16
28
|
|
|
17
|
-
|
|
29
|
+
Convert human-readable time durations into milliseconds using the `units` helpers and `getMilliSecondsFromUnits`:
|
|
18
30
|
|
|
19
|
-
#### Working with Units
|
|
20
31
|
```typescript
|
|
21
32
|
import { units, getMilliSecondsFromUnits } from '@push.rocks/smarttime';
|
|
22
33
|
|
|
23
|
-
//
|
|
24
|
-
|
|
34
|
+
// Individual unit conversions
|
|
35
|
+
const oneDay = units.days(1); // 86400000
|
|
36
|
+
const twoHours = units.hours(2); // 7200000
|
|
37
|
+
const thirtySeconds = units.seconds(30); // 30000
|
|
38
|
+
|
|
39
|
+
// Combined duration — great for timeouts, TTLs, cache expiration, etc.
|
|
40
|
+
const duration = getMilliSecondsFromUnits({
|
|
25
41
|
years: 1,
|
|
26
42
|
months: 2,
|
|
27
43
|
weeks: 3,
|
|
28
44
|
days: 4,
|
|
29
45
|
hours: 5,
|
|
30
46
|
minutes: 6,
|
|
31
|
-
seconds: 7
|
|
47
|
+
seconds: 7,
|
|
32
48
|
});
|
|
33
49
|
|
|
34
|
-
console.log(`Duration
|
|
50
|
+
console.log(`Duration: ${duration}ms`);
|
|
35
51
|
```
|
|
36
52
|
|
|
37
|
-
|
|
53
|
+
### 🗓️ Human-Readable Time Formatting
|
|
54
|
+
|
|
55
|
+
Turn raw milliseconds into a friendly string, or get a relative "time ago" description:
|
|
56
|
+
|
|
57
|
+
```typescript
|
|
58
|
+
import {
|
|
59
|
+
getMilliSecondsAsHumanReadableString,
|
|
60
|
+
getMilliSecondsAsHumanReadableAgoTime,
|
|
61
|
+
} from '@push.rocks/smarttime';
|
|
62
|
+
|
|
63
|
+
// "2h 30m"
|
|
64
|
+
console.log(getMilliSecondsAsHumanReadableString(9_000_000));
|
|
65
|
+
|
|
66
|
+
// "5 minutes ago" style output
|
|
67
|
+
const fiveMinutesAgo = Date.now() - 5 * 60 * 1000;
|
|
68
|
+
console.log(getMilliSecondsAsHumanReadableAgoTime(fiveMinutesAgo));
|
|
69
|
+
```
|
|
38
70
|
|
|
39
|
-
###
|
|
71
|
+
### 🔄 CronManager — Scheduled Task Execution
|
|
40
72
|
|
|
41
|
-
|
|
73
|
+
The `CronManager` lets you register and run multiple cron jobs using standard 6-field cron syntax (seconds included). Powered by [croner](https://github.com/Hexagon/croner).
|
|
42
74
|
|
|
43
|
-
#### Creating and Starting a CronManager
|
|
44
75
|
```typescript
|
|
45
76
|
import { CronManager } from '@push.rocks/smarttime';
|
|
46
77
|
|
|
47
78
|
const cronManager = new CronManager();
|
|
48
79
|
|
|
49
|
-
//
|
|
50
|
-
cronManager.addCronjob('* * * * *', async () => {
|
|
51
|
-
console.log(
|
|
80
|
+
// Run every 10 seconds
|
|
81
|
+
const job1 = cronManager.addCronjob('*/10 * * * * *', async (triggerTime) => {
|
|
82
|
+
console.log(`Job 1 triggered at ${new Date(triggerTime).toISOString()}`);
|
|
52
83
|
});
|
|
53
84
|
|
|
54
|
-
//
|
|
85
|
+
// Run every full minute
|
|
86
|
+
const job2 = cronManager.addCronjob('0 * * * * *', async () => {
|
|
87
|
+
console.log('Full minute tick!');
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
// Start all registered jobs
|
|
55
91
|
cronManager.start();
|
|
92
|
+
|
|
93
|
+
// Later: remove a specific job
|
|
94
|
+
cronManager.removeCronjob(job1);
|
|
95
|
+
|
|
96
|
+
// Stop all jobs
|
|
97
|
+
cronManager.stop();
|
|
56
98
|
```
|
|
57
99
|
|
|
58
|
-
The
|
|
100
|
+
The `CronManager` automatically calculates the shortest sleep interval between jobs and efficiently schedules wake-ups — no polling required.
|
|
59
101
|
|
|
60
|
-
###
|
|
102
|
+
### 📅 ExtendedDate — Enhanced Date Handling
|
|
61
103
|
|
|
62
|
-
|
|
104
|
+
`ExtendedDate` extends the native JavaScript `Date` with factory methods for common date formats and useful inspection methods:
|
|
63
105
|
|
|
64
|
-
#### Creating ExtendedDate Instances
|
|
65
106
|
```typescript
|
|
66
107
|
import { ExtendedDate } from '@push.rocks/smarttime';
|
|
67
108
|
|
|
68
|
-
//
|
|
69
|
-
const
|
|
70
|
-
console.log(dateFromEuroString.toString());
|
|
109
|
+
// From European format: "DD.MM.YYYY"
|
|
110
|
+
const date1 = ExtendedDate.fromEuropeanDate('25.12.2024');
|
|
71
111
|
|
|
72
|
-
//
|
|
73
|
-
const
|
|
74
|
-
console.log(dateFromHyphedString.toString());
|
|
75
|
-
```
|
|
112
|
+
// From European date + time with timezone context
|
|
113
|
+
const date2 = ExtendedDate.fromEuropeanDateAndTime('25.12.2024', '14:30:00', 'Europe/Berlin');
|
|
76
114
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
import { ExtendedDate } from '@push.rocks/smarttime';
|
|
115
|
+
// From hyphenated date: "YYYY-MM-DD"
|
|
116
|
+
const date3 = ExtendedDate.fromHyphedDate('2024-12-25');
|
|
80
117
|
|
|
81
|
-
|
|
82
|
-
|
|
118
|
+
// From milliseconds
|
|
119
|
+
const date4 = ExtendedDate.fromMillis(Date.now());
|
|
120
|
+
|
|
121
|
+
// From an existing Date object
|
|
122
|
+
const date5 = ExtendedDate.fromDate(new Date());
|
|
123
|
+
|
|
124
|
+
// Export back to various formats
|
|
125
|
+
console.log(date1.exportToEuropeanDate()); // "25.12.2024"
|
|
126
|
+
console.log(date1.exportToHyphedSortableDate()); // "2024-12-25"
|
|
127
|
+
|
|
128
|
+
// Get structured date units
|
|
129
|
+
const units = date1.exportToUnits();
|
|
130
|
+
console.log(units.monthName); // "December"
|
|
131
|
+
console.log(units.dayOfTheWeekName); // "Wednesday"
|
|
132
|
+
|
|
133
|
+
// Custom formatting (via dayjs)
|
|
134
|
+
console.log(date1.format('YYYY-MM-DD HH:mm'));
|
|
135
|
+
|
|
136
|
+
// Boolean checks
|
|
137
|
+
console.log(date4.isToday()); // true
|
|
138
|
+
|
|
139
|
+
// Time comparison: has less than 1 hour passed since this date?
|
|
140
|
+
console.log(date4.lessTimePassedToNow({ hours: 1 })); // true
|
|
141
|
+
console.log(date4.moreTimePassedToNow({ days: 1 })); // false
|
|
83
142
|
```
|
|
84
143
|
|
|
85
|
-
|
|
144
|
+
### ⏱️ HrtMeasurement — High-Resolution Timing
|
|
86
145
|
|
|
87
|
-
|
|
88
|
-
For performance testing and high-resolution time tracking, `@push.rocks/smarttime` provides the `HrtMeasurement` class.
|
|
146
|
+
Measure the duration of operations with precision:
|
|
89
147
|
|
|
90
148
|
```typescript
|
|
91
149
|
import { HrtMeasurement } from '@push.rocks/smarttime';
|
|
92
150
|
|
|
93
|
-
const
|
|
94
|
-
|
|
95
|
-
// Simulate some operations...
|
|
96
|
-
setTimeout(() => {
|
|
97
|
-
hrtMeasurement.stop();
|
|
98
|
-
console.log(`Operation took ${hrtMeasurement.milliSeconds} milliseconds.`);
|
|
99
|
-
}, 1000);
|
|
100
|
-
```
|
|
151
|
+
const measurement = new HrtMeasurement();
|
|
152
|
+
measurement.start();
|
|
101
153
|
|
|
102
|
-
|
|
154
|
+
// ... perform some operation ...
|
|
103
155
|
|
|
104
|
-
|
|
156
|
+
measurement.stop();
|
|
157
|
+
console.log(`Took ${measurement.milliSeconds}ms`);
|
|
158
|
+
console.log(`Took ${measurement.nanoSeconds}ns`);
|
|
105
159
|
|
|
106
|
-
|
|
160
|
+
// Reset and reuse
|
|
161
|
+
measurement.reset();
|
|
162
|
+
measurement.start();
|
|
163
|
+
// ...
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
### ⏲️ Timer — Pausable Countdown
|
|
167
|
+
|
|
168
|
+
A promise-based timer with pause, resume, and reset capabilities:
|
|
107
169
|
|
|
108
|
-
#### Using the Timer class
|
|
109
170
|
```typescript
|
|
110
171
|
import { Timer } from '@push.rocks/smarttime';
|
|
111
172
|
|
|
112
|
-
const timer = new Timer(5000); //
|
|
173
|
+
const timer = new Timer(5000); // 5-second countdown
|
|
113
174
|
timer.start();
|
|
114
175
|
|
|
115
|
-
|
|
116
|
-
|
|
176
|
+
// Await completion
|
|
177
|
+
await timer.completed;
|
|
178
|
+
console.log('Timer finished!');
|
|
179
|
+
|
|
180
|
+
// Or use pause/resume
|
|
181
|
+
const timer2 = new Timer(10000);
|
|
182
|
+
timer2.start();
|
|
183
|
+
|
|
184
|
+
// Pause after 3 seconds
|
|
185
|
+
setTimeout(() => timer2.pause(), 3000);
|
|
186
|
+
|
|
187
|
+
// Resume later
|
|
188
|
+
setTimeout(() => timer2.resume(), 6000);
|
|
189
|
+
|
|
190
|
+
await timer2.completed;
|
|
191
|
+
|
|
192
|
+
// Reset completely and start over
|
|
193
|
+
timer2.reset();
|
|
194
|
+
timer2.start();
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
Check remaining time with `timer.timeLeft`.
|
|
198
|
+
|
|
199
|
+
### 🔁 Interval — Repeating Jobs
|
|
200
|
+
|
|
201
|
+
Run functions at a fixed interval with start/stop control:
|
|
202
|
+
|
|
203
|
+
```typescript
|
|
204
|
+
import { Interval } from '@push.rocks/smarttime';
|
|
205
|
+
|
|
206
|
+
const interval = new Interval(2000); // Every 2 seconds
|
|
207
|
+
|
|
208
|
+
interval.addIntervalJob(() => {
|
|
209
|
+
console.log('Tick!', new Date().toISOString());
|
|
117
210
|
});
|
|
118
211
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
212
|
+
interval.addIntervalJob(() => {
|
|
213
|
+
console.log('Another parallel job');
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
interval.start();
|
|
217
|
+
|
|
218
|
+
// Stop later
|
|
219
|
+
setTimeout(() => interval.stop(), 10000);
|
|
122
220
|
```
|
|
123
221
|
|
|
124
|
-
|
|
222
|
+
### 🕰️ TimeStamp — Comparison & Tracking
|
|
223
|
+
|
|
224
|
+
The `TimeStamp` class captures a moment in time and provides comparison utilities:
|
|
225
|
+
|
|
226
|
+
```typescript
|
|
227
|
+
import { TimeStamp } from '@push.rocks/smarttime';
|
|
228
|
+
|
|
229
|
+
const stamp1 = new TimeStamp();
|
|
230
|
+
// ... some time passes ...
|
|
231
|
+
const stamp2 = new TimeStamp();
|
|
125
232
|
|
|
126
|
-
|
|
233
|
+
console.log(stamp1.milliSeconds); // Unix ms
|
|
234
|
+
console.log(stamp1.epochtime); // Unix seconds
|
|
127
235
|
|
|
128
|
-
|
|
236
|
+
// Comparison
|
|
237
|
+
console.log(stamp1.isOlderThan(stamp2)); // true
|
|
238
|
+
console.log(stamp2.isYoungerThanOtherTimeStamp(stamp1)); // true
|
|
239
|
+
|
|
240
|
+
// Derived timestamps track change
|
|
241
|
+
const derived = TimeStamp.fromTimeStamp(stamp1);
|
|
242
|
+
console.log(`${derived.change}ms have passed since stamp1`);
|
|
243
|
+
|
|
244
|
+
// From known milliseconds
|
|
245
|
+
const known = TimeStamp.fromMilliSeconds(1700000000000);
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
## API Overview
|
|
249
|
+
|
|
250
|
+
| Export | Description |
|
|
251
|
+
|---|---|
|
|
252
|
+
| `CronManager` | Register and run multiple cron jobs with automatic scheduling |
|
|
253
|
+
| `CronJob` | Individual cron job (created via `CronManager.addCronjob()`) |
|
|
254
|
+
| `ExtendedDate` | Enhanced `Date` with factory methods and formatting |
|
|
255
|
+
| `HrtMeasurement` | High-resolution time measurement |
|
|
256
|
+
| `Timer` | Promise-based countdown with pause/resume/reset |
|
|
257
|
+
| `Interval` | Repeating job execution at fixed intervals |
|
|
258
|
+
| `TimeStamp` | Point-in-time capture with comparison utilities |
|
|
259
|
+
| `units` | Time unit conversion functions (`days()`, `hours()`, etc.) |
|
|
260
|
+
| `getMilliSecondsFromUnits()` | Convert combined time units to milliseconds |
|
|
261
|
+
| `getMilliSecondsAsHumanReadableString()` | Format ms as human-readable string |
|
|
262
|
+
| `getMilliSecondsAsHumanReadableAgoTime()` | Format timestamp as relative "ago" string |
|
|
129
263
|
|
|
130
264
|
## License and Legal Information
|
|
131
265
|
|
|
132
|
-
This repository contains open-source code
|
|
266
|
+
This repository contains open-source code licensed under the MIT License. A copy of the license can be found in the [LICENSE](./LICENSE) file.
|
|
133
267
|
|
|
134
268
|
**Please note:** The MIT License does not grant permission to use the trade names, trademarks, service marks, or product names of the project, except as required for reasonable and customary use in describing the origin of the work and reproducing the content of the NOTICE file.
|
|
135
269
|
|
|
136
270
|
### Trademarks
|
|
137
271
|
|
|
138
|
-
This project is owned and maintained by Task Venture Capital GmbH. The names and logos associated with Task Venture Capital GmbH and any related products or services are trademarks of Task Venture Capital GmbH and are not included within the scope of the MIT license granted herein.
|
|
272
|
+
This project is owned and maintained by Task Venture Capital GmbH. The names and logos associated with Task Venture Capital GmbH and any related products or services are trademarks of Task Venture Capital GmbH or third parties, and are not included within the scope of the MIT license granted herein.
|
|
273
|
+
|
|
274
|
+
Use of these trademarks must comply with Task Venture Capital GmbH's Trademark Guidelines or the guidelines of the respective third-party owners, and any usage must be approved in writing. Third-party trademarks used herein are the property of their respective owners and used only in a descriptive manner, e.g. for an implementation of an API or similar.
|
|
139
275
|
|
|
140
276
|
### Company Information
|
|
141
277
|
|
|
142
|
-
Task Venture Capital GmbH
|
|
143
|
-
Registered at District
|
|
278
|
+
Task Venture Capital GmbH
|
|
279
|
+
Registered at District Court Bremen HRB 35230 HB, Germany
|
|
144
280
|
|
|
145
|
-
For any legal inquiries or
|
|
281
|
+
For any legal inquiries or further information, please contact us via email at hello@task.vc.
|
|
146
282
|
|
|
147
283
|
By using this repository, you acknowledge that you have read this section, agree to comply with its terms, and understand that the licensing of the code does not imply endorsement by Task Venture Capital GmbH of any derivative works.
|