关于债券付息的一些日期计算方式

来源:互联网 发布:福利app软件 编辑:程序博客网 时间:2024/05/06 07:17

最近在二期开发的时候 碰到的主要难点是债券付息兑付计划制定的业务问题  开发过程中涉及的许多算法

初步完成的代码中涉及到很多日期的特殊计算   记录下来做金融项目的时候可以作为参考   因为进度很急代码没有重构 只是为了未完成功能的第一阶段的代码


—— —— —— —— —— —— —— —— —— —— —— —— —— —— —— —— —— ——

1.(1)业务场景

付息频率为 月/次 为单位   能拿到字段 起息日  到期日  需要计算出中间所有的付息兑付计划日期

(2)主要问题:

1>如果起息日为某月31号 遇到没有31号的月份需要取30号   

2>如果起息日为30号 或者29号 遇到平年2月份需要取28号

(3)算法分析:

按照付息频率 拿到每个付息月份可以用calendar类自带加法运算月份的方法 add(int field, int amount) ( 此方法取到的日期  假如起息日为某月30日  如果下一个计息月为2月 会给你自动取到最后一天28日  那么在for循环中再往下计算会都取到计息月份的28号)

calendar类自带可以取到一个月最后一天的方法 那么若是31号 则取到当月的最后一天

如果是30号或者29号 按照add方法计算出所有计息日期放入list  然后遍历list 将不是二月份的日期全部替换成30号或29号

(4)代码

// 获得所有付息日期private List<String> awardInteDate(Long d1, Long d2,Long frequency) throws ParseException,java.text.ParseException {String str = d1.toString();List<String> list = new ArrayList<String>();//getMonthSpace()获得两个日期之间的月份数量for (int i = 0; i < InfordInteCalculateLogic.getMonthSpace(d1.toString(), d2.toString()) / frequency; i++) {SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");Date date = sdf.parse(str);Calendar ins = Calendar.getInstance();ins.setTime(date);ins.add(Calendar.MONTH,frequency.intValue());//yyyyMMdd格式的日期  取到日String s = d1.toString().substring(str.length() - 2, str.length());if ("31".equals(s)) {//如果是31号 取每个月最后一天 ins.set(Calendar.DATE, ins.getActualMaximum(Calendar.DATE));str = sdf.format(ins.getTime()).toString();list.add(str);}else {str = sdf.format(ins.getTime()).toString();list.add(str);}}String ss = d1.toString().substring(str.length() - 2, str.length());//如果是30号  将list中除了2月份之外所有月份的日改为30号if ("30".equals(ss)) {for (int i = 0; i < list.size(); i++) {String str1 = list.get(i);if (!"02".equals(str1.substring(4, 6))) {StringBuilder builder = new StringBuilder(str1);builder.replace(6, 8, "30");str1 = builder.toString();list.set(i, str1);}}}if ("29".equals(ss)) {for (int i = 0; i < list.size(); i++) {String str1 = list.get(i);if (!"02".equals(str1.substring(4, 6))) {StringBuilder builder = new StringBuilder(str1);builder.replace(6, 8, "29");str1 = builder.toString();list.set(i, str1);}}}return list;

// 计算两个日期之间月份数方法public static int getMonthSpace(String date1, String date2) throws ParseException,java.text.ParseException {int result = 0;SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");Calendar c1 = Calendar.getInstance();Calendar c2 = Calendar.getInstance();c1.setTime(sdf.parse(date1));c2.setTime(sdf.parse(date2));result = (c2.get(Calendar.YEAR) - c1.get(Calendar.YEAR)) * 12+ (c2.get(Calendar.MONTH) - c1.get(Calendar.MONTH));return result == 0 ? 1 : Math.abs(result);}


—— —— —— —— —— —— —— —— —— —— —— —— —— —— —— —— —— ——

2.(1)业务场景

1>非闰年计息年度确定

