@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.
@@ -3,7 +3,7 @@
3
3
  */
4
4
  export const commitinfo = {
5
5
  name: '@push.rocks/smarttime',
6
- version: '4.1.0',
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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic21hcnR0aW1lLmNsYXNzZXMuY3JvbmpvYi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3RzL3NtYXJ0dGltZS5jbGFzc2VzLmNyb25qb2IudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLE9BQU8sTUFBTSx3QkFBd0IsQ0FBQztBQUNsRCxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sb0NBQW9DLENBQUM7QUFFakUsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLG1DQUFtQyxDQUFDO0FBTS9ELE1BQU0sT0FBTyxPQUFPO0lBT2xCLFlBQVksV0FBd0IsRUFBRSxpQkFBeUIsRUFBRSxXQUF5QjtRQUxuRixXQUFNLEdBQXNDLFNBQVMsQ0FBQztRQUdyRCxzQkFBaUIsR0FBVyxDQUFDLENBQUM7UUFHcEMsSUFBSSxDQUFDLGNBQWMsR0FBRyxpQkFBaUIsQ0FBQztRQUN4QyxJQUFJLENBQUMsV0FBVyxHQUFHLFdBQVcsQ0FBQztRQUMvQixJQUFJLENBQUMsVUFBVSxHQUFHLElBQUksT0FBTyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsaUJBQWlCLENBQUMsQ0FBQztJQUMvRCxDQUFDO0lBRUQ7O09BRUc7SUFDSSxjQUFjO1FBQ25CLElBQUksSUFBSSxDQUFDLGlCQUFpQixLQUFLLENBQUMsRUFBRSxDQUFDO1lBQ2pDLElBQUksQ0FBQyxvQkFBb0IsRUFBRSxDQUFDO1FBQzlCLENBQUM7UUFDRCxJQUFJLElBQUksQ0FBQyxHQUFHLEVBQUUsR0FBRyxJQUFJLENBQUMsaUJBQWlCLEVBQUUsQ0FBQztZQUN4QyxNQUFNLFlBQVksR0FBRyxJQUFJLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDO1lBQzlELElBQUksWUFBWSxZQUFZLE9BQU8sRUFBRSxDQUFDO2dCQUNwQyxZQUFZLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFDNUMsQ0FBQztZQUNELElBQUksQ0FBQyxpQkFBaUIsR0FBRyxJQUFJLENBQUMsb0JBQW9CLEVBQUUsQ0FBQztRQUN2RCxDQUFDO1FBQ0QsT0FBTyxJQUFJLENBQUMsaUJBQWlCLENBQUM7SUFDaEMsQ0FBQztJQUVNLG9CQUFvQjtRQUN6QixPQUFPLENBQUMsSUFBSSxDQUFDLGlCQUFpQixHQUFHLElBQUksQ0FBQyxHQUFHLEVBQUUsR0FBRyxJQUFJLENBQUMsc0JBQXNCLEVBQUUsQ0FBQyxDQUFDO0lBQy9FLENBQUM7SUFFRDs7T0FFRztJQUNJLHNCQUFzQjtRQUMzQixPQUFPLElBQUksQ0FBQyxVQUFVLENBQUMsUUFBUSxFQUFFLENBQUM7SUFDcEMsQ0FBQztJQUVNLEtBQUs7UUFDVixJQUFJLENBQUMsTUFBTSxHQUFHLFNBQVMsQ0FBQztJQUMxQixDQUFDO0lBRU0sSUFBSTtRQUNULElBQUksQ0FBQyxNQUFNLEdBQUcsU0FBUyxDQUFDO0lBQzFCLENBQUM7Q0FDRiJ9
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.executionTimeout = new plugins.smartdelay.Timeout(0);
35
- do {
36
- let nextRunningCronjob;
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
- if (!nextRunningCronjob ||
40
- cronJob.getTimeToNextExecution() < nextRunningCronjob.getTimeToNextExecution()) {
41
- nextRunningCronjob = cronJob;
54
+ const msToNext = cronJob.getTimeToNextExecution();
55
+ if (msToNext < soonestMs) {
56
+ soonestMs = msToNext;
42
57
  }
43
58
  }
44
- if (nextRunningCronjob) {
45
- this.executionTimeout = new plugins.smartdelay.Timeout(nextRunningCronjob.getTimeToNextExecution());
46
- console.log(`Next CronJob scheduled in ${getMilliSecondsAsHumanReadableString(this.executionTimeout.getTimeLeft())}`);
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
- this.executionTimeout = new plugins.smartdelay.Timeout(1000);
50
- console.log('no cronjobs specified! Checking again in 1 second');
74
+ // No jobs — wait indefinitely until woken by addCronjob or stop
75
+ await this.cycleWakeDeferred.promise;
51
76
  }
52
- await this.executionTimeout.promise;
53
- } while (this.status === 'started');
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.cancel();
63
- }
64
- else {
65
- console.log(`You tried to stop a CronManager that was not actually started.`);
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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic21hcnR0aW1lLmNsYXNzZXMuY3Jvbm1hbmFnZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9zbWFydHRpbWUuY2xhc3Nlcy5jcm9ubWFuYWdlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLHdCQUF3QixDQUFDO0FBQ2xELE9BQU8sRUFBRSxPQUFPLEVBQXFCLE1BQU0sZ0NBQWdDLENBQUM7QUFDNUUsT0FBTyxFQUFFLG9DQUFvQyxFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFFNUUsTUFBTSxPQUFPLFdBQVc7SUFNdEI7UUFITyxXQUFNLEdBQTBCLFNBQVMsQ0FBQztRQUMxQyxhQUFRLEdBQUcsSUFBSSxPQUFPLENBQUMsR0FBRyxDQUFDLFNBQVMsRUFBVyxDQUFDO0lBRXhDLENBQUM7SUFFVCxVQUFVLENBQUMsaUJBQXlCLEVBQUUsZUFBNkI7UUFDeEUsTUFBTSxVQUFVLEdBQUcsSUFBSSxPQUFPLENBQUMsSUFBSSxFQUFFLGlCQUFpQixFQUFFLGVBQWUsQ0FBQyxDQUFDO1FBQ3pFLElBQUksQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLFVBQVUsQ0FBQyxDQUFDO1FBQzlCLElBQUksSUFBSSxDQUFDLE1BQU0sS0FBSyxTQUFTLEVBQUUsQ0FBQztZQUM5QixVQUFVLENBQUMsS0FBSyxFQUFFLENBQUM7UUFDckIsQ0FBQztRQUVELE9BQU8sVUFBVSxDQUFDO0lBQ3BCLENBQUM7SUFFTSxhQUFhLENBQUMsVUFBbUI7UUFDdEMsVUFBVSxDQUFDLElBQUksRUFBRSxDQUFDO1FBQ2xCLElBQUksQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLFVBQVUsQ0FBQyxDQUFDO0lBQ25DLENBQUM7SUFFRDs7T0FFRztJQUNJLEtBQUs7UUFDVixJQUFJLElBQUksQ0FBQyxNQUFNLEtBQUssU0FBUyxFQUFFLENBQUM7WUFDOUIsSUFBSSxDQUFDLE1BQU0sR0FBRyxTQUFTLENBQUM7WUFDeEIsS0FBSyxNQUFNLE9BQU8sSUFBSSxJQUFJLENBQUMsUUFBUSxDQUFDLFFBQVEsRUFBRSxFQUFFLENBQUM7Z0JBQy9DLE9BQU8sQ0FBQyxLQUFLLEVBQUUsQ0FBQztZQUNsQixDQUFDO1lBQ0QsSUFBSSxDQUFDLFlBQVksRUFBRSxDQUFDO1FBQ3RCLENBQUM7SUFDSCxDQUFDO0lBRU8sS0FBSyxDQUFDLFlBQVk7UUFDeEIsSUFBSSxDQUFDLGdCQUFnQixHQUFHLElBQUksT0FBTyxDQUFDLFVBQVUsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDMUQsR0FBRyxDQUFDO1lBQ0YsSUFBSSxrQkFBMkIsQ0FBQztZQUNoQyxLQUFLLE1BQU0sT0FBTyxJQUFJLElBQUksQ0FBQyxRQUFRLENBQUMsUUFBUSxFQUFFLEVBQUUsQ0FBQztnQkFDL0MsT0FBTyxDQUFDLGNBQWMsRUFBRSxDQUFDO2dCQUN6QixJQUNFLENBQUMsa0JBQWtCO29CQUNuQixPQUFPLENBQUMsc0JBQXNCLEVBQUUsR0FBRyxrQkFBa0IsQ0FBQyxzQkFBc0IsRUFBRSxFQUM5RSxDQUFDO29CQUNELGtCQUFrQixHQUFHLE9BQU8sQ0FBQztnQkFDL0IsQ0FBQztZQUNILENBQUM7WUFDRCxJQUFJLGtCQUFrQixFQUFFLENBQUM7Z0JBQ3ZCLElBQUksQ0FBQyxnQkFBZ0IsR0FBRyxJQUFJLE9BQU8sQ0FBQyxVQUFVLENBQUMsT0FBTyxDQUNwRCxrQkFBa0IsQ0FBQyxzQkFBc0IsRUFBRSxDQUM1QyxDQUFDO2dCQUNGLE9BQU8sQ0FBQyxHQUFHLENBQ1QsNkJBQTZCLG9DQUFvQyxDQUMvRCxJQUFJLENBQUMsZ0JBQWdCLENBQUMsV0FBVyxFQUFFLENBQ3BDLEVBQUUsQ0FDSixDQUFDO1lBQ0osQ0FBQztpQkFBTSxDQUFDO2dCQUNOLElBQUksQ0FBQyxnQkFBZ0IsR0FBRyxJQUFJLE9BQU8sQ0FBQyxVQUFVLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDO2dCQUM3RCxPQUFPLENBQUMsR0FBRyxDQUFDLG1EQUFtRCxDQUFDLENBQUM7WUFDbkUsQ0FBQztZQUVELE1BQU0sSUFBSSxDQUFDLGdCQUFnQixDQUFDLE9BQU8sQ0FBQztRQUN0QyxDQUFDLFFBQVEsSUFBSSxDQUFDLE1BQU0sS0FBSyxTQUFTLEVBQUU7SUFDdEMsQ0FBQztJQUFBLENBQUM7SUFFRjs7T0FFRztJQUNJLElBQUk7UUFDVCxJQUFJLElBQUksQ0FBQyxNQUFNLEtBQUssU0FBUyxFQUFFLENBQUM7WUFDOUIsSUFBSSxDQUFDLE1BQU0sR0FBRyxTQUFTLENBQUM7WUFDeEIsSUFBSSxDQUFDLGdCQUFnQixDQUFDLE1BQU0sRUFBRSxDQUFDO1FBQ2pDLENBQUM7YUFBTSxDQUFDO1lBQ04sT0FBTyxDQUFDLEdBQUcsQ0FBQyxnRUFBZ0UsQ0FBQyxDQUFDO1FBQ2hGLENBQUM7UUFDRCxLQUFLLE1BQU0sSUFBSSxJQUFJLElBQUksQ0FBQyxRQUFRLENBQUMsUUFBUSxFQUFFLEVBQUUsQ0FBQztZQUM1QyxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUM7UUFDZCxDQUFDO0lBQ0gsQ0FBQztDQUNGIn0=
96
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic21hcnR0aW1lLmNsYXNzZXMuY3Jvbm1hbmFnZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9zbWFydHRpbWUuY2xhc3Nlcy5jcm9ubWFuYWdlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLHdCQUF3QixDQUFDO0FBQ2xELE9BQU8sRUFBRSxPQUFPLEVBQXFCLE1BQU0sZ0NBQWdDLENBQUM7QUFFNUUsTUFBTSxPQUFPLFdBQVc7SUFRdEI7UUFMTyxXQUFNLEdBQTBCLFNBQVMsQ0FBQztRQUMxQyxhQUFRLEdBQUcsSUFBSSxPQUFPLENBQUMsR0FBRyxDQUFDLFNBQVMsRUFBVyxDQUFDO1FBRS9DLHNCQUFpQixHQUErQyxJQUFJLENBQUM7SUFFOUQsQ0FBQztJQUVoQjs7O09BR0c7SUFDSyxTQUFTO1FBQ2YsSUFBSSxJQUFJLENBQUMsaUJBQWlCLElBQUksSUFBSSxDQUFDLGlCQUFpQixDQUFDLE1BQU0sS0FBSyxTQUFTLEVBQUUsQ0FBQztZQUMxRSxJQUFJLENBQUMsaUJBQWlCLENBQUMsT0FBTyxFQUFFLENBQUM7UUFDbkMsQ0FBQztJQUNILENBQUM7SUFFTSxVQUFVLENBQUMsaUJBQXlCLEVBQUUsZUFBNkI7UUFDeEUsTUFBTSxVQUFVLEdBQUcsSUFBSSxPQUFPLENBQUMsSUFBSSxFQUFFLGlCQUFpQixFQUFFLGVBQWUsQ0FBQyxDQUFDO1FBQ3pFLElBQUksQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLFVBQVUsQ0FBQyxDQUFDO1FBQzlCLElBQUksSUFBSSxDQUFDLE1BQU0sS0FBSyxTQUFTLEVBQUUsQ0FBQztZQUM5QixVQUFVLENBQUMsS0FBSyxFQUFFLENBQUM7WUFDbkIsSUFBSSxDQUFDLFNBQVMsRUFBRSxDQUFDO1FBQ25CLENBQUM7UUFFRCxPQUFPLFVBQVUsQ0FBQztJQUNwQixDQUFDO0lBRU0sYUFBYSxDQUFDLFVBQW1CO1FBQ3RDLFVBQVUsQ0FBQyxJQUFJLEVBQUUsQ0FBQztRQUNsQixJQUFJLENBQUMsUUFBUSxDQUFDLE1BQU0sQ0FBQyxVQUFVLENBQUMsQ0FBQztRQUNqQyxJQUFJLElBQUksQ0FBQyxNQUFNLEtBQUssU0FBUyxFQUFFLENBQUM7WUFDOUIsSUFBSSxDQUFDLFNBQVMsRUFBRSxDQUFDO1FBQ25CLENBQUM7SUFDSCxDQUFDO0lBRUQ7O09BRUc7SUFDSSxLQUFLO1FBQ1YsSUFBSSxJQUFJLENBQUMsTUFBTSxLQUFLLFNBQVMsRUFBRSxDQUFDO1lBQzlCLElBQUksQ0FBQyxNQUFNLEdBQUcsU0FBUyxDQUFDO1lBQ3hCLEtBQUssTUFBTSxPQUFPLElBQUksSUFBSSxDQUFDLFFBQVEsQ0FBQyxRQUFRLEVBQUUsRUFBRSxDQUFDO2dCQUMvQyxPQUFPLENBQUMsS0FBSyxFQUFFLENBQUM7WUFDbEIsQ0FBQztZQUNELElBQUksQ0FBQyxZQUFZLEVBQUUsQ0FBQztRQUN0QixDQUFDO0lBQ0gsQ0FBQztJQUVPLEtBQUssQ0FBQyxZQUFZO1FBQ3hCLE9BQU8sSUFBSSxDQUFDLE1BQU0sS0FBSyxTQUFTLEVBQUUsQ0FBQztZQUNqQyxnREFBZ0Q7WUFDaEQsSUFBSSxDQUFDLGlCQUFpQixHQUFHLElBQUksT0FBTyxDQUFDLFlBQVksQ0FBQyxRQUFRLEVBQVEsQ0FBQztZQUVuRSx5REFBeUQ7WUFDekQsSUFBSSxTQUFTLEdBQUcsUUFBUSxDQUFDO1lBQ3pCLEtBQUssTUFBTSxPQUFPLElBQUksSUFBSSxDQUFDLFFBQVEsQ0FBQyxRQUFRLEVBQUUsRUFBRSxDQUFDO2dCQUMvQyxPQUFPLENBQUMsY0FBYyxFQUFFLENBQUM7Z0JBQ3pCLE1BQU0sUUFBUSxHQUFHLE9BQU8sQ0FBQyxzQkFBc0IsRUFBRSxDQUFDO2dCQUNsRCxJQUFJLFFBQVEsR0FBRyxTQUFTLEVBQUUsQ0FBQztvQkFDekIsU0FBUyxHQUFHLFFBQVEsQ0FBQztnQkFDdkIsQ0FBQztZQUNILENBQUM7WUFFRCxzRUFBc0U7WUFDdEUsSUFBSSxTQUFTLEdBQUcsUUFBUSxJQUFJLFNBQVMsR0FBRyxDQUFDLEVBQUUsQ0FBQztnQkFDMUMsSUFBSSxDQUFDLGdCQUFnQixHQUFHLElBQUksT0FBTyxDQUFDLFVBQVUsQ0FBQyxPQUFPLENBQUMsU0FBUyxDQUFDLENBQUM7Z0JBQ2xFLE1BQU0sT0FBTyxDQUFDLElBQUksQ0FBQztvQkFDakIsSUFBSSxDQUFDLGdCQUFnQixDQUFDLE9BQU87b0JBQzdCLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxPQUFPO2lCQUMvQixDQUFDLENBQUM7Z0JBQ0gsK0NBQStDO2dCQUMvQyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsTUFBTSxFQUFFLENBQUM7WUFDakMsQ0FBQztpQkFBTSxJQUFJLFNBQVMsSUFBSSxDQUFDLEVBQUUsQ0FBQztnQkFDMUIsaURBQWlEO2dCQUNqRCxTQUFTO1lBQ1gsQ0FBQztpQkFBTSxDQUFDO2dCQUNOLGdFQUFnRTtnQkFDaEUsTUFBTSxJQUFJLENBQUMsaUJBQWlCLENBQUMsT0FBTyxDQUFDO1lBQ3ZDLENBQUM7UUFDSCxDQUFDO1FBQ0QsSUFBSSxDQUFDLGlCQUFpQixHQUFHLElBQUksQ0FBQztJQUNoQyxDQUFDO0lBRUQ7O09BRUc7SUFDSSxJQUFJO1FBQ1QsSUFBSSxJQUFJLENBQUMsTUFBTSxLQUFLLFNBQVMsRUFBRSxDQUFDO1lBQzlCLElBQUksQ0FBQyxNQUFNLEdBQUcsU0FBUyxDQUFDO1lBQ3hCLElBQUksSUFBSSxDQUFDLGdCQUFnQixFQUFFLENBQUM7Z0JBQzFCLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxNQUFNLEVBQUUsQ0FBQztZQUNqQyxDQUFDO1lBQ0QsSUFBSSxDQUFDLFNBQVMsRUFBRSxDQUFDO1FBQ25CLENBQUM7UUFDRCxLQUFLLE1BQU0sSUFBSSxJQUFJLElBQUksQ0FBQyxRQUFRLENBQUMsUUFBUSxFQUFFLEVBQUUsQ0FBQztZQUM1QyxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUM7UUFDZCxDQUFDO0lBQ0gsQ0FBQztDQUNGIn0=
@@ -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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic21hcnR0aW1lLnVuaXRzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvc21hcnR0aW1lLnVuaXRzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxPQUFPLE1BQU0sd0JBQXdCLENBQUM7QUFFbEQsTUFBTSxDQUFDLElBQUksS0FBSyxHQUFHO0lBQ2pCLEtBQUssRUFBRSxDQUFDLFFBQVEsR0FBRyxDQUFDLEVBQVUsRUFBRTtRQUM5QixPQUFPLFFBQVEsR0FBRyxRQUFRLENBQUM7SUFDN0IsQ0FBQztJQUNELE1BQU0sRUFBRSxDQUFDLFFBQVEsR0FBRyxDQUFDLEVBQVUsRUFBRTtRQUMvQixPQUFPLFFBQVEsR0FBRyxPQUFPLENBQUM7SUFDNUIsQ0FBQztJQUNELEtBQUssRUFBRSxDQUFDLFFBQVEsR0FBRyxDQUFDLEVBQUUsRUFBRTtRQUN0QixPQUFPLFFBQVEsR0FBRyxPQUFPLENBQUM7SUFDNUIsQ0FBQztJQUNELElBQUksRUFBRSxDQUFDLFFBQVEsR0FBRyxDQUFDLEVBQUUsRUFBRTtRQUNyQixPQUFPLFFBQVEsR0FBRyxNQUFNLENBQUM7SUFDM0IsQ0FBQztJQUNELEtBQUssRUFBRSxDQUFDLFFBQVEsR0FBRyxDQUFDLEVBQUUsRUFBRTtRQUN0QixPQUFPLFFBQVEsR0FBRyxLQUFLLENBQUM7SUFDMUIsQ0FBQztJQUNELE9BQU8sRUFBRSxDQUFDLFFBQVEsR0FBRyxDQUFDLEVBQUUsRUFBRTtRQUN4QixPQUFPLFFBQVEsR0FBRyxLQUFLLENBQUM7SUFDMUIsQ0FBQztJQUNELE9BQU8sRUFBRSxDQUFDLFFBQVEsR0FBRyxDQUFDLEVBQUUsRUFBRTtRQUN4QixPQUFPLFFBQVEsR0FBRyxJQUFJLENBQUM7SUFDekIsQ0FBQztDQUNGLENBQUM7QUFZRixNQUFNLENBQUMsSUFBSSx3QkFBd0IsR0FBRyxDQUFDLGNBQW1DLEVBQUUsRUFBRTtJQUM1RSxJQUFJLGtCQUFrQixHQUFHLENBQUMsQ0FBQztJQUMzQixJQUFJLGVBQWUsR0FBRyxDQUFDLGVBQXVCLEVBQUUsRUFBRTtRQUNoRCxrQkFBa0IsR0FBRyxrQkFBa0IsR0FBRyxlQUFlLENBQUM7SUFDNUQsQ0FBQyxDQUFDO0lBQ0YsSUFBSSxjQUFjLENBQUMsS0FBSyxFQUFFLENBQUM7UUFDekIsZUFBZSxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsY0FBYyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUM7SUFDckQsQ0FBQztJQUNELElBQUksY0FBYyxDQUFDLE1BQU0sRUFBRSxDQUFDO1FBQzFCLGVBQWUsQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLGNBQWMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDO0lBQ3ZELENBQUM7SUFDRCxJQUFJLGNBQWMsQ0FBQyxLQUFLLEVBQUUsQ0FBQztRQUN6QixlQUFlLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxjQUFjLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQztJQUNyRCxDQUFDO0lBQ0QsSUFBSSxjQUFjLENBQUMsSUFBSSxFQUFFLENBQUM7UUFDeEIsZUFBZSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsY0FBYyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7SUFDbkQsQ0FBQztJQUNELElBQUksY0FBYyxDQUFDLEtBQUssRUFBRSxDQUFDO1FBQ3pCLGVBQWUsQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLGNBQWMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDO0lBQ3JELENBQUM7SUFDRCxJQUFJLGNBQWMsQ0FBQyxPQUFPLEVBQUUsQ0FBQztRQUMzQixlQUFlLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxjQUFjLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQztJQUN6RCxDQUFDO0lBQ0QsSUFBSSxjQUFjLENBQUMsT0FBTyxFQUFFLENBQUM7UUFDM0IsZUFBZSxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsY0FBYyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUM7SUFDekQsQ0FBQztJQUVELE9BQU8sa0JBQWtCLENBQUM7QUFDNUIsQ0FBQyxDQUFDO0FBRUYsTUFBTSxDQUFDLE1BQU0sb0NBQW9DLEdBQUcsQ0FBQyxlQUF1QixFQUFVLEVBQUU7SUFDdEYsT0FBTyxPQUFPLENBQUMsUUFBUSxDQUFDLGVBQWUsQ0FBQyxDQUFDO0FBQzNDLENBQUMsQ0FBQztBQUVGLE1BQU0sQ0FBQyxNQUFNLHFDQUFxQyxHQUFHLENBQUMsWUFBb0IsRUFBVSxFQUFFO0lBQ3BGLE9BQU8sT0FBTyxDQUFDLE9BQU8sQ0FBQyxtQkFBbUIsQ0FBQyxZQUFZLENBQUMsQ0FBQztBQUMzRCxDQUFDLENBQUEifQ==
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.0",
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": "^2.2.0",
12
- "@git.zone/tsbundle": "^2.1.0",
13
- "@git.zone/tsrun": "^1.3.3",
14
- "@git.zone/tstest": "^1.0.90",
15
- "@push.rocks/tapbundle": "^5.5.3",
16
- "@types/node": "^22.10.2"
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.1.0",
24
+ "@push.rocks/lik": "^6.2.2",
20
25
  "@push.rocks/smartdelay": "^3.0.5",
21
- "@push.rocks/smartpromise": "^4.0.4",
22
- "croner": "^9.0.0",
26
+ "@push.rocks/smartpromise": "^4.2.3",
27
+ "croner": "^10.0.1",
23
28
  "date-fns": "^4.1.0",
24
- "dayjs": "^1.11.13",
29
+ "dayjs": "^1.11.19",
25
30
  "is-nan": "^1.3.2",
26
- "pretty-ms": "^9.2.0"
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
- handle time in smart ways
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 --save
12
+ npm install @push.rocks/smarttime
9
13
  ```
10
14
 
11
- This will add `@push.rocks/smarttime` to your project's dependencies.
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` provides a comprehensive toolkit for handling various aspects of time manipulation, scheduling, and comparison in a TypeScript project. The following sections will guide you through the capabilities of this package, showcasing how to use its classes and functions effectively.
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
- ### Handling Time Units and Calculations
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
- // Define a duration using a combination of time units
24
- let durationInMilliseconds = getMilliSecondsFromUnits({
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 in milliseconds: ${durationInMilliseconds}`);
50
+ console.log(`Duration: ${duration}ms`);
35
51
  ```
36
52
 
37
- In the example above, we specify a complex duration made up of various time units using the `getMilliSecondsFromUnits` function. This is quite useful for calculations where you need to define durations in a more human-readable format.
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
- ### Scheduling with CronManager
71
+ ### 🔄 CronManager — Scheduled Task Execution
40
72
 
41
- `@push.rocks/smarttime` includes a powerful scheduling tool called `CronManager`, which allows you to schedule tasks using cron syntax.
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
- // Adding a cron job that runs every minute
50
- cronManager.addCronjob('* * * * *', async () => {
51
- console.log('This task runs every minute.');
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
- // Starting the CronManager
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 example demonstrates how to create a `CronManager`, add a cron job that runs every minute, and start the scheduling. You can add multiple cron jobs to a single manager, each with its own scheduling and task.
100
+ The `CronManager` automatically calculates the shortest sleep interval between jobs and efficiently schedules wake-ups no polling required.
59
101
 
60
- ### Working with Extended Date Class
102
+ ### 📅 ExtendedDate Enhanced Date Handling
61
103
 
62
- The `ExtendedDate` class extends the native JavaScript `Date` object, providing additional functionality for handling dates in various formats and zones.
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
- // Creating a date from a European format string
69
- const dateFromEuroString = ExtendedDate.fromEuropeanDate('31.12.2023');
70
- console.log(dateFromEuroString.toString());
109
+ // From European format: "DD.MM.YYYY"
110
+ const date1 = ExtendedDate.fromEuropeanDate('25.12.2024');
71
111
 
72
- // Creating a date from a hyphed date string
73
- const dateFromHyphedString = ExtendedDate.fromHyphedDate('2023-12-31');
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
- #### Checking if a Date is Today
78
- ```typescript
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
- const someDate = new ExtendedDate();
82
- console.log(`Is someDate today? ${someDate.isToday()}`);
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
- Using `ExtendedDate`, you can also easily check if a given date is today. This simplifies certain date comparisons that are common in web and application development.
144
+ ### ⏱️ HrtMeasurement High-Resolution Timing
86
145
 
87
- ### High-Resolution Time Measurement
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 hrtMeasurement = new HrtMeasurement();
94
- hrtMeasurement.start();
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
- This class allows you to measure the duration of operations in your code with high precision, offering both milliseconds and nanoseconds resolutions.
154
+ // ... perform some operation ...
103
155
 
104
- ### Interval and Timer functionalities
156
+ measurement.stop();
157
+ console.log(`Took ${measurement.milliSeconds}ms`);
158
+ console.log(`Took ${measurement.nanoSeconds}ns`);
105
159
 
106
- `@push.rocks/smarttime` includes classes for managing intervals and timers with enhanced control, such as pause, resume, and reset capabilities.
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); // A 5-second timer
173
+ const timer = new Timer(5000); // 5-second countdown
113
174
  timer.start();
114
175
 
115
- timer.completed.then(() => {
116
- console.log('Timer completed!');
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
- // Resetting the timer
120
- timer.reset();
121
- timer.start();
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
- The `Timer` class allows for asynchronous waiting in a more object-oriented manner. In the example, a `Timer` is created for five seconds, started, and then reset for demonstration purposes.
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
- ### Conclusion
233
+ console.log(stamp1.milliSeconds); // Unix ms
234
+ console.log(stamp1.epochtime); // Unix seconds
127
235
 
128
- `@push.rocks/smarttime` offers an extensive toolkit for dealing with time in JavaScript and TypeScript applications. Whether you need precise timing, scheduled tasks, or extended date functionalities, this package provides a suite of tools designed to handle time in smart and efficient ways. The examples provided herein demonstrate the core functionalities, aiming to help you integrate time-related features into your projects with ease.
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 that is licensed under the MIT License. A copy of the MIT License can be found in the [license](license) file within this repository.
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. 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.
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 court Bremen HRB 35230 HB, Germany
278
+ Task Venture Capital GmbH
279
+ Registered at District Court Bremen HRB 35230 HB, Germany
144
280
 
145
- For any legal inquiries or if you require further information, please contact us via email at hello@task.vc.
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.
@@ -3,6 +3,6 @@
3
3
  */
4
4
  export const commitinfo = {
5
5
  name: '@push.rocks/smarttime',
6
- version: '4.1.0',
6
+ version: '4.2.1',
7
7
  description: 'Provides utilities for advanced time handling including cron jobs, timestamps, intervals, and more.'
8
8
  }