🚀 手写方法 - 时间间隔精确计算处理

1,030 阅读3分钟

生活不止眼前的苟且,还有诗和远方

前言

大家好我是前端奶爸,入行4年的前端小学生,每天工作八小时摸鱼4小时

工作中很多时候会遇到跟时间相关的一些业务逻辑处理,比如说获取倒计时、时间格式化,业务需求中也会有一些和时间相关的处理,获取入职时间,入职时间天数换算入职年数等操作,下边的一些方法的封装可以解决日期相关的问题处理,节省其他伙伴的开发时间。

接收参数

  • 开始时间
  • 结束时间
  • 返回差值具体的单位 - 可选值("y" 、"M"、"d"、"h"、"m"、"s")

具体代码

/**
 * 计算两个日期时间相差的年数、月数、天数、小时数、分钟数、秒数
 * DIFFTIME(开始时间,结束时间,[单位]),单位可以是 "y" 、"M"、"d"、"h"、"m"、"s"'
 * console.log(DIFFTIME('2019-6-30 13:20:00', '2020-10-01 11:20:32', 's'))
 */

export const diffTime = function(startTime, endTime, unit) {
  // 判断当前月天数
  function getDays(mouth, year) {
    let days = 30;

    if (mouth === 2) {
      days = year % 4 === 0 ? 29 : 28;
    } else if ([1, 3, 5, 7, 8, 10, 12].indexOf(mouth) >= 0) {
      // 月份为:1,3,5,7,8,10,12 时,为大月.则天数为31;
      days = 31;
    }
    return days;
  }
  const start: any = new Date(startTime);
  const end: any = new Date(endTime);
  // 计算时间戳的差
  const diffValue = end - start;
  // 获取年
  const startYear = start.getFullYear();
  const endYear = end.getFullYear();
  // 获取月
  const startMouth = start.getMonth() + 1;
  const endMouth = end.getMonth() + 1;
  // 获取日
  const startDay = start.getDate();
  const endDay = end.getDate();
  // 获取小时
  const startHours = start.getHours();
  const endHours = end.getHours();
  // 获取分
  const startMinutes = start.getMinutes();
  const endMinutes = end.getMinutes();
  // 获取秒
  const startSeconds = start.getSeconds();
  const endSeconds = end.getSeconds();
  // 下方注释两行为调试用
  // console.log('start:', startYear, startMouth, startDay, startHours, startMinutes, startSeconds)
  // console.log('end:', endYear, endMouth, endDay, endHours, endMinutes, endSeconds)
  if (unit === "y" || unit === "M") {
    // 相差年份月份
    const diffYear = endYear - startYear;
    // 获取当前月天数
    const startDays = getDays(startMouth, startYear);
    const endDays = getDays(endMouth, endYear);
    const diffStartMouth =
      (startDays -
        (startDay +
          (startHours * 60 + startMinutes + startSeconds / 60) / 60 / 24 -
          1)) /
      startDays;
    const diffEndMouth =
      (endDay + (endHours * 60 + endMinutes + endSeconds / 60) / 60 / 24 - 1) /
      endDays;
    const diffMouth =
      diffStartMouth +
      diffEndMouth +
      (12 - startMouth - 1) +
      endMouth +
      (diffYear - 1) * 12;
    if (unit === "y") {
      return Math.floor((diffMouth / 12) * 10) / 10;
    } else {
      return parseInt(diffMouth);
    }
  } else if (unit === "d") {
    const d = parseInt((diffValue / 1000 / 60 / 60 / 24).toString());
    return d;
  } else if (unit === "h") {
    const h = parseInt((diffValue / 1000 / 60 / 60).toString());
    return h;
  } else if (unit === "m") {
    const m = parseInt((diffValue / 1000 / 60).toString());
    return m;
  } else if (unit === "s") {
    const s = parseInt((diffValue / 1000).toString());
    return s;
  } else {
    console.log("请输入正确的单位");
  }
};

// 计算时间格式化
export const computingTime = days => {
  const defaultMonthText = "<1个月";
  if (!days) {
    return defaultMonthText;
  }
  const durationTime = 24 * 60 * 60 * 1000 * days;
  const endDate = new Date();
  const startDate = new Date(endDate.getTime() - durationTime);
  let monthCount = diffTime(startDate, endDate, "M");
  let year = parseInt((monthCount / 12).toString());
  let month = monthCount % 12;
  let yearText = year == 0 ? "" : `${year}年`;
  let monthText = month == 0 ? defaultMonthText : `${month}个月`;
  return yearText + monthText;
};

// 计算时间格式化返回月数
export const computingTimeReturnMonth = days => {
  if (!days) {
    return 0;
  }
  const durationTime = 24 * 60 * 60 * 1000 * days;
  const endDate = new Date();
  const startDate = new Date(endDate.getTime() - durationTime);
  let monthCount = diffTime(startDate, endDate, "M");
  return monthCount;
};

