Backend security / security (push) Successful in 9s
Backend verify / verify (push) Successful in 10m23s
Backend security / security (pull_request) Successful in 8s
Backend verify / verify (pull_request) Successful in 10m39s
Conventional commits / commits (pull_request) Successful in 29s
Identify income dependencies by role and document screen-specific dates. Convert inclusive calendar days into half-open source ranges while preserving operation timestamps and existing stored coverage.
54 lines
1.6 KiB
TypeScript
54 lines
1.6 KiB
TypeScript
const MOSCOW_UTC_OFFSET_HOURS = 3;
|
|
export type DateOnlyRange = { from: string; to: string };
|
|
const moscow = 'Europe/Moscow';
|
|
const moscowFormatter = new Intl.DateTimeFormat('en-CA', {
|
|
timeZone: moscow,
|
|
year: 'numeric',
|
|
month: '2-digit',
|
|
day: '2-digit',
|
|
});
|
|
export function moscowDate(value: Date): string {
|
|
const parts = moscowFormatter.formatToParts(value);
|
|
const get = (type: string) => parts.find((part) => part.type === type)?.value;
|
|
return `${get('year')}-${get('month')}-${get('day')}`;
|
|
}
|
|
|
|
// Inclusive Moscow calendar dates become a half-open instant range, capped at now.
|
|
export function dateOnlyBounds(
|
|
range: DateOnlyRange,
|
|
now = new Date(),
|
|
): { from: Date; to: Date } {
|
|
const from = dateParts(range.from);
|
|
const end = dateParts(range.to);
|
|
const to = new Date(
|
|
Date.UTC(end[0], end[1] - 1, end[2] + 1, -MOSCOW_UTC_OFFSET_HOURS),
|
|
);
|
|
return {
|
|
from: new Date(
|
|
Date.UTC(from[0], from[1] - 1, from[2], -MOSCOW_UTC_OFFSET_HOURS),
|
|
),
|
|
to: to > now ? now : to,
|
|
};
|
|
}
|
|
|
|
export function dateParts(value: string): [number, number, number] {
|
|
const match = /^(\d{4})-(\d{2})-(\d{2})$/.exec(value);
|
|
if (!match) throw new Error('Invalid date');
|
|
const parts = [Number(match[1]), Number(match[2]), Number(match[3])] as [
|
|
number,
|
|
number,
|
|
number,
|
|
];
|
|
if (utcDate(value).toISOString().slice(0, 10) !== value)
|
|
throw new Error('Invalid date');
|
|
return parts;
|
|
}
|
|
|
|
export function utcDate(value: string): Date {
|
|
const match = /^(\d{4})-(\d{2})-(\d{2})$/.exec(value);
|
|
if (!match) return new Date(NaN);
|
|
return new Date(
|
|
Date.UTC(Number(match[1]), Number(match[2]) - 1, Number(match[3])),
|
|
);
|
|
}
|