计算交易日期js怎么实现

637 阅读4分钟

需求如下

首次结算日+回购期限(直接相加自然日),若结果为交易日,则取该日期,如果是周末或者节假日则 顺延到下一个交易日 怎么实现

分析,我们首先需要计算到期日是否为周末或者节假日 使用第三方库moment.js来实现

可以通过npm或者yarn安装moment.js,如下所示:

Copy code
npm install moment
  1. 导入moment.js库

在js文件中,通过import语句导入moment.js库,如下所示:

pythonCopy code
import moment from 'moment';
  1. 计算结算日+回购期限

使用moment.js库中的add()方法计算结算日+回购期限的结果,如下所示:

csharpCopy code
const firstSettlementDate = moment('2022-02-01'); // 首次结算日
const repurchaseDays = 10; // 回购期限
const settlementDate = firstSettlementDate.add(repurchaseDays, 'days'); // 结算日+回购期限
  1. 判断结果是否为交易日

使用moment.js库中的isBusinessDay()方法判断结果是否为交易日,如下所示:

scssCopy code
let nextBusinessDay = settlementDate;
while (!moment(nextBusinessDay).isBusinessDay()) {
  nextBusinessDay = moment(nextBusinessDay).add(1, 'days');
}
  1. 判断是否是周末或者节假日

使用moment.js库中的isWeekend()方法判断是否是周末,使用isHoliday()方法判断是否是节假日,如果是周末或者节假日,则顺延到下一个交易日,如下所示:

scssCopy code
while (moment(nextBusinessDay).isWeekend() || moment(nextBusinessDay).isHoliday()) {
  nextBusinessDay = moment(nextBusinessDay).add(1, 'days');
}

完整的代码示例如下:

scssCopy code
import moment from 'moment';

const firstSettlementDate = moment('2022-02-01'); // 首次结算日
const repurchaseDays = 10; // 回购期限
let settlementDate = firstSettlementDate.add(repurchaseDays, 'days'); // 结算日+回购期限

let nextBusinessDay = settlementDate;
while (!moment(nextBusinessDay).isBusinessDay()) {
  nextBusinessDay = moment(nextBusinessDay).add(1, 'days');
}

while (moment(nextBusinessDay).isWeekend() || moment(nextBusinessDay).isHoliday()) {
  nextBusinessDay = moment(nextBusinessDay).add(1, 'days');
}

console.log(nextBusinessDay.format('YYYY-MM-DD')); // 输出顺延后的日期

需要注意的是,判断是否是交易日、周末或者节假日需要依赖moment.js库中的isBusinessDay()、isWeekend()、isHoliday()方法,需要事先加载好相关的数据。如果需要自定义交易日、节假日等,可以使用moment-business-days库。

如果不依赖第三方库moment 怎么实现呢

代码示例:

javascriptCopy code
// 定义节假日数组,可以根据实际情况进行修改
const holidays = ['2022-01-01', '2022-02-01', '2022-02-02', '2022-04-05', '2022-05-01', '2022-06-25', '2022-09-19', '2022-10-01', '2022-10-02', '2022-10-03', '2022-10-04', '2022-10-05', '2022-10-06', '2022-10-07'];

// 定义计算函数
function calculateSettlementDate(startDate, repurchaseDays) {
  // 将开始日期转换为 Date 对象
  const start = new Date(startDate);
  // 计算结束日期
  const end = new Date(start.getTime() + repurchaseDays * 24 * 60 * 60 * 1000);
  // 判断结束日期是否是交易日
  if (isBusinessDay(end, holidays)) {
    return formatDate(end);
  } else {
    // 如果不是交易日,则顺延到下一个交易日
    return getNextBusinessDay(end, holidays);
  }
}