按照产品本身的生命周期确定其计息年度。如某附息债权融资计划,5年期,每三个月付息一次,起息日为2016年4月20日,则2016年7月20日为第一个付息日,2016年10月20日为第二个付息日,那么2016年4月20日——2017年4月20日(利息计算算头不算尾,下同)为该产品的第一个完整计息年度,该产品共5个计息年度。

2>闰年计息年度确定

    闰年计息年度确定,以其一个完整的计息年度内是否跨越闰年中的2月29日为标准。仍以前款所举产品为例,因2020年2月处于该产品的2019年4月20日至2020年4月20日这一计息年度内,所以该计息年度为闰年计息年度。因此,2019年在自然年度上虽不是闰年,但第四个计息期(2020年1月20日——2020年4月20日)因属于该产品2019年4月20日——2020年4月20日这一计息年度,所以应按闰年处理。而2020年虽然是在自然年度上是闰年,但其第五个计息年度(2020年4月20日——2021年4月20日)不是闰年计息年度,仍按非闰年处理。

(2)算法分析:

拿到 2个如期间所有的闰年 如果起息日是一个2月29号之后的时间 那么拼接前一年和当年为计息年度横跨的2年 将这两个年度放入数组  

如果是一个2月29号之前的日期  那么拼接当年和后一年为计息年度横跨的2年 将这两个年度放入数组  

如果付息计划时间 在这个数组list中任意一个数组中的两个时间跨度之内 那么代表在闰年计息年度中 flag+1 标记为闰年计息年度

(3)代码

//判断是否为闰年计息年度方法private int judgeLeapYearStyle(String date,String begin,String end){int i;List<Integer> list=new  ArrayList<Integer>();List<String []> arrList=new  ArrayList<String []>();for(i=Integer.parseInt(begin.substring(0, 4));i<=Integer.parseInt(end.substring(0, 4));i++){      if((i%4==0&&i%100!=0)||(i%400==0)) {      list.add(i);      }    }// 拿到 2个如期间所有的闰年 如果起息日是一个2月29号之后的时间 那么拼接前一年和当年为计息年度横跨的2年 将这两个年度放入数组// 如果是一个2月29号之前的日期  那么拼接当年和后一年为计息年度横跨的2年 将这两个年度放入数组   // 如果付息计划时间 在这个数组list中任意一个数组中的两个时间跨度之内 那么代表在闰年计息年度中 flag+1 标记为闰年计息年度String monthDay;if("0".equals(begin.substring(4, 5))){monthDay=begin.substring(5, 8);if(Integer.parseInt(monthDay)>=229){for (Integer integer : list) {String d1=String.valueOf(integer-1)+"0"+monthDay;String d2=String.valueOf(integer)+"0"+monthDay;String[] arr = new String []{d1,d2};arrList.add(arr);}}else{for (Integer integer : list) {String d1=String.valueOf(integer)+"0"+monthDay;String d2=String.valueOf(integer+1)+"0"+monthDay;String[] arr = new String []{d1,d2};arrList.add(arr);}}}else{monthDay=begin.substring(4, 8);if(Integer.parseInt(monthDay)>=229){for (Integer integer : list) {String d1=String.valueOf(integer-1)+monthDay;String d2=String.valueOf(integer)+monthDay;String[] arr = new String []{d1,d2};arrList.add(arr);}}else{for (Integer integer : list) {String d1=String.valueOf(integer)+"0"+monthDay;String d2=String.valueOf(integer+1)+"0"+monthDay;String[] arr = new String []{d1,d2};arrList.add(arr);}}}int flag = 0;for (String[] strings : arrList) {if(Integer.parseInt(date)>=Integer.parseInt(strings[0]) && Integer.parseInt(date)<=Integer.parseInt(strings[1])){flag+=1;}}return flag;}


这些业务场景比较特殊 复用性可能不是那勉强  仅仅用作自己学习思考的记录  因为之后要做浮息债的算法 计算方式会比之还要复杂很多 所以思路理清一步步往下做很重要

1 0
原创粉丝点击