feat: implement SQLite UTC timestamp normalization in stalker-item normalizer

This commit is contained in:
4gray committed 2026-04-22 22:21:29 +02:00
1 parent ad528238b2
commit a5b26065c9
2 files changed
+65

No files matched your search

@@ -0,0 +1,27 @@
import { normalizeStalkerDate } from './stalker-item.normalizer';
describe('normalizeStalkerDate', () => {
it('normalizes SQLite UTC timestamps without relying on engine-specific parsing', () => {
const originalParse = Date.parse;
const parseSpy = jest
.spyOn(Date, 'parse')
.mockImplementation((value: string) => {
if (value === '2026-04-21 22:49:02') {
return Number.NaN;
}
return originalParse(value);
});
expect(normalizeStalkerDate('2026-04-21 22:49:02')).toBe(
'2026-04-21T22:49:02.000Z'
);
expect(parseSpy).not.toHaveBeenCalledWith('2026-04-21 22:49:02');
});
it('preserves fractional seconds in SQLite UTC timestamps', () => {
expect(normalizeStalkerDate('2026-04-21 22:49:02.7')).toBe(
'2026-04-21T22:49:02.700Z'
);
});
});
@@ -3,6 +3,9 @@ import {
StalkerPortalItem,
} from './stalker-portal-item.interface';
const SQLITE_UTC_TIMESTAMP_PATTERN =
/^(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})(?:\.(\d{1,3}))?$/;
/**
* Extract a stable ID from an untyped Stalker portal item.
*
@@ -93,6 +96,10 @@ export function normalizeStalkerDate(value: unknown): string {
return new Date(ms).toISOString();
}
}
const sqliteUtcIso = normalizeSqliteUtcTimestamp(trimmed);
if (sqliteUtcIso) {
return sqliteUtcIso;
}
const parsed = Date.parse(trimmed);
if (!Number.isNaN(parsed)) {
return new Date(parsed).toISOString();
@@ -117,3 +124,34 @@ export function stalkerItemMatchesId(
const rawId = extractStalkerItemId(item, fallbackPrefix, fallbackIndex);
return rawId === targetId;
}
function normalizeSqliteUtcTimestamp(value: string): string | null {
const match = SQLITE_UTC_TIMESTAMP_PATTERN.exec(value);
if (!match) {
return null;
}
const [
,
year,
month,
day,
hours,
minutes,
seconds,
milliseconds = '0',
] = match;
const normalizedMs = milliseconds.padEnd(3, '0').slice(0, 3);
return new Date(
Date.UTC(
Number(year),
Number(month) - 1,
Number(day),
Number(hours),
Number(minutes),
Number(seconds),
Number(normalizedMs)
)
).toISOString();
}