Skip to content

Commit

Permalink
Merge pull request #270 from permafrost-dev/remove-dayjs-dep
Browse files Browse the repository at this point in the history
Remove dayjs dependency
  • Loading branch information
patinthehat committed Mar 29, 2024
2 parents 19e0453 + a0a3745 commit 66a1a16
Show file tree
Hide file tree
Showing 9 changed files with 132 additions and 51 deletions.
1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,6 @@
"dependencies": {
"@permafrost-dev/pretty-format": "^1.1.5",
"axios": "^1.6.8",
"dayjs": "^1.11.10",
"stacktrace-js": "^2.0.2",
"uuid": "^9.0.1",
"xml-formatter": "^3.6.2"
Expand Down
20 changes: 10 additions & 10 deletions src/Payloads/DatePayload.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { formatDateExtended } from '@/lib/utils';
import { Payload } from '@/Payloads/Payload';
import dayjs from 'dayjs';

export type PayloadType = 'date';

Expand Down Expand Up @@ -28,27 +28,27 @@ export class DatePayload extends Payload {
}

protected getTimestamp(): number | null {
if (this.date === null) return null;
if (!this.date) {
return null;
}

return dayjs(this.date.toISOString()).unix();
//remove the last '000' to get the timestamp in seconds:
return this.date.getTime() / 1000;
}

protected getFormatted(): string {
if (this.date === null) {
if (!this.date) {
return '--';
}

return dayjs(this.date.toISOString()).format(this.format);
return formatDateExtended(this.date, this.format);
}

protected getTimezoneName(): string {
if (this.date === null) {
if (!this.date) {
return '--';
}

const dateObj = this.date ? this.date : new Date();
const matches = /\((.*)\)/.exec(dateObj.toString());

return matches ? matches[1] : '--';
return formatDateExtended(this.date, 'T');
}
}
2 changes: 1 addition & 1 deletion src/Support/CacheStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export class CacheStore {
}

public countLastSecond(): number {
const lastSecond = this.clock.now().modify('-1 second');
const lastSecond = this.clock.now().subSeconds(1);
let amount = 0;

this.store.forEach(item => {
Expand Down
38 changes: 9 additions & 29 deletions src/Support/DateImmutable.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,10 @@
/* eslint-disable no-unused-vars */
import dayjs from 'dayjs';

interface DateImmutableModifyPart {
value: number;
unit: string;
}

export class DateImmutable {
public dateStr: string;
public dateTs: number;
protected _date!: Date;

public get date() {
return dayjs(this.dateStr).toDate();
return this._date;
}

public set date(value: Date) {
Expand All @@ -24,7 +17,8 @@ export class DateImmutable {
}

constructor(date: Date | null = null) {
this.date = date ?? new Date();
this._date = date ?? new Date();
this.date = this._date;
this.dateStr = this.date.toISOString();
this.dateTs = this.date.getTime();
}
Expand All @@ -33,25 +27,11 @@ export class DateImmutable {
return Math.floor(this.dateTs / 1000);
}

public modify(str: string): DateImmutable {
const strParts = str.split(' ');
const parts: DateImmutableModifyPart[] = [];

for (let idx = 0; idx < strParts.length; idx++) {
parts.push({
value: Number(strParts[idx]),
unit: strParts[idx + 1],
});

idx++;
}

let tempDate = dayjs(this.getTimestamp() * 1000);

parts.forEach(part => {
tempDate = tempDate.add(part.value * 1000);
});
public addSeconds(seconds: number): DateImmutable {
return DateImmutable.createFrom(new Date(this.dateTs + seconds * 1000));
}

return DateImmutable.createFrom(tempDate.toDate());
public subSeconds(seconds: number): DateImmutable {
return DateImmutable.createFrom(new Date(this.dateTs - seconds * 1000));
}
}
94 changes: 94 additions & 0 deletions src/lib/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -248,3 +248,97 @@ export function fileURLToPath(url): string {
throw new Error('Invalid URL.');
}
}

/**
* Returns a formatted date string using dayjs format strings.
* @param date Date
* @param format string
* @returns {string}
*/
export function formatDateExtended(date: Date, format = 'YYYY-MM-DD HH:mm:ss'): string {
const pad = number => (number < 10 ? `0${number}` : number);
const getTzName = date => {
const tzNameMatch = new Intl.DateTimeFormat('en', { timeZoneName: 'short' })
.formatToParts(date)
.find(part => part.type === 'timeZoneName');
return tzNameMatch ? tzNameMatch.value : '';
};

const tokens = {
// Year
YYYY: () => date.getFullYear(),
YY: () => String(date.getFullYear()).slice(-2),

// Month
MM: () => pad(date.getMonth() + 1),
M: () => date.getMonth() + 1,

// Day
DD: () => pad(date.getDate()),
D: () => date.getDate(),

// Hours
HH: () => pad(date.getHours()),
H: () => date.getHours(),
hh: () => pad(date.getHours() % 12 || 12),
h: () => date.getHours() % 12 || 12,

// Minutes
mm: () => pad(date.getMinutes()),
m: () => date.getMinutes(),

// Seconds
ss: () => pad(date.getSeconds()),
s: () => date.getSeconds(),

// AM/PM
A: () => (date.getHours() < 12 ? 'AM' : 'PM'),
a: () => (date.getHours() < 12 ? 'am' : 'pm'),

T: () => getTzName(date),
Z: () => {
const offset = date.getTimezoneOffset();
return `${(offset > 0 ? '-' : '+') + pad(Math.floor(Math.abs(offset) / 60))}:${pad(Math.abs(offset) % 60)}`;
},
z: () => {
const offset = date.getTimezoneOffset();
return `${(offset > 0 ? '-' : '+') + pad(Math.floor(Math.abs(offset) / 60)) + pad(Math.abs(offset) % 60)}`;
},

// Escape character is handled below in the loop
};

let formattedDate = '';
let escapeNext = false;
for (let i = 0; i < format.length; i++) {
if (format[i] === '[') {
escapeNext = true;
continue;
}

if (format[i] === ']') {
escapeNext = false;
continue;
}

if (escapeNext) {
formattedDate += format[i];
continue;
}

const twoCharToken = format.substring(i, i + 2);
const fourCharToken = format.substring(i, i + 4);

if (tokens[fourCharToken]) {
formattedDate += tokens[fourCharToken]();
i += 3; // Skip next 3 characters
} else if (tokens[twoCharToken]) {
formattedDate += tokens[twoCharToken]();
i += 1; // Skip next character
} else {
formattedDate += format[i];
}
}

return formattedDate;
}
4 changes: 2 additions & 2 deletions tests/Support/CacheStore.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,11 @@ it('can count per second', () => {

expect(store.countLastSecond()).toBe(3);

clock.moveForward('1 second');
clock.moveForwardInSeconds(1);

expect(store.countLastSecond()).toBe(3);

clock.moveForward('1 second');
clock.moveForwardInSeconds(1);

expect(store.countLastSecond()).toBe(0);
});
11 changes: 5 additions & 6 deletions tests/Support/DateImmutable.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,30 +2,29 @@
import { expect, it } from 'vitest';

import { DateImmutable } from '../../src/Support/DateImmutable';
import dayjs from 'dayjs';

it('returns a timestamp without milliseconds', () => {
const now = DateImmutable.createFrom(dayjs('2021-06-22T18:11:03.967Z').toDate());
const now = DateImmutable.createFrom(new Date('2021-06-22T18:11:03.000Z'));

expect(now.getTimestamp()).toBe(1624385463);
});

it('modifies the date by adding time', () => {
let now = DateImmutable.createFrom(dayjs('2021-06-22T18:11:03.967Z').toDate());
let now = DateImmutable.createFrom(new Date('2021-06-22T18:11:03.000Z'));

expect(now.getTimestamp()).toBe(1624385463);

now = now.modify('5 seconds');
now = now.addSeconds(5);

expect(now.getTimestamp()).toBe(1624385468);
});

it('modifies the date by subtracting time', () => {
let now = DateImmutable.createFrom(dayjs('2021-06-22T18:11:03.000Z').toDate());
let now = DateImmutable.createFrom(new Date('2021-06-22T18:11:03.000Z'));

expect(now.getTimestamp()).toBe(1624385463);

now = now.modify('-2 seconds');
now = now.subSeconds(2);

expect(now.getTimestamp()).toBe(1624385461);
});
4 changes: 2 additions & 2 deletions tests/TestClasses/FakeClock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ export class FakeClock implements Clock {
this.fixedNow = now ?? new DateImmutable();
}

public moveForward(modifier: string): void {
public moveForwardInSeconds(modifier: number): void {
const currentTime = this.now();
const modifiedTime = currentTime.modify(`${modifier}`);
const modifiedTime = currentTime.addSeconds(modifier);

this.freeze(modifiedTime);
}
Expand Down
9 changes: 9 additions & 0 deletions tests/lib/utils.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
end,
nonCryptoUuidV4,
md5,
formatDateExtended,
} from '../../src/lib/utils';

it.concurrent('sleeps for 0.1 sec', async () => {
Expand Down Expand Up @@ -79,3 +80,11 @@ it('calculates an md5 hash', () => {
const data = 'test';
expect(md5(data)).toBe('098f6bcd4621d373cade4e832627b4f6');
});

it('formats a date', () => {
const date = new Date('2021-01-01T12:34:56');
expect(formatDateExtended(date)).toBe('2021-01-01 12:34:56');
expect(formatDateExtended(date, 'YYYY-MM-DD')).toBe('2021-01-01');
expect(formatDateExtended(date, 'hh:mm:ss')).toBe('12:34:56');
expect(formatDateExtended(date, 'T').length).greaterThan(1);
});

0 comments on commit 66a1a16

Please sign in to comment.