57 lines
2.3 KiB
TypeScript
57 lines
2.3 KiB
TypeScript
import type { Timeframe } from '../types';
|
||
|
||
export function normalizeChartTimeframe(raw: string | undefined): Timeframe {
|
||
const t = (raw ?? '1h').trim();
|
||
const lower = t.toLowerCase();
|
||
if (lower === '1d') return '1D';
|
||
if (lower === '1w') return '1W';
|
||
if (lower === '1m' && t === '1M') return '1M';
|
||
if (['1m', '3m', '5m', '10m', '15m', '30m', '1h', '4h'].includes(lower)) return lower as Timeframe;
|
||
if (t === '1D' || t === '1W' || t === '1M') return t as Timeframe;
|
||
return '1h';
|
||
}
|
||
|
||
/** Unix epoch → 초 단위 정규화 (유효하지 않으면 0) */
|
||
export function normalizeEpochSecOptional(t: number | undefined | null): number {
|
||
if (t == null || !Number.isFinite(t) || t <= 0) return 0;
|
||
return t > 1e12 ? Math.floor(t / 1000) : Math.floor(t);
|
||
}
|
||
|
||
/** Unix epoch → 초 단위 정규화 (유효하지 않으면 현재 시각) */
|
||
export function normalizeEpochSec(t: number | undefined | null): number {
|
||
const v = normalizeEpochSecOptional(t);
|
||
return v > 0 ? v : Math.floor(Date.now() / 1000);
|
||
}
|
||
|
||
export function fmtListTimestamp(iso: string): string {
|
||
const d = new Date(iso);
|
||
if (Number.isNaN(d.getTime())) return iso;
|
||
return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')} ${String(d.getHours()).padStart(2, '0')}:${String(d.getMinutes()).padStart(2, '0')}`;
|
||
}
|
||
|
||
export function fmtShortTimestamp(iso: string): string {
|
||
const d = new Date(iso);
|
||
if (Number.isNaN(d.getTime())) return iso;
|
||
const yy = String(d.getFullYear()).slice(2);
|
||
return `${yy}.${String(d.getMonth() + 1).padStart(2, '0')}.${String(d.getDate()).padStart(2, '0')} ${String(d.getHours()).padStart(2, '0')}:${String(d.getMinutes()).padStart(2, '0')}`;
|
||
}
|
||
|
||
export const pct = (v: number, dec = 1) =>
|
||
isFinite(v) && v !== 0 ? `${v >= 0 ? '+' : ''}${(v * 100).toFixed(dec)}%` : '0.0%';
|
||
|
||
export const pctAbs = (v: number, dec = 0) =>
|
||
isFinite(v) ? `${(v * 100).toFixed(dec)}%` : '0%';
|
||
|
||
export const krw = (v: number) =>
|
||
isFinite(v) ? `${v >= 0 ? '+' : ''}₩${Math.round(v).toLocaleString()}` : '–';
|
||
|
||
const TF_SEC: Record<string, number> = {
|
||
'1m': 60, '3m': 180, '5m': 300, '10m': 600, '15m': 900, '30m': 1800,
|
||
'1h': 3600, '4h': 14400, '1D': 86400, '1W': 604800, '1M': 2592000,
|
||
};
|
||
|
||
export function timeframeBarSeconds(tf: string): number {
|
||
const n = normalizeChartTimeframe(tf);
|
||
return TF_SEC[n] ?? 3600;
|
||
}
|