198 lines
6.4 KiB
JavaScript
198 lines
6.4 KiB
JavaScript
|
|
// 工具函数:格式化日期
|
|||
|
|
// 参数:
|
|||
|
|
// - date: 可传入 时间戳(毫秒)、Date对象、日期字符串(如 "2024-09-12")
|
|||
|
|
// - format: 格式化模板(默认 "YYYY-MM-DD")
|
|||
|
|
function formatDate(date, format = "YYYY-MM-DD") {
|
|||
|
|
// 处理输入:统一转为 Date 对象
|
|||
|
|
if (!date) {
|
|||
|
|
date = new Date(); // 默认当前时间
|
|||
|
|
} else if (typeof date === "number") {
|
|||
|
|
date = new Date(date); // 时间戳转 Date
|
|||
|
|
} else if (typeof date === "string") {
|
|||
|
|
date = new Date(date); // 日期字符串转 Date
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 处理无效日期
|
|||
|
|
if (isNaN(date.getTime())) {
|
|||
|
|
console.error("无效的日期格式");
|
|||
|
|
return "";
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 提取日期部分
|
|||
|
|
const year = date.getFullYear();
|
|||
|
|
const month = date.getMonth() + 1; // 月份从 0 开始,需 +1
|
|||
|
|
const day = date.getDate();
|
|||
|
|
const hour = date.getHours();
|
|||
|
|
const minute = date.getMinutes();
|
|||
|
|
const second = date.getSeconds();
|
|||
|
|
|
|||
|
|
// 补零函数(将 1 转为 "01")
|
|||
|
|
const padZero = (num) => String(num).padStart(2, "0");
|
|||
|
|
|
|||
|
|
// 替换格式模板
|
|||
|
|
return format
|
|||
|
|
.replace("YYYY", year)
|
|||
|
|
.replace("MM", padZero(month))
|
|||
|
|
.replace("DD", padZero(day))
|
|||
|
|
.replace("HH", padZero(hour))
|
|||
|
|
.replace("mm", padZero(minute))
|
|||
|
|
.replace("ss", padZero(second));
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 计算n年前的日期
|
|||
|
|
* @param {number} n - 年前数(如1表示1年前,2表示2年前)
|
|||
|
|
* @param {Date|number|string} [baseDate] - 基准日期(可选,默认当前日期)
|
|||
|
|
* @returns {Date} 计算后的Date对象
|
|||
|
|
*/
|
|||
|
|
function getNYearsAgo(n, baseDate) {
|
|||
|
|
// 处理基准日期(默认当前日期)
|
|||
|
|
let date;
|
|||
|
|
if (!baseDate) {
|
|||
|
|
date = new Date(); // 默认以今天为基准
|
|||
|
|
} else if (typeof baseDate === 'number') {
|
|||
|
|
date = new Date(baseDate); // 时间戳转Date
|
|||
|
|
} else if (typeof baseDate === 'string') {
|
|||
|
|
date = new Date(baseDate); // 日期字符串转Date
|
|||
|
|
} else {
|
|||
|
|
date = new Date(baseDate); // 传入Date对象
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 校验日期有效性
|
|||
|
|
if (isNaN(date.getTime())) {
|
|||
|
|
console.error('无效的基准日期');
|
|||
|
|
return null;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 获取基准日期的年、月、日
|
|||
|
|
const year = date.getFullYear();
|
|||
|
|
const month = date.getMonth(); // 月份从0开始(0=1月,11=12月)
|
|||
|
|
const day = date.getDate();
|
|||
|
|
|
|||
|
|
// 计算n年前的年份
|
|||
|
|
const targetYear = year - n;
|
|||
|
|
// 创建目标日期(直接设置年份)
|
|||
|
|
const targetDate = new Date(targetYear, month, day);
|
|||
|
|
|
|||
|
|
// 特殊情况处理:如果目标日期的月份与原月份不一致(如2月29日跨年到非闰年)
|
|||
|
|
if (targetDate.getMonth() !== month) {
|
|||
|
|
// 说明原日期在目标年份中不存在(如2024-02-29 → 2023年没有2月29日)
|
|||
|
|
// 自动调整为目标月份的最后一天
|
|||
|
|
targetDate.setDate(0); // setDate(0) 表示上个月的最后一天
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return targetDate;
|
|||
|
|
}
|
|||
|
|
/**
|
|||
|
|
* 根据出生日期计算年龄
|
|||
|
|
* @param {string|Date} birthDate - 出生日期(支持字符串如"1990-05-15"或Date对象)
|
|||
|
|
* @returns {number} 年龄(如28),若日期无效则返回-1
|
|||
|
|
*/
|
|||
|
|
function calculateAge(birthDate) {
|
|||
|
|
// 处理出生日期输入(转为Date对象)
|
|||
|
|
let birth;
|
|||
|
|
if (birthDate instanceof Date) {
|
|||
|
|
birth = birthDate;
|
|||
|
|
} else if (typeof birthDate === 'string') {
|
|||
|
|
birth = new Date(birthDate);
|
|||
|
|
} else {
|
|||
|
|
console.error('出生日期格式错误');
|
|||
|
|
return -1;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 校验出生日期有效性
|
|||
|
|
if (isNaN(birth.getTime())) {
|
|||
|
|
console.error('无效的出生日期');
|
|||
|
|
return -1;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 获取当前日期和出生日期的年/月/日
|
|||
|
|
const today = new Date();
|
|||
|
|
const birthYear = birth.getFullYear();
|
|||
|
|
const birthMonth = birth.getMonth(); // 月份从0开始(0=1月)
|
|||
|
|
const birthDay = birth.getDate();
|
|||
|
|
|
|||
|
|
const currentYear = today.getFullYear();
|
|||
|
|
const currentMonth = today.getMonth();
|
|||
|
|
const currentDay = today.getDate();
|
|||
|
|
|
|||
|
|
// 计算年份差(初步年龄)
|
|||
|
|
let age = currentYear - birthYear;
|
|||
|
|
|
|||
|
|
// 调整年龄:若今年生日尚未过,则年龄减1
|
|||
|
|
if (
|
|||
|
|
currentMonth < birthMonth || // 当前月份 < 出生月份 → 生日未过
|
|||
|
|
(currentMonth === birthMonth && currentDay < birthDay) // 同月份但当前日期 < 出生日期 → 生日未过
|
|||
|
|
) {
|
|||
|
|
age--;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 年龄不能为负数(如出生日期在未来)
|
|||
|
|
return age < 0 ? 0 : age;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 根据生日计算星座
|
|||
|
|
* @param {number|string} month - 月份(1-12)
|
|||
|
|
* @param {number|string} day - 日期(1-31)
|
|||
|
|
* @returns {string} 星座名称,如"白羊座"、"金牛座"等
|
|||
|
|
*/
|
|||
|
|
function calculateConstellation(month, day) {
|
|||
|
|
// 确保 month 和 day 是数字类型
|
|||
|
|
const m = typeof month === 'string' ? parseInt(month, 10) : month;
|
|||
|
|
const d = typeof day === 'string' ? parseInt(day, 10) : day;
|
|||
|
|
|
|||
|
|
// 验证输入
|
|||
|
|
if (!m || !d || m < 1 || m > 12 || d < 1 || d > 31) {
|
|||
|
|
return '';
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 根据月份和日期判断星座
|
|||
|
|
if ((m === 3 && d >= 21) || (m === 4 && d <= 19)) return "白羊座";
|
|||
|
|
if ((m === 4 && d >= 20) || (m === 5 && d <= 20)) return "金牛座";
|
|||
|
|
if ((m === 5 && d >= 21) || (m === 6 && d <= 21)) return "双子座";
|
|||
|
|
if ((m === 6 && d >= 22) || (m === 7 && d <= 22)) return "巨蟹座";
|
|||
|
|
if ((m === 7 && d >= 23) || (m === 8 && d <= 22)) return "狮子座";
|
|||
|
|
if ((m === 8 && d >= 23) || (m === 9 && d <= 22)) return "处女座";
|
|||
|
|
if ((m === 9 && d >= 23) || (m === 10 && d <= 23)) return "天秤座";
|
|||
|
|
if ((m === 10 && d >= 24) || (m === 11 && d <= 22)) return "天蝎座";
|
|||
|
|
if ((m === 11 && d >= 23) || (m === 12 && d <= 21)) return "射手座";
|
|||
|
|
if ((m === 12 && d >= 22) || (m === 1 && d <= 19)) return "摩羯座";
|
|||
|
|
if ((m === 1 && d >= 20) || (m === 2 && d <= 18)) return "水瓶座";
|
|||
|
|
return "双鱼座";
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 根据生日字符串计算星座
|
|||
|
|
* @param {string} birthday - 生日字符串,格式:YYYY-MM-DD
|
|||
|
|
* @returns {string} 星座名称,如"白羊座"、"金牛座"等
|
|||
|
|
*/
|
|||
|
|
function calculateConstellationFromBirthday(birthday) {
|
|||
|
|
if (!birthday || typeof birthday !== 'string') {
|
|||
|
|
return '';
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
try {
|
|||
|
|
const parts = birthday.split('-');
|
|||
|
|
if (parts.length !== 3) {
|
|||
|
|
return '';
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
const month = parseInt(parts[1], 10);
|
|||
|
|
const day = parseInt(parts[2], 10);
|
|||
|
|
|
|||
|
|
return calculateConstellation(month, day);
|
|||
|
|
} catch (error) {
|
|||
|
|
console.error('计算星座失败:', error);
|
|||
|
|
return '';
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
module.exports = {
|
|||
|
|
formatDate: formatDate,
|
|||
|
|
getNYearsAgo: getNYearsAgo,
|
|||
|
|
calculateAge: calculateAge,
|
|||
|
|
calculateConstellation: calculateConstellation,
|
|||
|
|
calculateConstellationFromBirthday: calculateConstellationFromBirthday
|
|||
|
|
}
|