/** * 日期时间工具类。 * * 说明: * - 页面只需要展示日期时,统一使用这里的方法,避免每个页面重复处理格式。 * - 后端常见日期格式为 `YYYY-MM-DD` 或 `YYYY-MM-DD HH:mm:ss`。 * - 纯日期字符串用本地时区解析,避免浏览器按 UTC 解析导致日期偏移。 */ class DateUtil { /** * 转为“5月9日”格式。 * * @param {string|Date} dateStr 后端时间字符串或 Date 对象 * @returns {string} */ static formatDateToMonthDay(dateStr) { try { // 第一步:把传入的字符串或 Date 对象统一转成 Date。 const date = DateUtil._parseDate(dateStr); // 第二步:无效日期直接返回空字符串,页面不显示错误内容。 if (!DateUtil._isValidDate(date)) { return ''; } // 第三步:取月份和日期,拼接成中文展示格式。 const month = date.getMonth() + 1; const day = date.getDate(); return `${month}月${day}日`; } catch (error) { return ''; } } /** * 转为“2026年5月9日”格式。 * * @param {string|Date} dateStr 后端时间字符串或 Date 对象 * @returns {string} */ static formatDateToYearMonthDay(dateStr) { try { // 第一步:统一解析日期。 const date = DateUtil._parseDate(dateStr); // 第二步:无效日期不继续格式化。 if (!DateUtil._isValidDate(date)) { return ''; } // 第三步:分别取年月日,拼成完整中文日期。 const year = date.getFullYear(); const month = date.getMonth() + 1; const day = date.getDate(); return `${year}年${month}月${day}日`; } catch (error) { return ''; } } /** * 转为“YYYY-MM-DD”格式,适合列表右侧日期展示。 * * @param {string|Date} dateStr 后端时间字符串或 Date 对象 * @returns {string} */ static formatDateToYMD(dateStr) { try { // 第一步:统一解析日期。 const date = DateUtil._parseDate(dateStr); // 第二步:无效日期返回空字符串。 if (!DateUtil._isValidDate(date)) { return ''; } // 第三步:月份和日期补零,保证列表展示宽度稳定。 const year = date.getFullYear(); const month = String(date.getMonth() + 1).padStart(2, '0'); const day = String(date.getDate()).padStart(2, '0'); return `${year}-${month}-${day}`; } catch (error) { return ''; } } /** * 转为“YYYY-MM-DD HH:mm:ss”格式,适合资金流水、订单时间等完整时间展示。 * * @param {string|Date} dateStr 后端时间字符串或 Date 对象 * @returns {string} */ static formatDateTimeToYMDHMS(dateStr) { try { // 第一步:统一解析日期。 const date = DateUtil._parseDate(dateStr); // 第二步:无效日期返回空字符串,避免页面显示 Invalid Date。 if (!DateUtil._isValidDate(date)) { return ''; } // 第三步:分别补齐年月日时分秒,保证表格宽度稳定。 const year = date.getFullYear(); const month = String(date.getMonth() + 1).padStart(2, '0'); const day = String(date.getDate()).padStart(2, '0'); const hour = String(date.getHours()).padStart(2, '0'); const minute = String(date.getMinutes()).padStart(2, '0'); const second = String(date.getSeconds()).padStart(2, '0'); // 第四步:拼接成后端和页面都常用的完整时间格式。 return `${year}-${month}-${day} ${hour}:${minute}:${second}`; } catch (error) { return ''; } } /** * 转为“HH:mm:ss”格式,适合日志或轮询状态时间展示。 * * @param {string|number|Date} dateStr 后端时间、时间戳或 Date 对象 * @returns {string} */ /** * 转为“YYYY-MM-DD HH:mm”格式,适合评论发布时间等不需要精确到秒的场景。 * * @param {string|Date} dateStr 后端时间字符串或 Date 对象 * @returns {string} */ static formatDateTimeToYMDHM(dateStr) { try { // 第一步:统一解析传入的时间。 const date = DateUtil._parseDate(dateStr); // 第二步:无效时间返回空字符串,避免页面显示 Invalid Date。 if (!DateUtil._isValidDate(date)) { return ''; } // 第三步:只补齐到分钟,不展示秒。 const year = date.getFullYear(); const month = String(date.getMonth() + 1).padStart(2, '0'); const day = String(date.getDate()).padStart(2, '0'); const hour = String(date.getHours()).padStart(2, '0'); const minute = String(date.getMinutes()).padStart(2, '0'); return `${year}-${month}-${day} ${hour}:${minute}`; } catch (error) { return ''; } } static formatTimeToHMS(dateStr) { try { // 第一步:时间戳直接转 Date,字符串和 Date 继续走统一解析。 const date = typeof dateStr === 'number' ? new Date(dateStr) : DateUtil._parseDate(dateStr); // 第二步:无效时间返回空字符串。 if (!DateUtil._isValidDate(date)) { return ''; } // 第三步:补齐时分秒,保持展示稳定。 const hour = String(date.getHours()).padStart(2, '0'); const minute = String(date.getMinutes()).padStart(2, '0'); const second = String(date.getSeconds()).padStart(2, '0'); return `${hour}:${minute}:${second}`; } catch (error) { return ''; } } /** * 获取当前时间。 * * @returns {Date} */ static getCurrentDate() { return new Date(); } /** * 判断两个日期是否为同一天。 * * @param {string|Date} date1 第一个日期 * @param {string|Date} date2 第二个日期 * @returns {boolean} */ static isSameDay(date1, date2) { try { // 第一步:两个入参都先转成 Date。 const d1 = DateUtil._parseDate(date1); const d2 = DateUtil._parseDate(date2); // 第二步:任意一个日期无效,就判定不是同一天。 if (!DateUtil._isValidDate(d1) || !DateUtil._isValidDate(d2)) { return false; } // 第三步:同时比较年、月、日。 return d1.getFullYear() === d2.getFullYear() && d1.getMonth() === d2.getMonth() && d1.getDate() === d2.getDate(); } catch (error) { return false; } } /** * 统一解析日期。 * * @param {string|Date} dateStr 日期字符串或 Date 对象 * @returns {Date|null} */ static _parseDate(dateStr) { // 第一步:如果已经是 Date 对象,直接返回。 if (dateStr instanceof Date) { return dateStr; } // 第二步:非字符串不尝试解析。 if (typeof dateStr !== 'string') { return null; } // 第三步:去掉首尾空格,兼容接口偶发空白。 const value = dateStr.trim(); if (!value) { return null; } // 第四步:纯日期用斜杠格式解析,避免浏览器按 UTC 导致日期前后偏移。 if (/^\d{4}-\d{2}-\d{2}$/.test(value)) { return new Date(value.replace(/-/g, '/')); } // 第五步:带时间的字符串交给浏览器 Date 解析。 return new Date(value); } /** * 判断 Date 对象是否有效。 * * @param {Date|null} date 日期对象 * @returns {boolean} */ static _isValidDate(date) { return date instanceof Date && !Number.isNaN(date.getTime()); } } if (typeof module !== 'undefined' && module.exports) { module.exports = DateUtil; } else if (typeof window !== 'undefined') { window.DateUtil = DateUtil; }