@bgord/tools 1.1.0 → 1.1.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.
Files changed (48) hide show
  1. package/dist/age.vo.d.ts +4 -4
  2. package/dist/age.vo.js +4 -4
  3. package/dist/clock.vo.d.ts +2 -2
  4. package/dist/date-calculator.service.d.ts +5 -5
  5. package/dist/date-calculator.service.js +6 -9
  6. package/dist/date-range.vo.d.ts +6 -6
  7. package/dist/date-range.vo.js +1 -1
  8. package/dist/day.vo.d.ts +3 -3
  9. package/dist/day.vo.js +5 -5
  10. package/dist/hour.vo.d.ts +2 -2
  11. package/dist/hour.vo.js +1 -1
  12. package/dist/minute.vo.d.ts +2 -2
  13. package/dist/minute.vo.js +1 -1
  14. package/dist/month.vo.d.ts +3 -3
  15. package/dist/month.vo.js +7 -7
  16. package/dist/quarter.vo.d.ts +3 -3
  17. package/dist/quarter.vo.js +6 -6
  18. package/dist/rate-limiter.service.d.ts +3 -3
  19. package/dist/rate-limiter.service.js +1 -3
  20. package/dist/relative-date.vo.d.ts +3 -3
  21. package/dist/relative-date.vo.js +1 -1
  22. package/dist/stopwatch.service.d.ts +3 -3
  23. package/dist/stopwatch.service.js +2 -3
  24. package/dist/timestamp.vo.d.ts +13 -12
  25. package/dist/timestamp.vo.js +10 -6
  26. package/dist/week.vo.d.ts +3 -3
  27. package/dist/week.vo.js +8 -8
  28. package/dist/weekday.vo.d.ts +2 -2
  29. package/dist/weekday.vo.js +1 -1
  30. package/dist/year.vo.d.ts +3 -3
  31. package/dist/year.vo.js +8 -8
  32. package/package.json +1 -1
  33. package/src/age.vo.ts +6 -6
  34. package/src/clock.vo.ts +2 -2
  35. package/src/date-calculator.service.ts +7 -11
  36. package/src/date-range.vo.ts +8 -8
  37. package/src/day.vo.ts +7 -7
  38. package/src/hour.vo.ts +3 -3
  39. package/src/minute.vo.ts +3 -3
  40. package/src/month.vo.ts +9 -9
  41. package/src/quarter.vo.ts +8 -8
  42. package/src/rate-limiter.service.ts +5 -7
  43. package/src/relative-date.vo.ts +5 -5
  44. package/src/stopwatch.service.ts +4 -4
  45. package/src/timestamp.vo.ts +20 -16
  46. package/src/week.vo.ts +10 -10
  47. package/src/weekday.vo.ts +3 -3
  48. package/src/year.vo.ts +10 -10
package/dist/age.vo.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { Timestamp } from "./timestamp.vo";
1
+ import { TimestampVO } from "./timestamp.vo";
2
2
  export declare const AgeError: {
3
3
  readonly FutureBirthdate: "age.future.birthdate";
4
4
  };
