UNPKG

node-dateutils

Version:
313 lines (287 loc) 10.4 kB
const moment = require('moment'); const self = module.exports = { _depends: { moment: moment, }, _periodTypes: ["day", "week", "month", "year", "history"], fmt: { ts: (date) => moment(date).format('YYYY-MM-DD HH:mm:ss.SSS'), date: (date) => moment(date).format("YYYY-MM-DD"), day: (date) => moment(date).format("YYYY-MM-DD"), week: (date) => moment(date).format("GGGG-[W]WW"), month: (date) => moment(date).format("YYYY-MM"), year: (date) => moment(date).format("YYYY"), }, k_fmt: { // query: <dict> format query to period key <string:key> // 所有函数的 query 参数都要严格按照对应 key 的参数 // date: 'yyyy-mm-dd' day: (query) => `${query.date}`, week: (query) => { // 统一使用格式 'GGGG-[W]WW', 注意星期一是一周的第一天; // 注意 moment('${GGGG-[W]WW]}', "GGGG-[W]WW").day(1).isSame(moment('${GGGG-[W]WW]}', "GGGG-[W]WW")) if (query.Date) { return moment(query.Date).format('GGGG-[W]WW'); } else { return `${query.year}-W${String(query.week).trim().padStart(2, "0")}`; } }, month: (query) => `${query.year}-${String(query.month).trim().padStart(2, "0")}`, year: (query) => String(query.year).trim(), history: () => 'history', }, k_parse: { // key: <string> parse period_key to <dict:query> day: (key) => { let {date} = self.queryDate(key); return {date} }, week: (key) => { let [year, week] = key.split('-W').map(m => parseInt(m)); return {year, week} }, month: (key) => { let [year, month] = key.split('-').map(m => parseInt(m)); return {year, month} }, year: (key) => { return {year: parseInt(key)} }, history: () => { return {} }, }, formPeriod: (query) => { // 解析接口的 query 有两种方案 // A: {period, key} = query; // B:{date, week, month, year} = query; const {period, key} = query; if (period && key) { const query = self.k_parse[period](key); return {period, query, key} } else { return self.queryPeriod(query); } }, queryPeriod: function (form) { // return queryObject: {date, month, year, week} let int_args = ["week", "month", "year"]; let ints = new Set(int_args); let query = {}; let period = self.fetchPeriod(query); for (let attr in form) { let v = form[attr]; if (attr === "date") { let dt = self.queryDate(v); query[attr] = dt.date; } else { if (ints.has(attr)) { query[attr] = parseInt(v); } } } let key = self.k_fmt[period](query); return {query, period, key} }, queryDate: (...argsOfDate) => { const dt = new Date(...argsOfDate); const year = dt.getFullYear(); const month = dt.getMonth() + 1; const day = dt.getDate(); const week = parseInt(moment(dt.getTime()).format('W')); // date: 'yyyy-mm-dd' const date = `${year}-${month.toString().padStart(2, "0")}-${day.toString().padStart(2, "0")}`; return {year, month, day, week, date, Date: dt} }, fetchPeriod: function (query) { // return: day, month, week, year, history let {date, month, year, week} = query; let period; if (date) { period = "day"; } else { if (month && year) { period = "month"; } else { if (week && year) { period = "week"; } else { if (year) { period = "year"; } else { period = "history"; } } } } return period }, lastPeriod: { day: (query, days = 1) => { const ts = new Date(query.date).getTime(); const td = 1000 * 60 * 60 * 24 * days; const {date} = self.queryDate(ts - td); return {date} }, week: (query) => { const yw = self.k_fmt.week(query); // 上周一, -6: 上周的第一天 const d0 = moment(yw, "GGGG-[W]WW").day(-6); const year = d0.format('GGGG'); const week = d0.format('W'); return {year, week} }, month: (query) => { let year, month; if (query.month === 1) { month = 12; year = query.year - 1; } else { month = query.month - 1; year = query.year; } return {year, month} }, year: (query) => { let year = query.year - 1; return {year}; }, }, lastPeriodString: (period, string) => { const q = self.k_parse[period](string); const pq = self.lastPeriod[period](q); return self.k_fmt[period](pq); }, nextPeriod: { day: (query, days = 1) => { const ts = new Date(query.date).getTime(); const td = 1000 * 60 * 60 * 24 * days; const {date} = self.queryDate(ts + td); return {date} }, week: (query) => { // 下周一, +8: 下周的第一天; day(0) 为以周天算一个星期的第一天的星期天 const yw = self.k_fmt.week(query); const d0 = moment(yw, "GGGG-[W]WW").day(8); const year = d0.format('GGGG'); const week = d0.format('W'); return {year, week} }, month: (query) => { let year, month; if (query.month === 12) { month = 1; year = query.year + 1; } else { month = query.month + 1; year = query.year; } return {year, month} }, year: (query) => { const year = query.year + 1; return {year} } }, nextPeriodString: (period, string) => { const q = self.k_parse[period](string); const pq = self.nextPeriod[period](q); return self.k_fmt[period](pq); }, nextDay: (date, days = 1) => self.nextPeriod.day({date}, days).date, lastDay: (date, days = 1) => self.lastPeriod.day({date}, days).date, lastWeekString: (dt) => self.lastPeriodString("week", dt), lastMonthString: (dt) => self.lastPeriodString("month", dt), nextWeekString: (week_string) => moment(week_string, "GGGG-[W]WW").day(8).format("GGGG-[W]WW"), nextMonthString: (month_string) => self.nextPeriodString("month", month_string), periodScope: { day: (key) => { // start = moment(key, "YYYY-MM-DD").startOf('day'); const start = moment(key, "YYYY-MM-DD"); const end = moment(key, "YYYY-MM-DD").endOf('day'); return {start, end}; }, week: (key) => { // 这周一 , 等同于 moment(key, "GGGG-[W]WW"); const start = moment(key, "GGGG-[W]WW").day(1); // 这周日, endOf('week') 返回的是周六,不符合业务需求 const end = moment(key, "GGGG-[W]WW").day(7).endOf('day'); return {start, end}; }, month: (key) => { const start = moment(key, "YYYY-MM").local(); const end = moment(key, "YYYY-MM").endOf('month'); return {start, end}; }, year: (key) => { const start = moment(key, "YYYY").local(); const end = moment(key, "YYYY").endOf('year'); return {start, end}; }, }, periodScopeTs: (period, key) => { const func = self.periodScope[period]; if (func) { const {start, end} = func(key); const start_ts = start.valueOf(); const end_ts = end.valueOf(); return {start_ts, end_ts}; } }, periodScopeDate: (period, key) => { const func = self.periodScope[period]; if (func) { const {start, end} = func(key); const start_date = start.format('YYYY-MM-DD'); const end_date = end.format('YYYY-MM-DD'); return {start_date, end_date}; } }, periodDates: (period, key) => { const func = self.periodScope[period]; if (func) { const {start, end} = func(key); const t0 = start.valueOf(); const t1 = end.valueOf(); const ary = self.breakTimePoints(t0, t1); const ds = ary.map(ts => moment(ts).format('YYYY-MM-DD')); return ds; } }, scope180d: (expired_date) => { const ts = new Date(expired_date).getTime(); const end_date = self.lastDay(expired_date); const start_ts = ts - 180 * 1000 * 60 * 60 * 24; const start_date = self.queryDate(start_ts).date; return {ts, start_date, end_date} }, rangeDates: (start_date, end_date) => { const start = moment(start_date, 'YYYY-MM-DD').valueOf(); const end = moment(end_date, 'YYYY-MM-DD').valueOf(); const ary = self.breakTimePoints(start, end); const ds = ary.map(ts => moment(ts).format('YYYY-MM-DD')); return ds; }, breakTimePoints: (start_ts, end_ts, step = 24 * 60 * 60 * 1000) => { // step: milliseconds , the default is 1 day const ary = []; for (let ts = start_ts; ts <= end_ts; ts += step) { ary.push(ts); } return ary; }, timeOffset: (ts, offset = 0, round = 1000) => { return ts - ts % round + offset; }, lastHour: (ts) => { // 整点 const date = new Date(ts); const hour = date.getHours(); const secs = date.getSeconds(); if (secs === 0) { return (hour - 1 + 24) % 24 } else { return hour; } }, };