深拷贝:
function deepCopyFn(obj1) { var obj2 = Array.isArray(obj1) ? [] : {}; if (obj1 && typeof obj1 === "object") { for (var i in obj1) { var prop = obj1[i]; // 防止互相援用造成死循环,如obj1.a=obj if (prop == obj1) { continue; } if (obj1.hasOwnProperty(i)) { // 如果子属性为援用数据类型,递归复制 if (prop && typeof prop === "object") { obj2[i] = (prop.constructor === Array) ? [] : {}; arguments.callee(prop, obj2[i]); // 递归调用 } else { // 如果是根本数据类型,只是简略的复制 obj2[i] = prop; } } } } return obj2;}
日期工夫:
计算日期:
/** * @param{DateString} -- date_str, 日期字符串,例如: 2019-01-01 * @param{Number} -- day 日期计算,相差多少天。 */function getDateByDiffAndDateFn(date_str, day = 0) { let current_date = date_str ? new Date(date_str).getTime() : new Date().getTime(); let date = new Date(current_date + day * 3600000 * 24), year = date.getFullYear(), month = ("00" + (date.getMonth() + 1)).slice(-2), days = ("00" + date.getDate()).slice(-2); return `${year}-${month}-${days}`;}
判断是否为平年:
/** * 判断是否是平年 * @param{Number} -- year */ function isLeapYear(year) { return year % 4 == 0 && year % 100 != 0 || year % 400 == 0;}
验证字符串是否为日期字符串:
/** * @param{String|Object} -- date 验证字符串是否为 日期字符串 */ function checkDateString(date) { /** * date_str_regexp 匹配 */ let date_str_regexp =/^[0-9]{4}(-[0-9]{2}){2}|(:[0-9]{2}){2}|(\/[0-9]{2}){2}$/; if (!date_str_regexp.test(date)) { console.error("[Error] checkDateString 谬误传参, 请传入正确的日期字符串,例如: '2019-01-01'、'2019:01:01'、2019/01/01'。"); return false; } // let date_str = arg.replace(/:|\//, "-"), let date_arr = date.split(/-|:|\//); let thirty_one = [1, 3, 5, 7, 8, 10, 12], thirty = [4, 6, 9, 11]; switch(true) { case +date_arr[1] > 12 || +date_arr <= 0: console.error("[Error] checkDateString 谬误传参, 月份范畴为 1 ~ 12"); return false; case +date_arr[1] == 2 && isLeapYear(date_arr[0]) && (+date_arr[2] > 29 || +date_arr[2] <= 0): console.error(`[Error] checkDateString 谬误传参, 请填写存在的日期工夫,${date_arr[0]}-${date_arr[1]} 为平年, 日期的抉择范畴为 1 ~ 29`); return false; case +date_arr[1] == 2 && !isLeapYear(date_arr[0]) && (+date_arr[2] > 28 || +date_arr[2] <= 0): console.error(`[Error] checkDateString 谬误传参, 请填写存在的日期工夫,${date_arr[0]}-${date_arr[1]} 为平年, 日期的抉择范畴为 1 ~ 28`); return false; case thirty_one.includes(+date_arr[1]) && (+date_arr[2] > 31 || +date_arr[2] <= 0): console.error(`[Error] checkDateString 谬误传参, 请填写存在的日期工夫,${date_arr[0]}-${date_arr[1]}, 日期的抉择范畴为 1 ~ 31`); return false; case thirty.includes(+date_arr[1]) && (+date_arr[2] > 30 || +date_arr[2] <= 0): console.error(`[Error] checkDateString 谬误传参, 请填写存在的日期工夫,${date_arr[0]}-${date_arr[1]}, 日期的抉择范畴为 1 ~ 30`); return false; default: return true; }}
获取日期所在的周:
/** * 依据日期获取它所在的周的日期范畴 * @param{Object | String} -- arg */ function getWeeksByDate (arg) { let date = new Date(), year = date.getFullYear(), month = ("00" + (date.getMonth() + 1)).slice(-2), days = ("00" + date.getDate()).slice(-2), current_date = `${year}-${month}-${days}`; let default_config = { date: current_date, // 默认为以后日期 start_monday: true, // 是否按星期一为一个星期的开始工夫,默认为true,按星期一 到 星期日, false 就按星期日到星期六 return_all: false // 返回这周所有日期 }; switch(Object.prototype.toString.call(arg)) { // case '[object Date]': break; case '[object Object]': if (arg.date && !checkDateString(arg.date)) { return false; } arg.date = arg.date.replace(/:|\//, "-"); default_config = Object.assign(default_config, arg); break; case '[object String]': if (!checkDateString(arg)) { return false; } default_config.date = arg.replace(/:|\//, "-"); break; default: { console.error("[Error] getWeeksByDate 谬误传参!"); return false; } } let start_num = 0; week_day = new Date(default_config.date).getDay(); if (default_config.start_monday && week_day == 0) { start_num = -6; } else if (default_config.start_monday) { start_num = -week_day + 1; } else { start_num = -week_day; } let start_date = getDateByDiffAndDate(default_config.date, start_num); end_date = getDateByDiffAndDate(start_date, 6); let hebdomad = Array.from({length: 7}, (_item, i) => getDateByDiffAndDate(start_date, i)); let hebdomadWithWeek = hebdomad.map((item) => { let week = new Date(item).getDay(); let weekChinese = ""; switch (week) { case 0: weekChinese = "星期日"; break; case 1: weekChinese = "星期一"; break; case 2: weekChinese = "星期二"; break; case 3: weekChinese = "星期三"; break; case 4: weekChinese = "星期四"; break; case 5: weekChinese = "星期五"; break; case 6: weekChinese = "星期六"; break; } return { date: item, week: weekChinese } }); // 返回后果 let result = { start_date: start_date, end_date: end_date, hebdomad: hebdomad, hebdomadWithWeek: hebdomadWithWeek }; if (default_config.return_all) { result.weeks = [start_date]; for (let i = 1; i < 7; i++) { result.weeks.push(getDateByDiffAndDate(i, start_date)); } } return result;}
获取 输出年份 以及 将来或过来 几年:
/** * @param {string|number} year - example: 2020 * @param {integer} afterNumber - greater than zero and default is three */function getYearArrays (year, afterNumber = 3) { year = parseInt(year); afterNumber = parseInt(afterNumber); let length = Math.abs(afterNumber) + 1; let negative_bool = afterNumber < 0; let years = Array.from({length: length}).map((_item, index) => negative_bool ? year - index : year + index); years.sort(); return years;}
比拟两个日期大小:
/** * 比拟两个日期构造 * gt如果第一个日期晚于第二个日期,则返回 lt,反之亦然。如果两个日期相等,eq 则返回。 * @param {string} date1 - 例如: 2020-10-10 * @param {string} date2 - 例如: 2020-10-10 */Date.prototype.compare = function (date1, date2) { let platform = navigator.platform, regexp = /(iphone|ios)/i; // 如果是 IOS零碎,须要的是UTC格局 if (regexp.test(platform)) { date1 = date1.replace(" ", "T"); date2 = date2.replace(" ", "T"); } let date1_timestamp = new Date(date1).getTime(), date2_timestamp = new Date(date2).getTime(); switch (true) { case date1_timestamp > date2_timestamp: return "gt"; case date1_timestamp < date2_timestamp: return "lt"; default: return "eq"; }}
将获取到week 0 ~ 6 转换成中文:
/** * 把 获取到的星期几 转成 中文 * @param {integer} week - rang/范畴: 0 ~ 6 * @param {string} str - 字符串,拼接在 转换前的字符串 */function replaceWeekToChinese(week, str = "") { switch (week) { case 0: str += "日"; break; case 1: str += "一"; break; case 2: str += "二"; break; case 3: str += "三"; break; case 4: str += "四"; break; case 5: str += "五"; break; case 6: str += "六"; break; default: str = "输出谬误"; break; } return str;}
主观逻辑工具函数:
上面的工具函数, 具备主观逻辑性,定的规定解决,不肯定适宜使用者,请审慎应用
计算岁数 / 孕周
/** * 全局 的定义工夫 比照办法 date1 比照 date2 的 */Date.prototype.diff = function (date1, date2) { let date1_timestamp = new Date(date1).getTime(), date2_timestamp = new Date(date2).getTime(); let diff_days = (date1_timestamp - date2_timestamp) / (3600000 * 24); return parseInt(diff_days);}// 比拟两个日期构造// gt如果第一个日期晚于第二个日期,则返回 lt,反之亦然。如果两个日期相等,eq 则返回。Date.prototype.compare = function (date1, date2) { let platform = navigator.platform, regexp = /(iphone|ios)/i; // 如果是 IOS零碎,须要的是UTC格局 if (regexp.test(platform)) { date1 = date1.replace(" ", "T"); date2 = date2.replace(" ", "T"); } let date1_timestamp = new Date(date1).getTime(), date2_timestamp = new Date(date2).getTime(); switch (true) { case date1_timestamp > date2_timestamp: return "gt"; case date1_timestamp < date2_timestamp: return "lt"; default: return "eq"; }}/** * 获取 零碎以后日期 * @param {integer} day - 默认为 0 就是以后日期, * 如果是 负数,就是明天的后几天 * 如果是 正数,就是明天的前几天 */function getDate(day = 0) { let current_date = new Date().getTime(); let date = new Date(current_date + day * 3600000 * 24); let year = date.getFullYear(); let month = ("00" + (date.getMonth() + 1)).slice(-2); let days = ("00" + date.getDate()).slice(-2); return `${year}-${month}-${days}`;}/** * 通过日期 计算日期 * @param {integer} day - 计算数, 正负整数 * @param {string} date - 日期,默认是明天 格局:2019-01-01 */function calcDateByNum(day, date = getDate()) { if ([undefined, null].includes(day)) { console.error("[error] utils.js calcDateByNum 的 num 不能为空!"); return; } let temp = new Date(date).getTime(); let new_date = new Date(temp + day * 3600000 * 24); let year = new_date.getFullYear(); let month = ("00" + (new_date.getMonth() + 1)).slice(-2); let days = ("00" + new_date.getDate()).slice(-2); return `${year}-${month}-${days}`;}/** * 计算月龄,返回 几个月零几天,例如:12.30 - 12个月30日 * @param {String} birthday 出生日期 * @param {String} otherday 其余日期(默认是 明天) */function calculateAgeByDate(birthday, otherday = getDate()) { otherday = calcDateByNum(1, otherday); let birthday_arr = birthday.split("-"), otherday_arr = otherday.split("-"); let date_compare = new Date().compare(otherday, birthday); switch (date_compare) { case "gt": let months = 12 * (otherday_arr[0] - birthday_arr[0]) + (otherday_arr[1] - birthday_arr[1]); /** * 1、如果 otherdays_arr[2] > birthday_arr[2],那就是曾经满了一个月了,还多进去多少天,用 otherdays_arr[2] - birthday_arr[2] 取得。 * * 2、otherdays_arr[2] == birthday_arr[2] 那就刚刚好满一个月。days 为 0 */ if (otherday_arr[2] > birthday_arr[2]) { days = otherday_arr[2] - birthday_arr[2]; } else if (otherday_arr[2] < birthday_arr[2]) { /** * otherdays_arr[2] < birthday_arr[2] 有上面的状况 * 1、otherdays_arr[2] 和 birthday_arr[2] 都是那个月的最初一天。咱们认为是刚好满一个月。 * 例如:生日是 31 以后是 30 * * 2、birthday_arr[2] 是那个月的最初一天, 并且otherdays 上一个月的总天数小于 birthday_arr[2], * days等于 otherdays_arr[2]), * 例如:生日是 31 以后的上一个月最初一天是 28 * * 3、其余状况,都是计算 birthday_arr[2] 到 otherdays 上一个月的总天数 差 加上 otherdays_arr[2] * 例如: * calc_age("2006-02-28", "2008-02-29") 输入 2岁1天 * calc_age("2006-02-28", "2008-03-01") 输入 2岁2天 * 因为 2006 是平年,2月只有28天,2008是平年,最初一天是29. */ let last_days = new Date(otherday_arr[0], otherday_arr[1], 0).getDate(); let last_month_last_days = new Date(otherday_arr[0], otherday_arr[1] - 1, 0).getDate(); let is_birthday_last_days = new Date(birthday_arr[0], birthday_arr[1], 0).getDate() == parseInt(birthday_arr[2]); let is_otherday_last_days = last_days == parseInt(otherday_arr[2]); let compare_days = parseInt(birthday_arr[2]); if (is_birthday_last_days && is_otherday_last_days) { days = "00"; } else if (is_birthday_last_days && parseInt(birthday_arr[2]) > last_days) { months -= 1; days = parseInt(otherday_arr[2]); } else { months -= 1; days = last_month_last_days - parseInt(birthday_arr[2]) + parseInt(otherday_arr[2]); } } else { days = "00"; } return `${months}.${('0' + days).slice(-2)}`; case "eq": return 0; default: return -1; console.error("&1 不能小于 &2"); }}/** * 计算 出生日期 到 比照日期 的岁数 * 出生日期要 少于等于 比照日期 * @param {String} birthdays - 出生日期 * @param {String} otherday - 比照日期 默认是明天 * @returns {String} 例如: 1岁2月3天 */function calculateAgeString(birthdays, otherday = getDate()) { let age = calculateAgeByDate(birthdays, otherday); if (age == 0) { return `0天`; } let age_months = new String(age).split(".")[0], age_days = new String(age).split(".")[1]; let year = parseInt(age_months / 12), months = parseInt(age_months % 12), days = parseInt(age_days); let year_str = `${year}岁`, months_str = `${months}个月`, days_str = `${days}天`; if (!year) { year_str = ""; } if (!months) { months_str = ""; } if (!days) { days_str = ""; } return year_str + months_str + days_str;}/** * 反推计算以后怀孕的天数 * @param {String} birthday - 预产期 */function calculateGestationalDays(birthday, now = getDate()) { let diff_days = new Date().diff(birthday, now); let total_days = 40 * 7; switch (true) { case diff_days > 0: return { gestational_days: total_days - diff_days, progress_percent: (total_days - diff_days) / total_days * 100 }; case diff_days == 0: return { gestational_days: total_days, progress_percent: 100 }; default: return { gestational_days: total_days - diff_days, progress_percent: 100 }; }}/** * 把反推的怀孕多少天。转成文字版 * @param {Integer} gestational_days - 怀孕多少天 * */function getGestationalShow(gestational_days) { let week = Math.floor(gestational_days / 7), days = gestational_days % 7; switch (true) { case week == 0: return `${days}天`; case days == 0: return `${week}周`; default: return `${week}周${days}天`; }}/** * 获取以后工夫,替换问候语 * */function getGeetings() { let date = new Date(); let txt = ""; let hour = date.getHours(); switch (true) { case hour >= 6 && hour < 12: txt = "上午好"; break; case hour >= 12 && hour < 18: txt = "下午好"; break; default: txt = "早晨好"; } return txt;}