@@ -9,12 +9,12 @@ export declare class Age {
9
9
  private constructor();
10
10
  static fromValue(candidate: number): Age;
11
11
  static fromBirthdateEpochMs(params: {
12
- birthdate: Timestamp;
13
- now: Timestamp;
12
+ birthdate: TimestampVO;
13
+ now: TimestampVO;
14
14
  }): Age;
15
15
  static fromBirthdate(candidate: {
16
16
  birthdate: string;
17
- now: Timestamp;
17
+ now: TimestampVO;
18
18
  }): Age;
19
19
  get(): number;
20
20
  equals(other: Age): boolean;
package/dist/age.vo.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { differenceInYears } from "date-fns";
2
2
  import { AgeYears, AgeYearsConstraints } from "./age-years.vo";
3
- import { Timestamp } from "./timestamp.vo";
3
+ import { TimestampVO } from "./timestamp.vo";
4
4
  export const AgeError = { FutureBirthdate: "age.future.birthdate" };
5
5
  export class Age {
6
6
  value;
@@ -15,13 +15,13 @@ export class Age {
15
15
  static fromBirthdateEpochMs(params) {
16
16
  if (params.birthdate.isAfter(params.now))
17
17
  throw new Error(AgeError.FutureBirthdate);
18
- return Age.fromValue(differenceInYears(params.now.get(), params.birthdate.get()));
18
+ return Age.fromValue(differenceInYears(params.now.ms, params.birthdate.ms));
19
19
  }
20
20
  static fromBirthdate(candidate) {
21
- const birthdate = Timestamp.fromNumber(new Date(candidate.birthdate).getTime());
21
+ const birthdate = TimestampVO.fromNumber(new Date(candidate.birthdate).getTime());
22
22
  if (birthdate.isAfter(candidate.now))
23
23
  throw new Error(AgeError.FutureBirthdate);
24
- return Age.fromValue(differenceInYears(candidate.now.get(), birthdate.get()));
24
+ return Age.fromValue(differenceInYears(candidate.now.ms, birthdate.ms));
25
25
  }
26
26
  get() {
27
27
  return this.value;
@@ -3,13 +3,13 @@ import { Hour } from "./hour.vo";
3
3
  import type { HourSchemaType } from "./hour-schema.vo";
4
4
  import { Minute } from "./minute.vo";
5
5
  import type { MinuteSchemaType } from "./minute-schema.vo";
6
- import type { Timestamp } from "./timestamp.vo";
6
+ import type { TimestampVO } from "./timestamp.vo";
7
7
  export declare class Clock {
8
8
  private readonly hour;
9
9
  private readonly minute;
10
10
  private readonly formatter;
11
11
  constructor(hour: Hour, minute: Minute, formatter?: ClockFormatter);
12
- static fromEpochMs(timestamp: Timestamp, formatter?: ClockFormatter): Clock;
12
+ static fromEpochMs(timestamp: TimestampVO, formatter?: ClockFormatter): Clock;
13
13
  get(): {
14
14
  hour: HourSchemaType;
15
15
  minute: MinuteSchemaType;
@@ -1,10 +1,10 @@
1
- import type { TimeZoneOffsetValueType } from "./time-zone-offset-value.vo";
2
- import { Timestamp } from "./timestamp.vo";
1
+ import { Duration } from "./duration.service";
2
+ import { TimestampVO } from "./timestamp.vo";
3
3
  type GetStartOfDayTsInTzConfigType = {
4
- now: Timestamp;
5
- timeZoneOffsetMs: TimeZoneOffsetValueType;
4
+ now: TimestampVO;
5
+ timeZoneOffset: Duration;
6
6
  };
7
7
  export declare class DateCalculator {
8
- static getStartOfDayTsInTz(config: GetStartOfDayTsInTzConfigType): Timestamp;
8
+ static getStartOfDayTsInTz(config: GetStartOfDayTsInTzConfigType): TimestampVO;
9
9
  }
10
10
  export {};
@@ -1,15 +1,12 @@
1
1
  import { Duration } from "./duration.service";
2
- import { Timestamp } from "./timestamp.vo";
2
+ import { TimestampVO } from "./timestamp.vo";
3
3
  export class DateCalculator {
4
4
  static getStartOfDayTsInTz(config) {
5
5
  const dayMs = Duration.Days(1).ms;
6
- // UTC midnight for the UTC date of `now`
7
- const utcMidnight = Math.floor(config.now.get() / dayMs) * dayMs;
8
- // Candidate start of the local day (in UTC), anchored to the same UTC date
9
- let start = utcMidnight + config.timeZoneOffsetMs;
10
- // If the candidate is in the future relative to `now`, it means local midnight was "yesterday" in UTC.
11
- if (start > config.now.get())
12
- start -= dayMs;
13
- return Timestamp.fromNumber(start);
6
+ const utcMidnightOfNow = TimestampVO.fromNumber(Math.floor(config.now.ms / dayMs) * dayMs);
7
+ let startOfDayInTz = utcMidnightOfNow.add(config.timeZoneOffset);
8
+ if (startOfDayInTz.isAfter(config.now))
9
+ startOfDayInTz = startOfDayInTz.subtract(Duration.Days(1));
10
+ return startOfDayInTz;
14
11
  }
15
12
  }
@@ -1,15 +1,15 @@
1
- import type { Timestamp } from "./timestamp.vo";
1
+ import type { TimestampVO } from "./timestamp.vo";
2
2
  export declare const DateRangeError: {
3
3
  readonly Invalid: "date.range.invalid";
4
4
  };
5
5
  export declare class DateRange {
6
6
  private readonly start;
7
7
  private readonly end;
8
- constructor(start: Timestamp, end: Timestamp);
9
- getStart(): Timestamp;
10
- getEnd(): Timestamp;
11
- toRange(): [Timestamp, Timestamp];
12
- contains(timestamp: Timestamp): boolean;
8
+ constructor(start: TimestampVO, end: TimestampVO);
9
+ getStart(): TimestampVO;
10
+ getEnd(): TimestampVO;
11
+ toRange(): [TimestampVO, TimestampVO];
12
+ contains(timestamp: TimestampVO): boolean;
13
13
  equals(other: DateRange): boolean;
14
14
  toJSON(): {
15
15
  start: number;
@@ -24,6 +24,6 @@ export class DateRange {
24
24
  return this.start.equals(other.start) && this.end.equals(other.end);
25
25
  }
26
26
  toJSON() {
27
- return { start: this.getStart().get(), end: this.getEnd().get() };
27
+ return { start: this.getStart().ms, end: this.getEnd().ms };
28
28
  }
29
29
  }
package/dist/day.vo.d.ts CHANGED
@@ -1,9 +1,9 @@
1
1
  import { DateRange } from "./date-range.vo";
2
2
  import { type DayIsoIdType } from "./day-iso-id.vo";
3
- import { Timestamp } from "./timestamp.vo";
3
+ import { TimestampVO } from "./timestamp.vo";
4
4
  export declare class Day extends DateRange {
5
- static fromTimestamp(timestamp: Timestamp): Day;
6
- static fromNow(now: Timestamp): Day;
5
+ static fromTimestamp(timestamp: TimestampVO): Day;
6
+ static fromNow(now: TimestampVO): Day;
7
7
  static fromIsoId(isoId: DayIsoIdType): Day;
8
8
  toIsoId(): DayIsoIdType;
9
9
  previous(): Day;
package/dist/day.vo.js CHANGED
@@ -2,11 +2,11 @@ import { formatISO } from "date-fns";
2
2
  import { DateRange } from "./date-range.vo";
3
3
  import { DayIsoId } from "./day-iso-id.vo";
4
4
  import { Duration } from "./duration.service";
5
- import { Timestamp } from "./timestamp.vo";
5
+ import { TimestampVO } from "./timestamp.vo";
6
6
  export class Day extends DateRange {
7
7
  static fromTimestamp(timestamp) {
8
- const date = new Date(timestamp.get());
9
- const startUtc = Timestamp.fromNumber(Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate()));
8
+ const date = new Date(timestamp.ms);
9
+ const startUtc = TimestampVO.fromNumber(Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate()));
10
10
  const endUtc = startUtc.add(Duration.Days(1)).subtract(Duration.Ms(1));
11
11
  return new Day(startUtc, endUtc);
12
12
  }
@@ -15,13 +15,13 @@ export class Day extends DateRange {
15
15
  }
16
16
  static fromIsoId(isoId) {
17
17
  const [year, month, day] = DayIsoId.parse(isoId).split("-").map(Number);
18
- const startUtc = Timestamp.fromNumber(Date.UTC(year, month - 1, day));
18
+ const startUtc = TimestampVO.fromNumber(Date.UTC(year, month - 1, day));
19
19
  const endUtc = startUtc.add(Duration.Days(1)).subtract(Duration.Ms(1));
20
20
  return new Day(startUtc, endUtc);
21
21
  }
22
22
  toIsoId() {
23
23
  const midday = this.getStart().add(Duration.Hours(12));
24
- return DayIsoId.parse(formatISO(midday.get(), { representation: "date" }));
24
+ return DayIsoId.parse(formatISO(midday.ms, { representation: "date" }));
25
25
  }
26
26
  previous() {
27
27
  return this.shift(-1);
package/dist/hour.vo.d.ts CHANGED
@@ -1,12 +1,12 @@
1
1
  import { type HourFormatter } from "./hour-format.service";
2
2
  import { type HourSchemaType } from "./hour-schema.vo";
3
- import type { Timestamp } from "./timestamp.vo";
3
+ import type { TimestampVO } from "./timestamp.vo";
4
4
  export declare class Hour {
5
5
  private readonly value;
6
6
  static readonly ZERO: Hour;
7
7
  static readonly MAX: Hour;
8
8
  constructor(candidate: number);
9
- static fromEpochMs(timestamp: Timestamp): Hour;
9
+ static fromEpochMs(timestamp: TimestampVO): Hour;
10
10
  get(): HourSchemaType;
11
11
  format(formatter: HourFormatter): string;
12
12
  equals(another: Hour): boolean;
package/dist/hour.vo.js CHANGED
@@ -8,7 +8,7 @@ export class Hour {
8
8
  this.value = HourSchema.parse(candidate);
9
9
  }
10
10
  static fromEpochMs(timestamp) {
11
- return new Hour(new Date(timestamp.get()).getUTCHours());
11
+ return new Hour(new Date(timestamp.ms).getUTCHours());
12
12
  }
13
13
  get() {
14
14
  return this.value;
@@ -1,11 +1,11 @@
1
1
  import { type MinuteSchemaType } from "./minute-schema.vo";
2
- import type { Timestamp } from "./timestamp.vo";
2
+ import type { TimestampVO } from "./timestamp.vo";
3
3
  export declare class Minute {
4
4
  private readonly value;
5
5
  static readonly ZERO: Minute;
6
6
  static readonly MAX: Minute;
7
7
  constructor(candidate: number);
8
- static fromEpochMs(timestamp: Timestamp): Minute;
8
+ static fromEpochMs(timestamp: TimestampVO): Minute;
9
9
  get(): MinuteSchemaType;
10
10
  equals(another: Minute): boolean;
11
11
  isAfter(another: Minute): boolean;
package/dist/minute.vo.js CHANGED
@@ -7,7 +7,7 @@ export class Minute {
7
7
  this.value = MinuteSchema.parse(candidate);
8
8
  }
9
9
  static fromEpochMs(timestamp) {
10
- return new Minute(new Date(timestamp.get()).getUTCMinutes());
10
+ return new Minute(new Date(timestamp.ms).getUTCMinutes());
11
11
  }
12
12
  get() {
13
13
  return this.value;
@@ -1,9 +1,9 @@
1
1
  import { DateRange } from "./date-range.vo";
2
2
  import { type MonthIsoIdType } from "./month-iso-id.vo";
3
- import { Timestamp } from "./timestamp.vo";
3
+ import { TimestampVO } from "./timestamp.vo";
4
4
  export declare class Month extends DateRange {
5
- static fromTimestamp(timestamp: Timestamp): Month;
6
- static fromNow(now: Timestamp): Month;
5
+ static fromTimestamp(timestamp: TimestampVO): Month;
6
+ static fromNow(now: TimestampVO): Month;
7
7
  static fromIsoId(iso: MonthIsoIdType): Month;
8
8
  toIsoId(): MonthIsoIdType;
9
9
  previous(): Month;
package/dist/month.vo.js CHANGED
@@ -1,11 +1,11 @@
1
1
  import { endOfMonth, format, getMonth, setMonth, startOfMonth } from "date-fns";
2
2
  import { DateRange } from "./date-range.vo";
3
3
  import { MonthIsoId } from "./month-iso-id.vo";
4
- import { Timestamp } from "./timestamp.vo";
4
+ import { TimestampVO } from "./timestamp.vo";
5
5
  export class Month extends DateRange {
6
6
  static fromTimestamp(timestamp) {
7
- const start = Timestamp.fromNumber(startOfMonth(timestamp.get()).getTime());
8
- const end = Timestamp.fromNumber(endOfMonth(timestamp.get()).getTime());
7
+ const start = TimestampVO.fromNumber(startOfMonth(timestamp.ms).getTime());
8
+ const end = TimestampVO.fromNumber(endOfMonth(timestamp.ms).getTime());
9
9
  return new Month(start, end);
10
10
  }
11
11
  static fromNow(now) {
@@ -14,10 +14,10 @@ export class Month extends DateRange {
14
14
  static fromIsoId(iso) {
15
15
  const [year, month] = MonthIsoId.parse(iso).split("-").map(Number);
16
16
  const reference = setMonth(Date.UTC(year), month - 1).getTime();
17
- return Month.fromTimestamp(Timestamp.fromNumber(reference));
17
+ return Month.fromTimestamp(TimestampVO.fromNumber(reference));
18
18
  }
19
19
  toIsoId() {
20
- return MonthIsoId.parse(format(this.getStart().get(), "yyyy-MM"));
20
+ return MonthIsoId.parse(format(this.getStart().ms, "yyyy-MM"));
21
21
  }
22
22
  previous() {
23
23
  return this.shift(-1);
@@ -26,8 +26,8 @@ export class Month extends DateRange {
26
26
  return this.shift(1);
27
27
  }
28
28
  shift(count) {
29
- const shifted = setMonth(this.getStart().get(), getMonth(this.getStart().get()) + count).getTime();
30
- return Month.fromTimestamp(Timestamp.fromNumber(shifted));
29
+ const shifted = setMonth(this.getStart().ms, getMonth(this.getStart().ms) + count).getTime();
30
+ return Month.fromTimestamp(TimestampVO.fromNumber(shifted));
31
31
  }
32
32
  toString() {
33
33
  return this.toIsoId();
@@ -1,9 +1,9 @@
1
1
  import { DateRange } from "./date-range.vo";
2
2
  import { type QuarterIsoIdType } from "./quarter-iso-id.vo";
3
- import { Timestamp } from "./timestamp.vo";
3
+ import { TimestampVO } from "./timestamp.vo";
4
4
  export declare class Quarter extends DateRange {
5
- static fromTimestamp(timestamp: Timestamp): Quarter;
6
- static fromNow(now: Timestamp): Quarter;
5
+ static fromTimestamp(timestamp: TimestampVO): Quarter;
6
+ static fromNow(now: TimestampVO): Quarter;
7
7
  static fromIsoId(isoId: QuarterIsoIdType): Quarter;
8
8
  toIsoId(): QuarterIsoIdType;
9
9
  toString(): string;
@@ -1,11 +1,11 @@
1
1
  import { endOfQuarter, getQuarter, getYear, setQuarter, startOfQuarter } from "date-fns";
2
2
  import { DateRange } from "./date-range.vo";
3
3
  import { QuarterIsoId } from "./quarter-iso-id.vo";
4
- import { Timestamp } from "./timestamp.vo";
4
+ import { TimestampVO } from "./timestamp.vo";
5
5
  export class Quarter extends DateRange {
6
6
  static fromTimestamp(timestamp) {
7
- const start = Timestamp.fromNumber(startOfQuarter(timestamp.get()).getTime());
8
- const end = Timestamp.fromNumber(endOfQuarter(timestamp.get()).getTime());
7
+ const start = TimestampVO.fromNumber(startOfQuarter(timestamp.ms).getTime());
8
+ const end = TimestampVO.fromNumber(endOfQuarter(timestamp.ms).getTime());
9
9
  return new Quarter(start, end);
10
10
  }
11
11
  static fromNow(now) {
@@ -14,11 +14,11 @@ export class Quarter extends DateRange {
14
14
  static fromIsoId(isoId) {
15
15
  const [year, quarter] = QuarterIsoId.parse(isoId).split("-Q").map(Number);
16
16
  const reference = setQuarter(Date.UTC(year), quarter).getTime();
17
- return Quarter.fromTimestamp(Timestamp.fromNumber(reference));
17
+ return Quarter.fromTimestamp(TimestampVO.fromNumber(reference));
18
18
  }
19
19
  toIsoId() {
20
- const year = getYear(this.getStart().get());
21
- const quarter = getQuarter(this.getStart().get());
20
+ const year = getYear(this.getStart().ms);
21
+ const quarter = getQuarter(this.getStart().ms);
22
22
  return QuarterIsoId.parse(`${year}-Q${quarter}`);
23
23
  }
24
24
  toString() {
@@ -1,5 +1,5 @@
1
- import { Duration } from "./duration.service";
2
- import type { Timestamp } from "./timestamp.vo";
1
+ import type { Duration } from "./duration.service";
2
+ import type { TimestampVO } from "./timestamp.vo";
3
3
  type RateLimiterResultSuccessType = {
4
4
  allowed: true;
5
5
  };
@@ -12,6 +12,6 @@ export declare class RateLimiter {
12
12
  private readonly duration;
13
13
  private lastInvocation;
14
14
  constructor(duration: Duration);
15
- verify(now: Timestamp): RateLimiterResultType;
15
+ verify(now: TimestampVO): RateLimiterResultType;
16
16
  }
17
17
  export {};
@@ -1,4 +1,3 @@
1
- import { Duration } from "./duration.service";
2
1
  export class RateLimiter {
3
2
  duration;
4
3
  lastInvocation = null;
@@ -15,7 +14,6 @@ export class RateLimiter {
15
14
  this.lastInvocation = now;
16
15
  return { allowed: true };
17
16
  }
18
- const remainingDelta = nextAllowedTimestamp.get() - now.get();
19
- return { allowed: false, remaining: Duration.Ms(remainingDelta) };
17
+ return { allowed: false, remaining: nextAllowedTimestamp.difference(now) };
20
18
  }
21
19
  }
@@ -1,4 +1,4 @@
1
- import type { Timestamp } from "./timestamp.vo";
1
+ import type { TimestampVO } from "./timestamp.vo";
2
2
  import type { TimestampValueType } from "./timestamp-value.vo";
3
3
  import type { Falsy } from "./ts-utils";
4
4
  type RelativeDateType = {
@@ -6,8 +6,8 @@ type RelativeDateType = {
6
6
  relative: string;
7
7
  };
8
8
  export declare class RelativeDate {
9
- static truthy(timestamp: Timestamp): RelativeDateType;
10
- static falsy(timestamp: Falsy<Timestamp>): RelativeDateType | null;
9
+ static truthy(timestamp: TimestampVO): RelativeDateType;
10
+ static falsy(timestamp: Falsy<TimestampVO>): RelativeDateType | null;
11
11
  private static _format;
12
12
  }
13
13
  export {};
@@ -9,6 +9,6 @@ export class RelativeDate {
9
9
  return RelativeDate._format(timestamp);
10
10
  }
11
11
  static _format(timestamp) {
12
- return { raw: timestamp.get(), relative: DateFormatters.relative(timestamp.get()) };
12
+ return { raw: timestamp.ms, relative: DateFormatters.relative(timestamp.ms) };
13
13
  }
14
14
  }
@@ -1,5 +1,5 @@
1
- import { Duration } from "./duration.service";
2
- import { Timestamp } from "./timestamp.vo";
1
+ import type { Duration } from "./duration.service";
2
+ import { TimestampVO } from "./timestamp.vo";
3
3
  export declare const StopwatchError: {
4
4
  readonly AlreadyStopped: "stopwatch.already.stopped";
5
5
  };
@@ -7,6 +7,6 @@ export type StopwatchResultType = Duration;
7
7
  export declare class Stopwatch {
8
8
  private readonly start;
9
9
  private state;
10
- constructor(start: Timestamp);
10
+ constructor(start: TimestampVO);
11
11
  stop(): StopwatchResultType;
12
12
  }
@@ -1,5 +1,4 @@
1
- import { Duration } from "./duration.service";
2
- import { Timestamp } from "./timestamp.vo";
1
+ import { TimestampVO } from "./timestamp.vo";
3
2
  export const StopwatchError = { AlreadyStopped: "stopwatch.already.stopped" };
4
3
  var StopwatchState;
5
4
  (function (StopwatchState) {
@@ -16,6 +15,6 @@ export class Stopwatch {
16
15
  if (this.state === StopwatchState.stopped)
17
16
  throw new Error(StopwatchError.AlreadyStopped);
18
17
  this.state = StopwatchState.stopped;
19
- return Duration.Ms(Timestamp.fromNumber(Date.now() - this.start.get()).get());
18
+ return TimestampVO.fromNumber(Date.now()).difference(this.start);
20
19
  }
21
20
  }
@@ -1,18 +1,19 @@
1
- import type { Duration } from "./duration.service";
1
+ import { Duration } from "./duration.service";
2
2
  import { type TimestampValueType } from "./timestamp-value.vo";
3
- export declare class Timestamp {
3
+ export declare class TimestampVO {
4
4
  private readonly value;
5
5
  constructor(value: TimestampValueType);
6
- static fromValue(value: TimestampValueType): Timestamp;
7
- static fromNumber(value: number): Timestamp;
8
- add(duration: Duration): Timestamp;
9
- subtract(duration: Duration): Timestamp;
10
- isBefore(another: Timestamp): boolean;
11
- isBeforeOrEqual(another: Timestamp): boolean;
12
- isAfter(another: Timestamp): boolean;
13
- isAfterOrEqual(another: Timestamp): boolean;
14
- equals(another: Timestamp): boolean;
15
- get(): TimestampValueType;
6
+ static fromValue(value: TimestampValueType): TimestampVO;
7
+ static fromNumber(value: number): TimestampVO;
8
+ add(duration: Duration): TimestampVO;
9
+ subtract(duration: Duration): TimestampVO;
10
+ difference(another: TimestampVO): Duration;
11
+ isBefore(another: TimestampVO): boolean;
12
+ isBeforeOrEqual(another: TimestampVO): boolean;
13
+ isAfter(another: TimestampVO): boolean;
14
+ isAfterOrEqual(another: TimestampVO): boolean;
15
+ equals(another: TimestampVO): boolean;
16
+ get ms(): TimestampValueType;
16
17
  toJSON(): TimestampValueType;
17
18
  toString(): string;
18
19
  }
@@ -1,20 +1,24 @@
1
+ import { Duration } from "./duration.service";
1
2
  import { TimestampValue } from "./timestamp-value.vo";
2
- export class Timestamp {
3
+ export class TimestampVO {
3
4
  value;
4
5
  constructor(value) {
5
6
  this.value = value;
6
7
  }
7
8
  static fromValue(value) {
8
- return new Timestamp(value);
9
+ return new TimestampVO(value);
9
10
  }
10
11
  static fromNumber(value) {
11
- return new Timestamp(TimestampValue.parse(value));
12
+ return new TimestampVO(TimestampValue.parse(value));
12
13
  }
13
14
  add(duration) {
14
- return Timestamp.fromNumber(this.value + duration.ms);
15
+ return TimestampVO.fromNumber(this.value + duration.ms);
15
16
  }
16
17
  subtract(duration) {
17
- return Timestamp.fromNumber(this.value - duration.ms);
18
+ return TimestampVO.fromNumber(this.value - duration.ms);
19
+ }
20
+ difference(another) {
21
+ return Duration.Ms(this.value - another.value);
18
22
  }
19
23
  isBefore(another) {
20
24
  return this.value < another.value;
@@ -31,7 +35,7 @@ export class Timestamp {
31
35
  equals(another) {
32
36
  return this.value === another.value;
33
37
  }
34
- get() {
38
+ get ms() {
35
39
  return this.value;
36
40
  }
37
41
  toJSON() {
package/dist/week.vo.d.ts CHANGED
@@ -1,9 +1,9 @@
1
1
  import { DateRange } from "./date-range.vo";
2
- import { Timestamp } from "./timestamp.vo";
2
+ import { TimestampVO } from "./timestamp.vo";
3
3
  import { type WeekIsoIdType } from "./week-iso-id.vo";
4
4
  export declare class Week extends DateRange {
5
- static fromTimestamp(timestamp: Timestamp): Week;
6
- static fromNow(now: Timestamp): Week;
5
+ static fromTimestamp(timestamp: TimestampVO): Week;
6
+ static fromNow(now: TimestampVO): Week;
7
7
  static fromIsoId(isoId: WeekIsoIdType): Week;
8
8
  toIsoId(): WeekIsoIdType;
9
9
  previous(): Week;
package/dist/week.vo.js CHANGED
@@ -1,11 +1,11 @@
1
1
  import { addWeeks, endOfISOWeek, getISOWeek, getISOWeekYear, setISOWeek, startOfISOWeek } from "date-fns";
2
2
  import { DateRange } from "./date-range.vo";
3
- import { Timestamp } from "./timestamp.vo";
3
+ import { TimestampVO } from "./timestamp.vo";
4
4
  import { WeekIsoId } from "./week-iso-id.vo";
5
5
  export class Week extends DateRange {
6
6
  static fromTimestamp(timestamp) {
7
- const start = Timestamp.fromNumber(startOfISOWeek(timestamp.get()).getTime());
8
- const end = Timestamp.fromNumber(endOfISOWeek(timestamp.get()).getTime());
7
+ const start = TimestampVO.fromNumber(startOfISOWeek(timestamp.ms).getTime());
8
+ const end = TimestampVO.fromNumber(endOfISOWeek(timestamp.ms).getTime());
9
9
  return new Week(start, end);
10
10
  }
11
11
  static fromNow(now) {
@@ -15,11 +15,11 @@ export class Week extends DateRange {
15
15
  const [year, week] = WeekIsoId.parse(isoId).split("-W").map(Number);
16
16
  // ISO-8601 rule: Jan 4 is always in week 01 of the ISO week-year.
17
17
  const reference = setISOWeek(Date.UTC(year, 0, 4), week).getTime();
18
- return Week.fromTimestamp(Timestamp.fromNumber(reference));
18
+ return Week.fromTimestamp(TimestampVO.fromNumber(reference));
19
19
  }
20
20
  toIsoId() {
21
- const year = getISOWeekYear(this.getStart().get());
22
- const week = getISOWeek(this.getStart().get());
21
+ const year = getISOWeekYear(this.getStart().ms);
22
+ const week = getISOWeek(this.getStart().ms);
23
23
  return WeekIsoId.parse(`${year}-W${String(week).padStart(2, "0")}`);
24
24
  }
25
25
  previous() {
@@ -29,8 +29,8 @@ export class Week extends DateRange {
29
29
  return this.shift(1);
30
30
  }
31
31
  shift(count) {
32
- const shifted = addWeeks(this.getStart().get(), count).getTime();
33
- return Week.fromTimestamp(Timestamp.fromNumber(shifted));
32
+ const shifted = addWeeks(this.getStart().ms, count).getTime();
33
+ return Week.fromTimestamp(TimestampVO.fromNumber(shifted));
34
34
  }
35
35
  toString() {
36
36
  return this.toIsoId();
@@ -1,4 +1,4 @@
1
- import type { Timestamp } from "./timestamp.vo";
1
+ import type { TimestampVO } from "./timestamp.vo";
2
2
  export type WeekdayFormatter = (value: Weekday["value"]) => string;
3
3
  export declare enum WeekdayFormatterEnum {
4
4
  FULL = "FULL",// "Sunday"
@@ -19,7 +19,7 @@ export declare class Weekday {
19
19
  static readonly FRIDAY: Weekday;
20
20
  static readonly SATURDAY: Weekday;
21
21
  constructor(candidate: number, formatter?: WeekdayFormatter);
22
- static fromUtcTimestamp(timestamp: Timestamp, formatter?: WeekdayFormatter): Weekday;
22
+ static fromUtcTimestamp(timestamp: TimestampVO, formatter?: WeekdayFormatter): Weekday;
23
23
  get(): number;
24
24
  format(): string;
25
25
  toString(): string;
@@ -41,7 +41,7 @@ export class Weekday {
41
41
  this.formatter = formatter ?? WeekdayFormatters.FULL;
42
42
  }
43
43
  static fromUtcTimestamp(timestamp, formatter) {
44
- const dayZeroBased = new Date(timestamp.get()).getUTCDay(); // 0..6
44
+ const dayZeroBased = new Date(timestamp.ms).getUTCDay(); // 0..6
45
45
  return new Weekday(dayZeroBased, formatter);
46
46
  }
47
47
  get() {
package/dist/year.vo.d.ts CHANGED
@@ -1,9 +1,9 @@
1
1
  import { DateRange } from "./date-range.vo";
2
- import { Timestamp } from "./timestamp.vo";
2
+ import { TimestampVO } from "./timestamp.vo";
3
3
  import { type YearIsoIdType } from "./year-iso-id.vo";
4
4
  export declare class Year extends DateRange {
5
- static fromTimestamp(timestamp: Timestamp): Year;
6
- static fromNow(now: Timestamp): Year;
5
+ static fromTimestamp(timestamp: TimestampVO): Year;
6
+ static fromNow(now: TimestampVO): Year;
7
7
  static fromNumber(candidate: number): Year;
8
8
  static fromIsoId(isoId: YearIsoIdType): Year;
9
9
  toIsoId(): YearIsoIdType;
package/dist/year.vo.js CHANGED
@@ -1,11 +1,11 @@
1
1
  import { addYears, endOfYear, getYear, startOfYear } from "date-fns";
2
2
  import { DateRange } from "./date-range.vo";
3
- import { Timestamp } from "./timestamp.vo";
3
+ import { TimestampVO } from "./timestamp.vo";
4
4
  import { YearIsoId } from "./year-iso-id.vo";
5
5
  export class Year extends DateRange {
6
6
  static fromTimestamp(timestamp) {
7
- const start = Timestamp.fromNumber(startOfYear(timestamp.get()).getTime());
8
- const end = Timestamp.fromNumber(endOfYear(timestamp.get()).getTime());
7
+ const start = TimestampVO.fromNumber(startOfYear(timestamp.ms).getTime());
8
+ const end = TimestampVO.fromNumber(endOfYear(timestamp.ms).getTime());
9
9
  return new Year(start, end);
10
10
  }
11
11
  static fromNow(now) {
@@ -16,13 +16,13 @@ export class Year extends DateRange {
16
16
  }
17
17
  static fromIsoId(isoId) {
18
18
  const reference = Date.UTC(Number(isoId));
19
- return Year.fromTimestamp(Timestamp.fromNumber(reference));
19
+ return Year.fromTimestamp(TimestampVO.fromNumber(reference));
20
20
  }
21
21
  toIsoId() {
22
- return YearIsoId.parse(String(getYear(this.getStart().get())));
22
+ return YearIsoId.parse(String(getYear(this.getStart().ms)));
23
23
  }
24
24
  isLeapYear() {
25
- const year = getYear(this.getStart().get());
25
+ const year = getYear(this.getStart().ms);
26
26
  return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;
27
27
  }
28
28
  previous() {
@@ -32,8 +32,8 @@ export class Year extends DateRange {
32
32
  return this.shift(1);
33
33
  }
34
34
  shift(count) {
35
- const shifted = addYears(this.getStart().get(), count).getTime();
36
- return Year.fromTimestamp(Timestamp.fromNumber(shifted));
35
+ const shifted = addYears(this.getStart().ms, count).getTime();
36
+ return Year.fromTimestamp(TimestampVO.fromNumber(shifted));
37
37
  }
38
38
  toString() {
39
39
  return this.toIsoId();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bgord/tools",
3
- "version": "1.1.0",
3
+ "version": "1.1.1",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "author": "Bartosz Gordon",
package/src/age.vo.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { differenceInYears } from "date-fns";
2
2
  import { AgeYears, AgeYearsConstraints, type AgeYearsType } from "./age-years.vo";
3
- import { Timestamp } from "./timestamp.vo";
3
+ import { TimestampVO } from "./timestamp.vo";
4
4
 
5
5
  export const AgeError = { FutureBirthdate: "age.future.birthdate" } as const;
6
6
 
@@ -14,16 +14,16 @@ export class Age {
14
14
  return new Age(AgeYears.parse(candidate));
15
15
  }
16
16
 
17
- static fromBirthdateEpochMs(params: { birthdate: Timestamp; now: Timestamp }): Age {
17
+ static fromBirthdateEpochMs(params: { birthdate: TimestampVO; now: TimestampVO }): Age {
18
18
  if (params.birthdate.isAfter(params.now)) throw new Error(AgeError.FutureBirthdate);
19
- return Age.fromValue(differenceInYears(params.now.get(), params.birthdate.get()));
19
+ return Age.fromValue(differenceInYears(params.now.ms, params.birthdate.ms));
20
20
  }
21
21
 
22
- static fromBirthdate(candidate: { birthdate: string; now: Timestamp }): Age {
23
- const birthdate = Timestamp.fromNumber(new Date(candidate.birthdate).getTime());
22
+ static fromBirthdate(candidate: { birthdate: string; now: TimestampVO }): Age {
23
+ const birthdate = TimestampVO.fromNumber(new Date(candidate.birthdate).getTime());
24
24
 
25
25
  if (birthdate.isAfter(candidate.now)) throw new Error(AgeError.FutureBirthdate);
26
- return Age.fromValue(differenceInYears(candidate.now.get(), birthdate.get()));
26
+ return Age.fromValue(differenceInYears(candidate.now.ms, birthdate.ms));
27
27
  }
28
28
 
29
29
  get(): number {
package/src/clock.vo.ts CHANGED
@@ -3,7 +3,7 @@ import { Hour } from "./hour.vo";
3
3
  import type { HourSchemaType } from "./hour-schema.vo";
4
4
  import { Minute } from "./minute.vo";
5
5
  import type { MinuteSchemaType } from "./minute-schema.vo";
6
- import type { Timestamp } from "./timestamp.vo";
6
+ import type { TimestampVO } from "./timestamp.vo";
7
7
 
8
8
  export class Clock {
9
9
  private readonly formatter: ClockFormatter;
@@ -16,7 +16,7 @@ export class Clock {
16
16
  this.formatter = formatter ?? ClockFormatters.TWENTY_FOUR_HOURS;
17
17
  }
18
18
 
19
- static fromEpochMs(timestamp: Timestamp, formatter?: ClockFormatter): Clock {
19
+ static fromEpochMs(timestamp: TimestampVO, formatter?: ClockFormatter): Clock {
20
20
  const hour = Hour.fromEpochMs(timestamp);
21
21
  const minute = Minute.fromEpochMs(timestamp);
22
22
 
@@ -1,22 +1,18 @@
1
1
  import { Duration } from "./duration.service";
2
- import type { TimeZoneOffsetValueType } from "./time-zone-offset-value.vo";
3
- import { Timestamp } from "./timestamp.vo";
2
+ import { TimestampVO } from "./timestamp.vo";
4
3
 
5
- type GetStartOfDayTsInTzConfigType = { now: Timestamp; timeZoneOffsetMs: TimeZoneOffsetValueType };
4
+ type GetStartOfDayTsInTzConfigType = { now: TimestampVO; timeZoneOffset: Duration };
6
5
 
7
6
  export class DateCalculator {
8
- static getStartOfDayTsInTz(config: GetStartOfDayTsInTzConfigType): Timestamp {
7
+ static getStartOfDayTsInTz(config: GetStartOfDayTsInTzConfigType): TimestampVO {
9
8
  const dayMs = Duration.Days(1).ms;
10
9
 
11
- // UTC midnight for the UTC date of `now`
12
- const utcMidnight = Math.floor(config.now.get() / dayMs) * dayMs;
10
+ const utcMidnightOfNow = TimestampVO.fromNumber(Math.floor(config.now.ms / dayMs) * dayMs);
13
11
 
14
- // Candidate start of the local day (in UTC), anchored to the same UTC date
15
- let start = utcMidnight + config.timeZoneOffsetMs;
12
+ let startOfDayInTz = utcMidnightOfNow.add(config.timeZoneOffset);
16
13
 
17
- // If the candidate is in the future relative to `now`, it means local midnight was "yesterday" in UTC.
18
- if (start > config.now.get()) start -= dayMs;
14
+ if (startOfDayInTz.isAfter(config.now)) startOfDayInTz = startOfDayInTz.subtract(Duration.Days(1));
19
15
 
20
- return Timestamp.fromNumber(start);
16
+ return startOfDayInTz;
21
17
  }
22
18
  }
@@ -1,28 +1,28 @@
1
- import type { Timestamp } from "./timestamp.vo";
1
+ import type { TimestampVO } from "./timestamp.vo";
2
2
 
3
3
  export const DateRangeError = { Invalid: "date.range.invalid" } as const;
4
4
 
5
5
  export class DateRange {
6
6
  constructor(
7
- private readonly start: Timestamp,
8
- private readonly end: Timestamp,
7
+ private readonly start: TimestampVO,
8
+ private readonly end: TimestampVO,
9
9
  ) {
10
10
  if (start.isAfter(end)) throw new Error(DateRangeError.Invalid);
11
11
  }
12
12
 
13
- getStart(): Timestamp {
13
+ getStart(): TimestampVO {
14
14
  return this.start;
15
15
  }
16
16
 
17
- getEnd(): Timestamp {
17
+ getEnd(): TimestampVO {
18
18
  return this.end;
19
19
  }
20
20
 
21
- toRange(): [Timestamp, Timestamp] {
21
+ toRange(): [TimestampVO, TimestampVO] {
22
22
  return [this.start, this.end];
23
23
  }
24
24
 
25
- contains(timestamp: Timestamp): boolean {
25
+ contains(timestamp: TimestampVO): boolean {
26
26
  return timestamp.isAfterOrEqual(this.start) && timestamp.isBeforeOrEqual(this.end);
27
27
  }
28
28
 
@@ -31,6 +31,6 @@ export class DateRange {
31
31
  }
32
32
 
33
33
  toJSON(): { start: number; end: number } {
34
- return { start: this.getStart().get(), end: this.getEnd().get() };
34
+ return { start: this.getStart().ms, end: this.getEnd().ms };
35
35
  }
36
36
  }
package/src/day.vo.ts CHANGED
@@ -2,13 +2,13 @@ import { formatISO } from "date-fns";
2
2
  import { DateRange } from "./date-range.vo";
3
3
  import { DayIsoId, type DayIsoIdType } from "./day-iso-id.vo";
4
4
  import { Duration } from "./duration.service";
5
- import { Timestamp } from "./timestamp.vo";
5
+ import { TimestampVO } from "./timestamp.vo";
6
6
 
7
7
  export class Day extends DateRange {
8
- static fromTimestamp(timestamp: Timestamp): Day {
9
- const date = new Date(timestamp.get());
8
+ static fromTimestamp(timestamp: TimestampVO): Day {
9
+ const date = new Date(timestamp.ms);
10
10
 
11
- const startUtc = Timestamp.fromNumber(
11
+ const startUtc = TimestampVO.fromNumber(
12
12
  Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate()),
13
13
  );
14
14
  const endUtc = startUtc.add(Duration.Days(1)).subtract(Duration.Ms(1));
@@ -16,14 +16,14 @@ export class Day extends DateRange {
16
16
  return new Day(startUtc, endUtc);
17
17
  }
18
18
 
19
- static fromNow(now: Timestamp): Day {
19
+ static fromNow(now: TimestampVO): Day {
20
20
  return Day.fromTimestamp(now);
21
21
  }
22
22
 
23
23
  static fromIsoId(isoId: DayIsoIdType): Day {
24
24
  const [year, month, day] = DayIsoId.parse(isoId).split("-").map(Number);
25
25
 
26
- const startUtc = Timestamp.fromNumber(Date.UTC(year, month - 1, day));
26
+ const startUtc = TimestampVO.fromNumber(Date.UTC(year, month - 1, day));
27
27
  const endUtc = startUtc.add(Duration.Days(1)).subtract(Duration.Ms(1));
28
28
 
29
29
  return new Day(startUtc, endUtc);
@@ -32,7 +32,7 @@ export class Day extends DateRange {
32
32
  toIsoId(): DayIsoIdType {
33
33
  const midday = this.getStart().add(Duration.Hours(12));
34
34
 
35
- return DayIsoId.parse(formatISO(midday.get(), { representation: "date" }));
35
+ return DayIsoId.parse(formatISO(midday.ms, { representation: "date" }));
36
36
  }
37
37
 
38
38
  previous(): Day {
package/src/hour.vo.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { type HourFormatter, HourFormatters } from "./hour-format.service";
2
2
  import { HourSchema, type HourSchemaType } from "./hour-schema.vo";
3
- import type { Timestamp } from "./timestamp.vo";
3
+ import type { TimestampVO } from "./timestamp.vo";
4
4
 
5
5
  export class Hour {
6
6
  private readonly value: HourSchemaType;
@@ -12,8 +12,8 @@ export class Hour {
12
12
  this.value = HourSchema.parse(candidate);
13
13
  }
14
14
 
15
- static fromEpochMs(timestamp: Timestamp): Hour {
16
- return new Hour(new Date(timestamp.get()).getUTCHours());
15
+ static fromEpochMs(timestamp: TimestampVO): Hour {
16
+ return new Hour(new Date(timestamp.ms).getUTCHours());
17
17
  }
18
18
 
19
19
  get(): HourSchemaType {
package/src/minute.vo.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { MinuteSchema, type MinuteSchemaType } from "./minute-schema.vo";
2
- import type { Timestamp } from "./timestamp.vo";
2
+ import type { TimestampVO } from "./timestamp.vo";
3
3
 
4
4
  export class Minute {
5
5
  private readonly value: MinuteSchemaType;
@@ -11,8 +11,8 @@ export class Minute {
11
11
  this.value = MinuteSchema.parse(candidate);
12
12
  }
13
13
 
14
- static fromEpochMs(timestamp: Timestamp): Minute {
15
- return new Minute(new Date(timestamp.get()).getUTCMinutes());
14
+ static fromEpochMs(timestamp: TimestampVO): Minute {
15
+ return new Minute(new Date(timestamp.ms).getUTCMinutes());
16
16
  }
17
17
 
18
18
  get(): MinuteSchemaType {
package/src/month.vo.ts CHANGED
@@ -1,17 +1,17 @@
1
1
  import { endOfMonth, format, getMonth, setMonth, startOfMonth } from "date-fns";
2
2
  import { DateRange } from "./date-range.vo";
3
3
  import { MonthIsoId, type MonthIsoIdType } from "./month-iso-id.vo";
4
- import { Timestamp } from "./timestamp.vo";
4
+ import { TimestampVO } from "./timestamp.vo";
5
5
 
6
6
  export class Month extends DateRange {
7
- static fromTimestamp(timestamp: Timestamp): Month {
8
- const start = Timestamp.fromNumber(startOfMonth(timestamp.get()).getTime());
9
- const end = Timestamp.fromNumber(endOfMonth(timestamp.get()).getTime());
7
+ static fromTimestamp(timestamp: TimestampVO): Month {
8
+ const start = TimestampVO.fromNumber(startOfMonth(timestamp.ms).getTime());
9
+ const end = TimestampVO.fromNumber(endOfMonth(timestamp.ms).getTime());
10
10
 
11
11
  return new Month(start, end);
12
12
  }
13
13
 
14
- static fromNow(now: Timestamp): Month {
14
+ static fromNow(now: TimestampVO): Month {
15
15
  return Month.fromTimestamp(now);
16
16
  }
17
17
 
@@ -20,11 +20,11 @@ export class Month extends DateRange {
20
20
 
21
21
  const reference = setMonth(Date.UTC(year), month - 1).getTime();
22
22
 
23
- return Month.fromTimestamp(Timestamp.fromNumber(reference));
23
+ return Month.fromTimestamp(TimestampVO.fromNumber(reference));
24
24
  }
25
25
 
26
26
  toIsoId(): MonthIsoIdType {
27
- return MonthIsoId.parse(format(this.getStart().get(), "yyyy-MM"));
27
+ return MonthIsoId.parse(format(this.getStart().ms, "yyyy-MM"));
28
28
  }
29
29
 
30
30
  previous(): Month {
@@ -36,9 +36,9 @@ export class Month extends DateRange {
36
36
  }
37
37
 
38
38
  shift(count: number): Month {
39
- const shifted = setMonth(this.getStart().get(), getMonth(this.getStart().get()) + count).getTime();
39
+ const shifted = setMonth(this.getStart().ms, getMonth(this.getStart().ms) + count).getTime();
40
40
 
41
- return Month.fromTimestamp(Timestamp.fromNumber(shifted));
41
+ return Month.fromTimestamp(TimestampVO.fromNumber(shifted));
42
42
  }
43
43
 
44
44
  toString(): string {
package/src/quarter.vo.ts CHANGED
@@ -1,17 +1,17 @@
1
1
  import { endOfQuarter, getQuarter, getYear, setQuarter, startOfQuarter } from "date-fns";
2
2
  import { DateRange } from "./date-range.vo";
3
3
  import { QuarterIsoId, type QuarterIsoIdType } from "./quarter-iso-id.vo";
4
- import { Timestamp } from "./timestamp.vo";
4
+ import { TimestampVO } from "./timestamp.vo";
5
5
 
6
6
  export class Quarter extends DateRange {
7
- static fromTimestamp(timestamp: Timestamp): Quarter {
8
- const start = Timestamp.fromNumber(startOfQuarter(timestamp.get()).getTime());
9
- const end = Timestamp.fromNumber(endOfQuarter(timestamp.get()).getTime());
7
+ static fromTimestamp(timestamp: TimestampVO): Quarter {
8
+ const start = TimestampVO.fromNumber(startOfQuarter(timestamp.ms).getTime());
9
+ const end = TimestampVO.fromNumber(endOfQuarter(timestamp.ms).getTime());
10
10
 
11
11
  return new Quarter(start, end);
12
12
  }
13
13
 
14
- static fromNow(now: Timestamp): Quarter {
14
+ static fromNow(now: TimestampVO): Quarter {
15
15
  return Quarter.fromTimestamp(now);
16
16
  }
17
17
 
@@ -20,12 +20,12 @@ export class Quarter extends DateRange {
20
20
 
21
21
  const reference = setQuarter(Date.UTC(year), quarter).getTime();
22
22
 
23
- return Quarter.fromTimestamp(Timestamp.fromNumber(reference));
23
+ return Quarter.fromTimestamp(TimestampVO.fromNumber(reference));
24
24
  }
25
25
 
26
26
  toIsoId(): QuarterIsoIdType {
27
- const year = getYear(this.getStart().get());
28
- const quarter = getQuarter(this.getStart().get());
27
+ const year = getYear(this.getStart().ms);
28
+ const quarter = getQuarter(this.getStart().ms);
29
29
 
30
30
  return QuarterIsoId.parse(`${year}-Q${quarter}`);
31
31
  }
@@ -1,16 +1,16 @@
1
- import { Duration } from "./duration.service";
2
- import type { Timestamp } from "./timestamp.vo";
1
+ import type { Duration } from "./duration.service";
2
+ import type { TimestampVO } from "./timestamp.vo";
3
3
 
4
4
  type RateLimiterResultSuccessType = { allowed: true };
5
5
  type RateLimiterResultErrorType = { allowed: false; remaining: Duration };
6
6
  type RateLimiterResultType = RateLimiterResultSuccessType | RateLimiterResultErrorType;
7
7
 
8
8
  export class RateLimiter {
9
- private lastInvocation: Timestamp | null = null;
9
+ private lastInvocation: TimestampVO | null = null;
10
10
 
11
11
  constructor(private readonly duration: Duration) {}
12
12
 
13
- verify(now: Timestamp): RateLimiterResultType {
13
+ verify(now: TimestampVO): RateLimiterResultType {
14
14
  if (this.lastInvocation == null) {
15
15
  this.lastInvocation = now;
16
16
 
@@ -25,8 +25,6 @@ export class RateLimiter {
25
25
  return { allowed: true };
26
26
  }
27
27
 
28
- const remainingDelta = nextAllowedTimestamp.get() - now.get();
29
-
30
- return { allowed: false, remaining: Duration.Ms(remainingDelta) };
28
+ return { allowed: false, remaining: nextAllowedTimestamp.difference(now) };
31
29
  }
32
30
  }
@@ -1,21 +1,21 @@
1
1
  import { DateFormatters } from "./date-formatter.service";
2
- import type { Timestamp } from "./timestamp.vo";
2
+ import type { TimestampVO } from "./timestamp.vo";
3
3
  import type { TimestampValueType } from "./timestamp-value.vo";
4
4
  import type { Falsy } from "./ts-utils";
5
5
 
6
6
  type RelativeDateType = { raw: TimestampValueType; relative: string };
7
7
 
8
8
  export class RelativeDate {
9
- static truthy(timestamp: Timestamp): RelativeDateType {
9
+ static truthy(timestamp: TimestampVO): RelativeDateType {
10
10
  return RelativeDate._format(timestamp);
11
11
  }
12
12
 
13
- static falsy(timestamp: Falsy<Timestamp>): RelativeDateType | null {
13
+ static falsy(timestamp: Falsy<TimestampVO>): RelativeDateType | null {
14
14
  if (!timestamp) return null;
15
15
  return RelativeDate._format(timestamp);
16
16
  }
17
17
 
18
- private static _format(timestamp: Timestamp): RelativeDateType {
19
- return { raw: timestamp.get(), relative: DateFormatters.relative(timestamp.get()) };
18
+ private static _format(timestamp: TimestampVO): RelativeDateType {
19
+ return { raw: timestamp.ms, relative: DateFormatters.relative(timestamp.ms) };
20
20
  }
21
21
  }
@@ -1,5 +1,5 @@
1
- import { Duration } from "./duration.service";
2
- import { Timestamp } from "./timestamp.vo";
1
+ import type { Duration } from "./duration.service";
2
+ import { TimestampVO } from "./timestamp.vo";
3
3
 
4
4
  export const StopwatchError = { AlreadyStopped: "stopwatch.already.stopped" } as const;
5
5
 
@@ -13,13 +13,13 @@ export type StopwatchResultType = Duration;
13
13
  export class Stopwatch {
14
14
  private state: StopwatchState = StopwatchState.started;
15
15
 
16
- constructor(private readonly start: Timestamp) {}
16
+ constructor(private readonly start: TimestampVO) {}
17
17
 
18
18
  stop(): StopwatchResultType {
19
19
  if (this.state === StopwatchState.stopped) throw new Error(StopwatchError.AlreadyStopped);
20
20
 
21
21
  this.state = StopwatchState.stopped;
22
22
 
23
- return Duration.Ms(Timestamp.fromNumber(Date.now() - this.start.get()).get());
23
+ return TimestampVO.fromNumber(Date.now()).difference(this.start);
24
24
  }
25
25
  }
@@ -1,46 +1,50 @@
1
- import type { Duration } from "./duration.service";
1
+ import { Duration } from "./duration.service";
2
2
  import { TimestampValue, type TimestampValueType } from "./timestamp-value.vo";
3
3
 
4
- export class Timestamp {
4
+ export class TimestampVO {
5
5
  constructor(private readonly value: TimestampValueType) {}
6
6
 
7
- static fromValue(value: TimestampValueType): Timestamp {
8
- return new Timestamp(value);
7
+ static fromValue(value: TimestampValueType): TimestampVO {
8
+ return new TimestampVO(value);
9
9
  }
10
10
 
11
- static fromNumber(value: number): Timestamp {
12
- return new Timestamp(TimestampValue.parse(value));
11
+ static fromNumber(value: number): TimestampVO {
12
+ return new TimestampVO(TimestampValue.parse(value));
13
13
  }
14
14
 
15
- add(duration: Duration): Timestamp {
16
- return Timestamp.fromNumber(this.value + duration.ms);
15
+ add(duration: Duration): TimestampVO {
16
+ return TimestampVO.fromNumber(this.value + duration.ms);
17
17
  }
18
18
 
19
- subtract(duration: Duration): Timestamp {
20
- return Timestamp.fromNumber(this.value - duration.ms);
19
+ subtract(duration: Duration): TimestampVO {
20
+ return TimestampVO.fromNumber(this.value - duration.ms);
21
21
  }
22
22
 
23
- isBefore(another: Timestamp): boolean {
23
+ difference(another: TimestampVO): Duration {
24
+ return Duration.Ms(this.value - another.value);
25
+ }
26
+
27
+ isBefore(another: TimestampVO): boolean {
24
28
  return this.value < another.value;
25
29
  }
26
30
 
27
- isBeforeOrEqual(another: Timestamp): boolean {
31
+ isBeforeOrEqual(another: TimestampVO): boolean {
28
32
  return this.value <= another.value;
29
33
  }
30
34
 
31
- isAfter(another: Timestamp): boolean {
35
+ isAfter(another: TimestampVO): boolean {
32
36
  return this.value > another.value;
33
37
  }
34
38
 
35
- isAfterOrEqual(another: Timestamp): boolean {
39
+ isAfterOrEqual(another: TimestampVO): boolean {
36
40
  return this.value >= another.value;
37
41
  }
38
42
 
39
- equals(another: Timestamp): boolean {
43
+ equals(another: TimestampVO): boolean {
40
44
  return this.value === another.value;
41
45
  }
42
46
 
43
- get(): TimestampValueType {
47
+ get ms(): TimestampValueType {
44
48
  return this.value;
45
49
  }
46
50
 
package/src/week.vo.ts CHANGED
@@ -1,17 +1,17 @@
1
1
  import { addWeeks, endOfISOWeek, getISOWeek, getISOWeekYear, setISOWeek, startOfISOWeek } from "date-fns";
2
2
  import { DateRange } from "./date-range.vo";
3
- import { Timestamp } from "./timestamp.vo";
3
+ import { TimestampVO } from "./timestamp.vo";
4
4
  import { WeekIsoId, type WeekIsoIdType } from "./week-iso-id.vo";
5
5
 
6
6
  export class Week extends DateRange {
7
- static fromTimestamp(timestamp: Timestamp): Week {
8
- const start = Timestamp.fromNumber(startOfISOWeek(timestamp.get()).getTime());
9
- const end = Timestamp.fromNumber(endOfISOWeek(timestamp.get()).getTime());
7
+ static fromTimestamp(timestamp: TimestampVO): Week {
8
+ const start = TimestampVO.fromNumber(startOfISOWeek(timestamp.ms).getTime());
9
+ const end = TimestampVO.fromNumber(endOfISOWeek(timestamp.ms).getTime());
10
10
 
11
11
  return new Week(start, end);
12
12
  }
13
13
 
14
- static fromNow(now: Timestamp): Week {
14
+ static fromNow(now: TimestampVO): Week {
15
15
  return Week.fromTimestamp(now);
16
16
  }
17
17
 
@@ -21,12 +21,12 @@ export class Week extends DateRange {
21
21
  // ISO-8601 rule: Jan 4 is always in week 01 of the ISO week-year.
22
22
  const reference = setISOWeek(Date.UTC(year, 0, 4), week).getTime();
23
23
 
24
- return Week.fromTimestamp(Timestamp.fromNumber(reference));
24
+ return Week.fromTimestamp(TimestampVO.fromNumber(reference));
25
25
  }
26
26
 
27
27
  toIsoId(): WeekIsoIdType {
28
- const year = getISOWeekYear(this.getStart().get());
29
- const week = getISOWeek(this.getStart().get());
28
+ const year = getISOWeekYear(this.getStart().ms);
29
+ const week = getISOWeek(this.getStart().ms);
30
30
 
31
31
  return WeekIsoId.parse(`${year}-W${String(week).padStart(2, "0")}`);
32
32
  }
@@ -40,9 +40,9 @@ export class Week extends DateRange {
40
40
  }
41
41
 
42
42
  shift(count: number): Week {
43
- const shifted = addWeeks(this.getStart().get(), count).getTime();
43
+ const shifted = addWeeks(this.getStart().ms, count).getTime();
44
44
 
45
- return Week.fromTimestamp(Timestamp.fromNumber(shifted));
45
+ return Week.fromTimestamp(TimestampVO.fromNumber(shifted));
46
46
  }
47
47
 
48
48
  toString(): string {
package/src/weekday.vo.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { Timestamp } from "./timestamp.vo";
1
+ import type { TimestampVO } from "./timestamp.vo";
2
2
 
3
3
  export type WeekdayFormatter = (value: Weekday["value"]) => string;
4
4
 
@@ -52,8 +52,8 @@ export class Weekday {
52
52
  this.formatter = formatter ?? WeekdayFormatters.FULL;
53
53
  }
54
54
 
55
- static fromUtcTimestamp(timestamp: Timestamp, formatter?: WeekdayFormatter): Weekday {
56
- const dayZeroBased = new Date(timestamp.get()).getUTCDay(); // 0..6
55
+ static fromUtcTimestamp(timestamp: TimestampVO, formatter?: WeekdayFormatter): Weekday {
56
+ const dayZeroBased = new Date(timestamp.ms).getUTCDay(); // 0..6
57
57
  return new Weekday(dayZeroBased, formatter);
58
58
  }
59
59
 
package/src/year.vo.ts CHANGED
@@ -1,17 +1,17 @@
1
1
  import { addYears, endOfYear, getYear, startOfYear } from "date-fns";
2
2
  import { DateRange } from "./date-range.vo";
3
- import { Timestamp } from "./timestamp.vo";
3
+ import { TimestampVO } from "./timestamp.vo";
4
4
  import { YearIsoId, type YearIsoIdType } from "./year-iso-id.vo";
5
5
 
6
6
  export class Year extends DateRange {
7
- static fromTimestamp(timestamp: Timestamp): Year {
8
- const start = Timestamp.fromNumber(startOfYear(timestamp.get()).getTime());
9
- const end = Timestamp.fromNumber(endOfYear(timestamp.get()).getTime());
7
+ static fromTimestamp(timestamp: TimestampVO): Year {
8
+ const start = TimestampVO.fromNumber(startOfYear(timestamp.ms).getTime());
9
+ const end = TimestampVO.fromNumber(endOfYear(timestamp.ms).getTime());
10
10
 
11
11
  return new Year(start, end);
12
12
  }
13
13
 
14
- static fromNow(now: Timestamp): Year {
14
+ static fromNow(now: TimestampVO): Year {
15
15
  return Year.fromTimestamp(now);
16
16
  }
17
17
 
@@ -22,15 +22,15 @@ export class Year extends DateRange {
22
22
  static fromIsoId(isoId: YearIsoIdType): Year {
23
23
  const reference = Date.UTC(Number(isoId));
24
24
 
25
- return Year.fromTimestamp(Timestamp.fromNumber(reference));
25
+ return Year.fromTimestamp(TimestampVO.fromNumber(reference));
26
26
  }
27
27
 
28
28
  toIsoId(): YearIsoIdType {
29
- return YearIsoId.parse(String(getYear(this.getStart().get())));
29
+ return YearIsoId.parse(String(getYear(this.getStart().ms)));
30
30
  }
31
31
 
32
32
  isLeapYear(): boolean {
33
- const year = getYear(this.getStart().get());
33
+ const year = getYear(this.getStart().ms);
34
34
 
35
35
  return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;
36
36
  }
@@ -44,9 +44,9 @@ export class Year extends DateRange {
44
44
  }
45
45
 
46
46
  shift(count: number): Year {
47
- const shifted = addYears(this.getStart().get(), count).getTime();
47
+ const shifted = addYears(this.getStart().ms, count).getTime();
48
48
 
49
- return Year.fromTimestamp(Timestamp.fromNumber(shifted));
49
+ return Year.fromTimestamp(TimestampVO.fromNumber(shifted));
50
50
  }
51
51
 
52
52
  toString(): string {