js-计算请假时长,去除午休与休息日期

本文介绍了一个使用dayjs库计算特定条件下工作时间总长的JavaScript函数。该函数考虑了上班时间、下班时间、午休时间、请假时间和剔除日期等因素,通过精确到分钟的计算,为人力资源管理和考勤提供了实用的解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

const dayjs = require('dayjs');

function getTotal (options) {
  // {
  //   // 上班时间
  //   startWorkTime,
  //     // 下班时间
  //     endWorkTime,
  //     // 请假开始时间
  //     beginAt,
  //     // 请假结束时间
  //     endAt,
  //     // 是否去除午休时间
  //     excludeFreeTime,
  //     // 午休开始时间
  //     startFreeTime,
  //     // 午休结束时间
  //     endFreeTime
  //     //剔除日期数组
  //     excludeDates
  // }
  if (dayjs(options.beginAt).isAfter(dayjs(options.endAt))) {
    [options.beginAt, options.endAt] = [options.endAt, options.beginAt];
  }

  options.excludeDates = options.excludeDates.map(d => dayjs(d));

  let minute = 0;

  const diffDay = dayjs(options.endAt).startOf('day').diff(dayjs(options.beginAt).startOf('day'), 'day');

  for (let i = 0; i <= diffDay; i++) {
    const day = dayjs(options.beginAt).add(i, 'day').startOf('day');

    if (options.excludeDates.some(d => d.isSame(day, 'date'))) {
      continue;
    }

    const startWorkAt = day.minute(options.startWorkTime * 60);
    const endWorkAt = day.minute(options.endWorkTime * 60);
    const startFreeAt = day.minute(options.startFreeTime * 60);
    const endFreeAt = day.minute(options.endFreeTime * 60);
    let beginAt = dayjs(options.beginAt);
    beginAt = beginAt.isBefore(startWorkAt) ? startWorkAt : beginAt.isAfter(endWorkAt) ? endWorkAt : beginAt;
    let endAt = dayjs(options.endAt);
    endAt = endAt.isAfter(endWorkAt) ? endWorkAt : endAt;
    if (options.excludeFreeTime) {
      beginAt = (beginAt.isAfter(startFreeAt) && beginAt.isBefore(endFreeAt)) ? endFreeAt : beginAt;
      endAt = (endAt.isAfter(startFreeAt) && endAt.isBefore(endFreeAt)) ? startFreeAt : endAt;
    }

    let ranges = [];

    if (diffDay === 0) {
      if (options.excludeFreeTime && beginAt.isBefore(startFreeAt) && endAt.isAfter(endFreeAt)) {
        ranges = [[beginAt, startFreeAt], [endFreeAt, endAt]];
      } else {
        ranges = [[beginAt, endAt]];
      }
    } else if (i === 0) {
      if (options.excludeFreeTime) {
        ranges = beginAt.isBefore(startFreeAt) ? [
          [beginAt, startFreeAt],
          [endFreeAt, endWorkAt]
        ] : [[beginAt, endWorkAt]];
      } else {
        ranges = [[beginAt, endWorkAt]];
      }
    } else if (i === diffDay) {
      if (options.excludeFreeTime) {
        ranges = endAt.isBefore(startFreeAt) ? [[startWorkAt, endAt]] : [
          [startWorkAt, startFreeAt],
          [endFreeAt, endAt]
        ];
      } else {
        ranges = [[startWorkAt, endAt]];
      }
    } else {
      if (options.excludeFreeTime) {
        ranges = [
          [startWorkAt, startFreeAt],
          [endFreeAt, endWorkAt]
        ];
      } else {
        ranges = [[startWorkAt, endWorkAt]];
      }
    }

    console.log(ranges.map(r => {
      return r.map(d => d.format('YYYY-MM-DD HH:mm:ss'));
    }), ranges.map(range => {
      const diff = range[1].diff(range[0], 'minute');
      if (diff < 0) {
        return 0;
      }
      return diff;
    }).reduce((a, b) => a + b, 0));

    minute += ranges.map(range => {
      const diff = range[1].diff(range[0], 'minute');
      if (diff < 0) {
        return 0;
      }
      return diff;
    }).reduce((a, b) => a + b, 0);

  }
  console.log(`
分钟: ${ minute }
小时: ${ parseFloat((minute / 60).toFixed(2)) }
  `);
  return parseFloat((minute / 60).toFixed(2));
}

getTotal({
  startWorkTime: 9,
  endWorkTime: 18,
  beginAt: '2020-08-16 12:30:00',
  endAt: '2020-08-18 14:40:00',
  startFreeTime: 12,
  endFreeTime: 13.5,
  excludeFreeTime: true,
  excludeDates: ['2020-08-17']
});

运行结果:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值