// 计算时间格式化返回相差天数小时分钟
export const computingTimeReturnDayHoursMinutes = (startDate, endDate) => {
  if (!endDate) {
    endDate = new Date();
  }
  let times = diffTime(startDate, endDate, "s");
  var days = Math.floor(times / (24 * 3600));
  //计算出小时数
  var leave1 = times % (24 * 3600);
  var hours = Math.floor(leave1 / 3600);
  //计算相差分钟数
  var leave2 = leave1 % 3600;
  var minutes = Math.floor(leave2 / 60);

  return times < 60
    ? "<1分钟"
    : `${days > 0 ? `${days}天` : ""}${hours > 0 ? `${hours}小时` : ""}${
        minutes > 0 ? `${minutes}分钟` : ""
      }`;
};

备注

返回时间是按照矢量时间进行计算的,会精确计算是否有闰月或者当前月份日期是三十一天等情况。

方法扩展

计算时间格式化

业务需求描述

假设有入职人员小A,他入职公司已经360天,我们要计算他具体的入职司龄,就会用到下边的方法,我们传入小A的入职具体天数,然后通过 diffTime 方法计算出入职公司的具体月数,然后用月数进行处理,返回小A当前入职的具体格式化司龄。

具体返回的格式可以根据自己实际业务进行调整,目前返回格式是xxx年xxx个月

代码

// 计算时间格式化
export const computingTime = days => {
  const defaultMonthText = "<1个月";
  if (!days) {
    return defaultMonthText;
  }
  const durationTime = 24 * 60 * 60 * 1000 * days;
  const endDate = new Date();
  const startDate = new Date(endDate.getTime() - durationTime);
  let monthCount = diffTime(startDate, endDate, "M");
  let year = parseInt((monthCount / 12).toString());
  let month = monthCount % 12;
  let yearText = year == 0 ? "" : `${year}年`;
  let monthText = month == 0 ? defaultMonthText : `${month}个月`;
  return yearText + monthText;
};

计算时间格式化返回相差天数小时数分钟

业务需求描述

在上一个函数的基础上进行一个细化,返回具体的相差时间,传入参数是开始时间和结束时间,需要进行改时间格式化处理,如果结束时间没有传入会以当前默认事件为结束时间进行计算。

代码

// 计算时间格式化返回相差天数小时分钟
export const computingTimeReturnDayHoursMinutes = (startDate, endDate) => {
  if (!endDate) {
    endDate = new Date();
  }
  let times = diffTime(startDate, endDate, "s");
  var days = Math.floor(times / (24 * 3600));
  //计算出小时数
  var leave1 = times % (24 * 3600);
  var hours = Math.floor(leave1 / 3600);
  //计算相差分钟数
  var leave2 = leave1 % 3600;
  var minutes = Math.floor(leave2 / 60);

  return times < 60
    ? "<1分钟"
    : `${days > 0 ? `${days}天` : ""}${hours > 0 ? `${hours}小时` : ""}${
        minutes > 0 ? `${minutes}分钟` : ""
      }`;
};

其他方法

时间戳转换标准格式

/**
 * 时间戳转换标准格式
 * timeStamp(1625605200) => '2021-6-29 05:00:00'
 */
function timeTest(m) {
  return m < 10 ? "0" + m : m;
}
export const timeStamp = (x: number) => {
  var time = new Date(x * 1000);
  var y = time.getFullYear();
  var m = time.getMonth() + 1;
  var d = time.getDate();
  var h = time.getHours();
  var mm = time.getMinutes();
  var s = time.getSeconds();
  return (
    y +
    "-" +
    timeTest(m) +
    "-" +
    timeTest(d) +
    " " +
    timeTest(h) +
    ":" +
    timeTest(mm) +
    ":" +
    timeTest(s)
  );
};

格式化标准时间

// 返回格式化后时间:year-month-day hour:minute:second
export const formatDate = (fromDate, isShowHours = false) => {
  let date = new Date(fromDate);
  let year = date.getFullYear();
  let month = date.getMonth() + 1;
  let day = date.getDate();
  let hour = date.getHours();
  let minute = date.getMinutes();
  let second = date.getSeconds();
  if (isShowHours) {
    return (
      year +
      "-" +
      formatTen(month) +
      "-" +
      formatTen(day) +
      " " +
      formatTen(hour) +
      ":" +
      formatTen(minute) +
      ":" +
      formatTen(second)
    );
  } else {
    return year + "-" + formatTen(month) + "-" + formatTen(day);
  }
};
可以通过第二个参数判断是否要返回时分秒精确时间

结尾

往期文章

如果小伙伴们觉得有用的话欢迎点赞分享~

如果有其他好的方法也可以评论区留言,大家一同进步~