Fix time formatting
This commit is contained in:
parent
87f582590b
commit
7148254b35
|
|
@ -59,6 +59,7 @@ Bun.serve<ClientData>({
|
|||
clients.delete(ws);
|
||||
if (clients.size === 0) wsClients.delete(game);
|
||||
}
|
||||
console.log(`[css-hot] ${game} disconnected (${wsClients.get(game)!.size} clients)`);
|
||||
},
|
||||
message() { },
|
||||
},
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
"version": "1.0.0",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"start": "bun --hot build/server.ts",
|
||||
"start": "bun build/server.ts",
|
||||
"bake": "bun build/build.ts",
|
||||
"test": "bun test"
|
||||
},
|
||||
|
|
|
|||
|
|
@ -120,13 +120,25 @@ export const formatNumber = (n: number): string => {
|
|||
};
|
||||
|
||||
export const formatTime = (seconds: number): string => {
|
||||
const y = Math.floor(seconds / 31536000);
|
||||
const mo = Math.floor((seconds % 31536000) / 2592000);
|
||||
const w = Math.floor((seconds % 2592000) / 604800);
|
||||
const d = Math.floor((seconds % 604800) / 86400);
|
||||
const h = Math.floor((seconds % 86400) / 3600);
|
||||
const mi = Math.floor((seconds % 3600) / 60);
|
||||
const s = Math.floor(seconds % 60);
|
||||
const secInMinute = 60;
|
||||
const secInHour = 60 * secInMinute;
|
||||
const secInDay = 24 * secInHour;
|
||||
const secInWeek = 7 * secInDay;
|
||||
const secInMonth = 30 * secInDay;
|
||||
const secInYear = 365 * secInDay;
|
||||
|
||||
const y = Math.floor(seconds / secInYear);
|
||||
let rem = seconds % secInYear;
|
||||
const mo = Math.floor(rem / secInMonth);
|
||||
rem %= secInMonth;
|
||||
const w = Math.floor(rem / secInWeek);
|
||||
rem %= secInWeek;
|
||||
const d = Math.floor(rem / secInDay);
|
||||
rem %= secInDay;
|
||||
const h = Math.floor(rem / secInHour);
|
||||
rem %= secInHour;
|
||||
const mi = Math.floor(rem / secInMinute);
|
||||
const s = Math.floor(rem % secInMinute);
|
||||
|
||||
const parts: string[] = [];
|
||||
if (y > 0) parts.push(`${y}y`);
|
||||
|
|
@ -135,9 +147,10 @@ export const formatTime = (seconds: number): string => {
|
|||
if (d > 0) parts.push(`${d}d`);
|
||||
|
||||
const hasBigParts = parts.length > 0;
|
||||
const hasTime = h > 0 || mi > 0 || s > 0;
|
||||
if (hasBigParts || hasTime) {
|
||||
parts.push(`${h}:${String(mi).padStart(2, '0')}:${String(s).padStart(2, '0')}`);
|
||||
}
|
||||
return parts.join(' ') || '0:00:00';
|
||||
const timeStr = hasBigParts || h > 0
|
||||
? `${h}:${String(mi).padStart(2, '0')}:${String(s).padStart(2, '0')}`
|
||||
: `${mi}:${String(s).padStart(2, '0')}`;
|
||||
|
||||
parts.push(timeStr);
|
||||
return parts.join(' ');
|
||||
};
|
||||
|
|
|
|||
|
|
@ -16,6 +16,8 @@ import {
|
|||
sinHash,
|
||||
throttle,
|
||||
callUpdater,
|
||||
formatTime,
|
||||
formatNumber,
|
||||
} from '@common/utils';
|
||||
|
||||
describe('utils', () => {
|
||||
|
|
@ -268,7 +270,13 @@ describe('utils', () => {
|
|||
it('should be deterministic', () => {
|
||||
const hash1 = sinHash(1, 2, 3);
|
||||
const hash2 = sinHash(1, 2, 3);
|
||||
expect(hash1).toBe(hash2);
|
||||
expect(hash1).toBeCloseTo(hash2);
|
||||
});
|
||||
|
||||
it('should produce different hashes for different inputs', () => {
|
||||
const hash1 = sinHash(1, 2, 3);
|
||||
const hash2 = sinHash(4, 5, 6);
|
||||
expect(hash1).not.toBeCloseTo(hash2);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -300,4 +308,89 @@ describe('utils', () => {
|
|||
expect(callUpdater(10, 5)).toBe(10);
|
||||
});
|
||||
});
|
||||
|
||||
describe('formatNumber', () => {
|
||||
it('should return small numbers as-is', () => {
|
||||
expect(formatNumber(0)).toBe('0');
|
||||
expect(formatNumber(42)).toBe('42');
|
||||
expect(formatNumber(999)).toBe('999');
|
||||
});
|
||||
|
||||
it('should format thousands with k suffix', () => {
|
||||
expect(formatNumber(1_000)).toBe('1.00k');
|
||||
expect(formatNumber(5_500)).toBe('5.50k');
|
||||
expect(formatNumber(999_999)).toBe('1000.00k');
|
||||
});
|
||||
|
||||
it('should format millions with M suffix', () => {
|
||||
expect(formatNumber(1_000_000)).toBe('1.00M');
|
||||
expect(formatNumber(2_500_000)).toBe('2.50M');
|
||||
expect(formatNumber(999_999_999)).toBe('1000.00M');
|
||||
});
|
||||
|
||||
it('should format billions with B suffix', () => {
|
||||
expect(formatNumber(1_000_000_000)).toBe('1.00B');
|
||||
expect(formatNumber(3_750_000_000)).toBe('3.75B');
|
||||
expect(formatNumber(999_999_999_999)).toBe('1000.00B');
|
||||
});
|
||||
|
||||
it('should format trillions with T suffix', () => {
|
||||
expect(formatNumber(1_000_000_000_000)).toBe('1.00T');
|
||||
expect(formatNumber(5_250_000_000_000)).toBe('5.25T');
|
||||
});
|
||||
});
|
||||
|
||||
describe('formatTime', () => {
|
||||
it('should return 0:00 for zero seconds', () => {
|
||||
expect(formatTime(0)).toBe('0:00');
|
||||
});
|
||||
|
||||
it('should format seconds correctly', () => {
|
||||
expect(formatTime(1)).toBe('0:01');
|
||||
expect(formatTime(30)).toBe('0:30');
|
||||
expect(formatTime(59)).toBe('0:59');
|
||||
});
|
||||
|
||||
it('should format minutes correctly', () => {
|
||||
expect(formatTime(60)).toBe('1:00');
|
||||
expect(formatTime(2 * 60 + 5)).toBe('2:05');
|
||||
expect(formatTime(59 * 60 + 59)).toBe('59:59');
|
||||
});
|
||||
|
||||
it('should format hours correctly', () => {
|
||||
expect(formatTime(60 * 60)).toBe('1:00:00');
|
||||
expect(formatTime(2 * 60 * 60 + 60 + 5)).toBe('2:01:05');
|
||||
});
|
||||
|
||||
it('should format days correctly', () => {
|
||||
expect(formatTime(24 * 60 * 60)).toBe('1d 0:00:00');
|
||||
expect(formatTime(2 * 24 * 60 * 60)).toBe('2d 0:00:00');
|
||||
});
|
||||
|
||||
it('should format weeks correctly', () => {
|
||||
expect(formatTime(7 * 24 * 60 * 60)).toBe('1w 0:00:00');
|
||||
});
|
||||
|
||||
it('should format months correctly', () => {
|
||||
const month = 30 * 24 * 60 * 60;
|
||||
expect(formatTime(month)).toBe('1m 0:00:00');
|
||||
});
|
||||
|
||||
it('should format years correctly', () => {
|
||||
const year = 365 * 24 * 60 * 60;
|
||||
expect(formatTime(year)).toBe('1y 0:00:00');
|
||||
});
|
||||
|
||||
it('should format complex durations', () => {
|
||||
const total =
|
||||
365 * 24 * 60 * 60 + // 1y
|
||||
30 * 24 * 60 * 60 + // 1m
|
||||
7 * 24 * 60 * 60 + // 1w
|
||||
24 * 60 * 60 + // 1d
|
||||
60 * 60 + // 1h
|
||||
60 + // 1m
|
||||
1; // 1s
|
||||
expect(formatTime(total)).toBe('1y 1m 1w 1d 1:01:01');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in New Issue