关于债券付息的一些日期计算方式
最近在二期开发的时候 碰到的主要难点是债券付息兑付计划制定的业务问题 开发过程中涉及的许多算法
初步完成的代码中涉及到很多日期的特殊计算 记录下来做金融项目的时候可以作为参考 因为进度很急代码没有重构 只是为了未完成功能的第一阶段的代码
—— —— —— —— —— —— —— —— —— —— —— —— —— —— —— —— —— ——
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 awardInteDate(Long d1, Long d2,Long frequency) throws ParseException,java.text.ParseException {String str = d1.toString();List list = new ArrayList();//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日为标准。仍以前款所举产品为例,因2023年2月处于该产品的2023年4月20日至2023年4月20日这一计息年度内,所以该计息年度为闰年计息年度。因此,2023年在自然年度上虽不是闰年,但第四个计息期(2023年1月20日——2023年4月20日)因属于该产品2023年4月20日——2023年4月20日这一计息年度,所以应按闰年处理。而2023年虽然是在自然年度上是闰年,但其第五个计息年度(2023年4月20日——2023年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 list=new ArrayList();List arrList=new ArrayList();for(i=Integer.parseInt(begin.substring(0, 4));i=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)版权声明: 本站仅提供信息存储空间服务,旨在传递更多信息,不拥有所有权,不承担相关法律责任,不代表本网赞同其观点和对其真实性负责。如因作品内容、版权和其它问题需要同本网联系的,请发送邮件至 举报,一经查实,本站将立刻删除。