// 判断日期是否为交易日
function isBusinessDay(date, holidays) {
  const dayOfWeek = date.getDay();
  // 周六周日不是交易日
  if (dayOfWeek === 0 || dayOfWeek === 6) {
    return false;
  }
  // 判断是否为节假日
  const formattedDate = formatDate(date);
  if (holidays.includes(formattedDate)) {
    return false;
  }
  return true;
}

// 将日期格式化为 yyyy-mm-dd 的形式
function formatDate(date) {
  const year = date.getFullYear();
  const month = ('0' + (date.getMonth() + 1)).slice(-2);
  const day = ('0' + date.getDate()).slice(-2);
  return `${year}-${month}-${day}`;
}

// 获取下一个交易日
function getNextBusinessDay(date, holidays) {
  let nextDay = new Date(date);
  while (!isBusinessDay(nextDay, holidays)) {
    nextDay = new Date(nextDay.getTime() + 24 * 60 * 60 * 1000);
  }
  return formatDate(nextDay);
}

// 示例使用
const settlementDate = calculateSettlementDate('2022-01-10', 5);
console.log(settlementDate); // 输出 2022-01-15

在上面的代码中,我们使用了三个函数:

  1. isBusinessDay(date, holidays):用于判断一个日期是否为交易日,返回 true 或者 false
  2. getNextBusinessDay(date, holidays):用于获取下一个交易日。
  3. calculateSettlementDate(startDate, repurchaseDays):用于计算结算日期。

需要注意的是,在判断日期是否为交易日的时候,我们先判断了是否为周六周日,然后再判断是否为节假日。如果判断为节假日,则直接返回 false。在计算下一个交易日

完整的可运行的 JavaScript 代码示例:

javascriptCopy code
function formatDate(date) {
  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}`;
}

function isWeekend(date) {
  const dayOfWeek = date.getDay();
  return dayOfWeek === 0 || dayOfWeek === 6;
}

function isHoliday(date) {
  // TODO: 根据实际情况实现节假日判断逻辑
  return false;
}

function calculateRepurchaseDate(settlementDate, repurchasePeriod) {
  const DAY_IN_MS = 24 * 60 * 60 * 1000;

  const settlementDateObj = new Date(settlementDate);
  const repurchasePeriodMs = repurchasePeriod * DAY_IN_MS;
  const repurchaseDateObj = new Date(settlementDateObj.getTime() + repurchasePeriodMs);
  let repurchaseDateStr = formatDate(repurchaseDateObj);

  let repurchaseDate = new Date(repurchaseDateStr);
  while (isWeekend(repurchaseDate) || isHoliday(repurchaseDate)) {
    repurchaseDate = new Date(repurchaseDate.getTime() + DAY_IN_MS);
    repurchaseDateStr = formatDate(repurchaseDate);
  }

  return repurchaseDateStr;
}

// 使用示例
const settlementDate = '2023-02-21';
const repurchasePeriod = 3;

const repurchaseDate = calculateRepurchaseDate(settlementDate, repurchasePeriod);
console.log(`回购到期日为 ${repurchaseDate}`);

这里将计算回购到期日的功能封装成了一个名为calculateRepurchaseDate的函数,并在函数内部使用了之前定义的辅助函数。在函数外部定义了首次结算日和回购期限的变量,并调用calculateRepurchaseDate函数计算回购到期日。最后将回购到期日输出到控制台上。

isHoliday 实现

判断节假日是否包括法定节假日、补休日、调休日等比较复杂,需要根据具体情况进行判断。这里提供一个简单的做法,假设节假日列表是一个数组,数组中包含节假日的日期字符串。

javascriptCopy code
function isHoliday(date) {
  const holidayList = ['2023-04-05', '2023-04-06']; // 假设节假日列表是一个数组,包含4月5日和4月6日
  const dateStr = formatDate(date);
  return holidayList.includes(dateStr);
}

这里将节假日日期字符串保存在一个数组中,然后通过includes方法判断指定日期是否在数组中。在实际应用中,需要根据实际情况来获取节假日列表。