(function () { 'use strict'; var PRESETS = [ 'today', 'yesterday', 'last_7_days', 'last_30_days', 'this_month', 'last_month', 'custom', ]; function pad(value) { return String(value).padStart(2, '0'); } function dateText(date) { return ( date.getFullYear() + '-' + pad(date.getMonth() + 1) + '-' + pad(date.getDate()) ); } function localDate(value) { if (value instanceof Date) { return new Date( value.getFullYear(), value.getMonth(), value.getDate() ); } var match = String(value || '').match(/^(\d{4})-(\d{2})-(\d{2})$/); if (!match) return null; var date = new Date( Number(match[1]), Number(match[2]) - 1, Number(match[3]) ); return Number.isNaN(date.getTime()) ? null : date; } function addDays(date, count) { return new Date( date.getFullYear(), date.getMonth(), date.getDate() + count ); } function createRange(preset, options) { var name = PRESETS.indexOf(preset) >= 0 ? preset : 'today'; var opts = options || {}; var now = localDate(opts.now || new Date()); var start = now; var end = now; if (name === 'yesterday') start = end = addDays(now, -1); else if (name === 'last_7_days') start = addDays(now, -6); else if (name === 'last_30_days') start = addDays(now, -29); else if (name === 'this_month') start = new Date(now.getFullYear(), now.getMonth(), 1); else if (name === 'last_month') { start = new Date(now.getFullYear(), now.getMonth() - 1, 1); end = new Date(now.getFullYear(), now.getMonth(), 0); } else if (name === 'custom') { start = localDate(opts.start); end = localDate(opts.end); if (!start || !end || start.getTime() > end.getTime()) { throw new Error('Invalid custom date range'); } } // UI 和 API 都使用包含首尾的自然日;在线时长等跨日指标由服务端按业务时区切日,前端不自行累计秒数。 return Object.freeze({ preset: name, startDate: dateText(start), endDate: dateText(end), }); } window.HyGuild = window.HyGuild || {}; window.HyGuild.dateRange = { presets: Object.freeze(PRESETS.slice()), create: createRange, }; })();