在金融业务中经常涉及到交易日期的计算交易日和自然日是有区别的比如法定节假日周末都是不能交易的我们叫非交易日允许交易的日我们称之为交易日。交易日每天也不是24小时比如中国股市的股票交易时间在每个交易日的AM930-1130 和 PM1300-1500。为了满足724小时服务我们对用户提供的服务在非交易日或是非交易时段也是有支持的所以将非交易时段产生的业务它的交易日会算到下一个最近交易时段的交易日中为
以下是Java实现的参考代码:
import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.List;
public class TradeDayUtil {
private List<Date> tradeDayList;
/**
* 工具初始化,初始化的目的是让工具具备更加合适各的数据结构,方便计算提高效率
* @param tradeDayList 包含一年内所有的交易日起,格式如:20160701 20160704 20160705,非交易日20160702 20160703不在其中.
*/
public void init(List<String> tradeDayList) {
this.tradeDayList = new ArrayList<>();
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
for (String tradeDay : tradeDayList) {
try {
Date date = sdf.parse(tradeDay);
this.tradeDayList.add(date);
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* 给定任意时间,返回给定时间的T+n交易日
* @param time 给定要计算的时间。
* @param offsetDays 交易日偏移量,offsetDays可以为负数,表示T-n的计算。
*/
public String getTradeDay(Date time, int offsetDays) {
Calendar calendar = Calendar.getInstance();
calendar.setTime(time);
int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK);
if (dayOfWeek == Calendar.SATURDAY || dayOfWeek == Calendar.SUNDAY) {
// 如果给定时间是周末,则将时间调整到最近的交易日
if (dayOfWeek == Calendar.SATURDAY) {
calendar.add(Calendar.DAY_OF_MONTH, 2);
} else {
calendar.add(Calendar.DAY_OF_MONTH, 1);
}
calendar.set(Calendar.HOUR_OF_DAY, 9);
calendar.set(Calendar.MINUTE, 30);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
} else {
// 如果给定时间是交易日,则将时间调整到上午或下午交易时间段内
int hourOfDay = calendar.get(Calendar.HOUR_OF_DAY);
if (hourOfDay < 9 || (hourOfDay >= 12 && hourOfDay < 13) || hourOfDay >= 15) {
if (hourOfDay < 9) {
calendar.set(Calendar.HOUR_OF_DAY, 9);
calendar.set(Calendar.MINUTE, 30);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
} else {
calendar.set(Calendar.HOUR_OF_DAY, 13);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
}
}
}
// 根据偏移量计算T+n交易日
if (offsetDays > 0) {
int count = 0;
while (count < offsetDays) {
calendar.add(Calendar.DAY_OF_MONTH, 1);
if (isTradeDay(calendar.getTime())) {
count++;
}
}
} else if (offsetDays < 0) {
int count = 0;
while (count > offsetDays) {
calendar.add(Calendar.DAY_OF_MONTH, -1);
if (isTradeDay(calendar.getTime())) {
count--;
}
}
}
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
return sdf.format(calendar.getTime());
}
/**
* 判断给定的日期是否是交易日
* @param date 给定的日期
* @return 如果是交易日返回true,否则返回false
*/
private boolean isTradeDay(Date date) {
return tradeDayList.contains(date);
}
}
实现中主要考虑了以下几点:
-
将交易日列表以Date类型的形式存储,方便后续计算。
-
根据给定时间的星期几和时间段,将时间调整到最近的交易日和交易时间段内。
-
根据偏移量计算T+n交易日,如果偏移量为负数,则计算T-n交易日。
-
判断给定的日期是否是交易日,主要是通过判断其是否在交易日列表中实现的。
下面是单元测试代码:
import org.junit.Assert; import org.junit.Before; import org.junit.Test;
import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.List;
public class TradeDayUtilTest {
private TradeDayUtil tradeDayUtil;
@Before
public void setUp() throws Exception {
List<String> tradeDayList = new ArrayList<>();
tradeDayList.add("20220103");
tradeDayList.add("20220104");
tradeDayList.add("20220105");
tradeDayList.add("20220106");
tradeDayList.add("20220107");
tradeDayList.add("20220110");
tradeDayList.add("20220111");
tradeDayList.add("20220112");
tradeDayList.add("20220113");
tradeDayList.add("20220114");
tradeDayUtil = new TradeDayUtil();
tradeDayUtil.init(tradeDayList);
}
@Test
public void testGetTradeDay() throws Exception {
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd HH:mm:ss");
// 2022年1月10日上午9点的T+0交易日应该是20220110
String tradeDay = tradeDayUtil.getTradeDay(sdf.parse("20220110 09:00:00"), 0);
Assert.assertEquals("20220110", tradeDay);
// 2022年1月10日下午3点的T+0交易日应该是20220110
tradeDay = tradeDayUtil.getTradeDay(sdf.parse("20220110 15:00:00"), 0);
Assert.assertEquals("20220110", tradeDay);
// 2022年1月10日下午6点的T+0交易日应该是20220111
tradeDay = tradeDayUtil.getTradeDay(sdf.parse("20220110 18:00:00"), 0);
Assert.assertEquals("20220111", tradeDay);
// 2022年1月8日上午8点的T+1交易日应该是20220110
tradeDay = tradeDayUtil.getTradeDay(sdf.parse("20220108 08:00:00"), 1);
Assert.assertEquals("20220110", tradeDay);
// 2022年1月11日下午4点的T-1交易日应该是20220110
tradeDay = tradeDayUtil.getTradeDay(sdf.parse("20220111 16:00:00"), -1);
Assert.assertEquals("20220110", tradeDay);
// 2022年1月1日上午10点的T+5交易日应该是20220112
tradeDay = tradeDayUtil.getTradeDay(sdf.parse("20220101 10:00:00"), 5);
Assert.assertEquals("20220112", tradeDay);
}
原文地址: http://www.cveoy.top/t/topic/fiv5 著作权归作者所有。请勿转载和采集!