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)代码
[java] view plain copy
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;
[java] view plain copy
// 计算两个日期之间月份数方法 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)代码
[java] view plain copy
//判断是否为闰年计息年度方法 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; }
浮息债的算法 计算方式会比这还要复杂很多。