Initial commit
This commit is contained in:
214
src/utils/tradingDayUtils.js
Normal file
214
src/utils/tradingDayUtils.js
Normal file
@@ -0,0 +1,214 @@
|
||||
// src/utils/tradingDayUtils.js
|
||||
// 交易日计算工具函数
|
||||
|
||||
/**
|
||||
* 中国股市交易日工具类
|
||||
* 包含节假日判断和交易日计算
|
||||
*/
|
||||
class TradingDayUtils {
|
||||
constructor() {
|
||||
// 2024-2025年的法定节假日(需要定期更新)
|
||||
this.holidays = new Set([
|
||||
// 2024年节假日
|
||||
'2024-01-01', // 元旦
|
||||
'2024-02-09', '2024-02-10', '2024-02-11', '2024-02-12', '2024-02-13',
|
||||
'2024-02-14', '2024-02-15', '2024-02-16', '2024-02-17', // 春节
|
||||
'2024-04-04', '2024-04-05', '2024-04-06', // 清明节
|
||||
'2024-05-01', '2024-05-02', '2024-05-03', '2024-05-04', '2024-05-05', // 劳动节
|
||||
'2024-06-08', '2024-06-09', '2024-06-10', // 端午节
|
||||
'2024-09-15', '2024-09-16', '2024-09-17', // 中秋节
|
||||
'2024-10-01', '2024-10-02', '2024-10-03', '2024-10-04',
|
||||
'2024-10-05', '2024-10-06', '2024-10-07', // 国庆节
|
||||
|
||||
// 2025年节假日(预估,需要根据官方公告更新)
|
||||
'2025-01-01', // 元旦
|
||||
'2025-01-28', '2025-01-29', '2025-01-30', '2025-01-31',
|
||||
'2025-02-01', '2025-02-02', '2025-02-03', '2025-02-04', // 春节
|
||||
'2025-04-04', '2025-04-05', '2025-04-06', // 清明节
|
||||
'2025-05-01', '2025-05-02', '2025-05-03', // 劳动节
|
||||
'2025-05-31', '2025-06-01', '2025-06-02', // 端午节
|
||||
'2025-10-01', '2025-10-02', '2025-10-03', '2025-10-04',
|
||||
'2025-10-05', '2025-10-06', '2025-10-07', '2025-10-08', // 国庆节+中秋节
|
||||
]);
|
||||
|
||||
// A股交易时间
|
||||
this.marketOpenTime = { hour: 9, minute: 30 };
|
||||
this.marketCloseTime = { hour: 15, minute: 0 };
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否为周末
|
||||
* @param {Date} date
|
||||
* @returns {boolean}
|
||||
*/
|
||||
isWeekend(date) {
|
||||
const day = date.getDay();
|
||||
return day === 0 || day === 6; // 0是周日,6是周六
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否为节假日
|
||||
* @param {Date} date
|
||||
* @returns {boolean}
|
||||
*/
|
||||
isHoliday(date) {
|
||||
const dateStr = this.formatDate(date);
|
||||
return this.holidays.has(dateStr);
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否为交易日
|
||||
* @param {Date} date
|
||||
* @returns {boolean}
|
||||
*/
|
||||
isTradingDay(date) {
|
||||
return !this.isWeekend(date) && !this.isHoliday(date);
|
||||
}
|
||||
|
||||
/**
|
||||
* 格式化日期为 YYYY-MM-DD
|
||||
* @param {Date} date
|
||||
* @returns {string}
|
||||
*/
|
||||
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}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断时间是否在交易时间内
|
||||
* @param {Date} datetime
|
||||
* @returns {boolean}
|
||||
*/
|
||||
isInTradingHours(datetime) {
|
||||
const hours = datetime.getHours();
|
||||
const minutes = datetime.getMinutes();
|
||||
|
||||
// 上午交易时间:9:30-11:30
|
||||
const morningStart = hours > 9 || (hours === 9 && minutes >= 30);
|
||||
const morningEnd = hours < 11 || (hours === 11 && minutes <= 30);
|
||||
|
||||
// 下午交易时间:13:00-15:00
|
||||
const afternoonStart = hours >= 13;
|
||||
const afternoonEnd = hours < 15;
|
||||
|
||||
return (morningStart && morningEnd) || (afternoonStart && afternoonEnd);
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断事件是否发生在交易时间后
|
||||
* @param {Date} datetime
|
||||
* @returns {boolean}
|
||||
*/
|
||||
isAfterTradingHours(datetime) {
|
||||
const hours = datetime.getHours();
|
||||
const minutes = datetime.getMinutes();
|
||||
return hours > 15 || (hours === 15 && minutes > 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取下一个交易日
|
||||
* @param {Date} date
|
||||
* @returns {Date}
|
||||
*/
|
||||
getNextTradingDay(date) {
|
||||
const nextDay = new Date(date);
|
||||
nextDay.setDate(nextDay.getDate() + 1);
|
||||
|
||||
while (!this.isTradingDay(nextDay)) {
|
||||
nextDay.setDate(nextDay.getDate() + 1);
|
||||
}
|
||||
|
||||
return nextDay;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取上一个交易日
|
||||
* @param {Date} date
|
||||
* @returns {Date}
|
||||
*/
|
||||
getPreviousTradingDay(date) {
|
||||
const prevDay = new Date(date);
|
||||
prevDay.setDate(prevDay.getDate() - 1);
|
||||
|
||||
while (!this.isTradingDay(prevDay)) {
|
||||
prevDay.setDate(prevDay.getDate() - 1);
|
||||
}
|
||||
|
||||
return prevDay;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据事件时间获取对应的交易日
|
||||
* 规则:
|
||||
* 1. 如果是交易日的交易时间内,返回当天
|
||||
* 2. 如果是交易日的15:00后,返回下一个交易日
|
||||
* 3. 如果是非交易日(周末或节假日),返回下一个交易日
|
||||
*
|
||||
* @param {Date|string} eventDateTime 事件时间
|
||||
* @returns {string} 交易日期 YYYY-MM-DD
|
||||
*/
|
||||
getEffectiveTradingDay(eventDateTime) {
|
||||
const datetime = typeof eventDateTime === 'string' ? new Date(eventDateTime) : eventDateTime;
|
||||
|
||||
// 如果是非交易日,直接返回下一个交易日
|
||||
if (!this.isTradingDay(datetime)) {
|
||||
return this.formatDate(this.getNextTradingDay(datetime));
|
||||
}
|
||||
|
||||
// 如果是交易日
|
||||
// 检查是否在15:00之后
|
||||
if (this.isAfterTradingHours(datetime)) {
|
||||
// 15:00后,返回下一个交易日
|
||||
return this.formatDate(this.getNextTradingDay(datetime));
|
||||
}
|
||||
|
||||
// 交易日的15:00前,返回当天
|
||||
return this.formatDate(datetime);
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量加载交易日数据(如果有CSV文件)
|
||||
* @param {string} csvContent CSV内容
|
||||
*/
|
||||
loadTradingDaysFromCSV(csvContent) {
|
||||
const lines = csvContent.trim().split('\n');
|
||||
const tradingDays = new Set();
|
||||
|
||||
// 跳过标题行
|
||||
for (let i = 1; i < lines.length; i++) {
|
||||
const date = lines[i].trim();
|
||||
if (date) {
|
||||
// 转换日期格式 2010/1/4 -> 2010-01-04
|
||||
const parts = date.split('/');
|
||||
if (parts.length === 3) {
|
||||
const year = parts[0];
|
||||
const month = parts[1].padStart(2, '0');
|
||||
const day = parts[2].padStart(2, '0');
|
||||
tradingDays.add(`${year}-${month}-${day}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.tradingDaysSet = tradingDays;
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用CSV数据判断是否为交易日(如果已加载)
|
||||
* @param {Date} date
|
||||
* @returns {boolean}
|
||||
*/
|
||||
isTradingDayByCSV(date) {
|
||||
if (this.tradingDaysSet) {
|
||||
return this.tradingDaysSet.has(this.formatDate(date));
|
||||
}
|
||||
// 如果没有CSV数据,回退到默认判断
|
||||
return this.isTradingDay(date);
|
||||
}
|
||||
}
|
||||
|
||||
// 导出单例
|
||||
export const tradingDayUtils = new TradingDayUtils();
|
||||
export default tradingDayUtils;
|
||||
Reference in New Issue
Block a user