package incomeCalculator;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
public class IncomeCalculator {
private static final BigDecimal bg100 = new BigDecimal(100);
private static final BigDecimal bg360 = new BigDecimal(360);
private static final BigDecimal bg12 = new BigDecimal(12);
private static final BigDecimal bg3 = new BigDecimal(3);
private static final BigDecimal bg1 = new BigDecimal(1);
private static final BigDecimal bg0 = new BigDecimal(0);
private static final long dayOfMillisecond = 24 * 60 * 60 * 1000;
private static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
public static final DecimalFormat df = new DecimalFormat("#,##,##0.00");
/**
*
DEBX---等额本息---自然月---期限单位:月
YCFQ---本息到期一次性付清---自然月---期限单位:月||天
AJHB---每月付息,按季还本---自然月---期限单位:月
DEBJ---等额本金---自然月||固定日---期限单位:月
MYFX---每月付息,到期还本---自然月||固定日---期限单位:月
*/
public static void main(String[] args) throws IOException {
System.out.println("===========收益计算器===========");
System.out.println("=====请选择以下类型");
System.out.println("1-1:[DEBX]---等额本息");
System.out.println("1-2:[YCFQ]---本息到期一次性付清");
System.out.println("1-3:[AJHB]---每月付息,按季还本");
System.out.println("1-4:[DEBJ]---等额本金");
System.out.println("1-5:[MYFX]---每月付息,到期还本");
System.out.println("=====请选择以下付息方式");
System.out.println("2-1:[MON]---自然月");
System.out.println("2-2:[DAY]---固定日");
System.out.println("=====请选择以下期限单位");
System.out.println("3-1:[QXMON]---月");
System.out.println("3-2:[QXDAY]---天");
System.out.println("输入数据如(DEBX,MON,QXMON,1000,8.5,5)");
System.out.println("上面数据含义:等额本息,自然月,期限单位(月),投资金额1000元,年利率8.5%,期限5个月");
String jklx = null;
String fxfs = null;
String qxdw = null;
String tzje = null;
String nll = null;
String jkqx = null;
String inputStr = null;
while(true){
System.out.println("=====请输入...........(输入数据英文逗号分隔,输入0退出)");
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
inputStr = br.readLine();
String input[] = inputStr.split(",");
if("0".equals(input[0])){
System.exit(0);
}
jklx = input[0];
fxfs = input[1];
qxdw = input[2];
tzje = input[3];
nll = input[4];
jkqx = input[5];
BigDecimal investAmt = new BigDecimal(tzje);
BigDecimal yearRate = new BigDecimal(nll).divide(bg100);
int qx = Integer.parseInt(jkqx);
switch (jklx) {
case "DEBX":
calcDEBX(jklx,fxfs,qxdw,investAmt,yearRate,qx);
break;
case "YCFQ":
calcYCFQ(jklx,fxfs,qxdw,investAmt,yearRate,qx);
break;
case "AJHB":
calcAJHB(jklx,fxfs,qxdw,investAmt,yearRate,qx);
break;
case "DEBJ":
calcDEBJ(jklx,fxfs,qxdw,investAmt,yearRate,qx);
break;
case "MYFX":
calcMYFX(jklx,fxfs,qxdw,investAmt,yearRate,qx);
break;
default:
System.out.println("未识别的还款方式");
break;
}
}
}
/**
* 每月付息
* @param jklx 借款方式
* @param fxfs 付息方式
* @param qxdw 期限单位
* @param investAmt 投资金额
* @param yearRate 年利率
* @param qx 借款期限
*/
private static void calcMYFX(String jklx, String fxfs, String qxdw,
BigDecimal investAmt, BigDecimal yearRate,int qx) {
if("MON".equals(fxfs) && "QXMON".equals(qxdw)){
System.out.println("每月付息,自然月付息,收益计算开始...");
BigDecimal monthRate = yearRate.divide(bg12,9,BigDecimal.ROUND_HALF_UP);
System.out.println("月利率:"+monthRate);
Calendar calendar = Calendar.getInstance();
//还款日期
String repayDate = null;
//总收益
BigDecimal sy = bg0;
//月收益
BigDecimal syOFmon = bg0;
//本金
BigDecimal bjOFmon = bg0;
for (int i = 1; i <= qx; i++) {
calendar.add(Calendar.MONTH, 1);
repayDate = sdf.format(calendar.getTime());
syOFmon = investAmt.multiply(monthRate).setScale(2, BigDecimal.ROUND_HALF_UP);
if(i == qx){
bjOFmon = investAmt;
}
sy = sy.add(syOFmon);
//金额判断 金额小于0置为0
if(bjOFmon.compareTo(bg0) < 0){
bjOFmon = bg0;
}
if(syOFmon.compareTo(bg0) < 0){
syOFmon = bg0;
}
System.out.println("第"+i+"期|还款时间:"+repayDate+"|还款本金:"+df.format(bjOFmon)+"|还款利息:"+df.format(syOFmon)+"|本息和:"+df.format(syOFmon.add(bjOFmon)));
}
System.out.println("总收益:"+df.format(sy));
}else{
System.out.println("每月付息,固定日付息(默认15号),收益计算开始...");
Calendar calendar = Calendar.getInstance();
int today = calendar.get(Calendar.DAY_OF_MONTH);
Calendar endDate = Calendar.getInstance();
endDate.add(Calendar.MONTH, qx);
int lastDay = endDate.get(Calendar.DAY_OF_MONTH);
if(today == 15){
System.out.println("今天为15号,请参考自然月付息");
}else{
BigDecimal dayRate = yearRate.divide(bg360,9,BigDecimal.ROUND_HALF_UP);
System.out.println("日利率:"+dayRate);
//还款日期
String repayDate = null;
//总收益
BigDecimal sy = bg0;
//月收益
BigDecimal syOFmon = bg0;
//本金
BigDecimal bjOFmon = bg0;
int fisrtDays = 0;
int lastDays = 0;
qx = qx +1 ;
for (int i = 1; i <= qx; i++) {
//第一期
if(i == 1){
if(today > 15){
// v1.0 存在bug,时间跨年,天数减出来为负数
// int start = calendar.get(Calendar.DAY_OF_YEAR);
// v2.0
long start = calendar.getTimeInMillis();
calendar.add(Calendar.MONTH, 1);
calendar.set(Calendar.DAY_OF_MONTH, 15);
long end = calendar.getTimeInMillis();
fisrtDays = (int) ((end - start) / dayOfMillisecond);
}else{
long start = calendar.getTimeInMillis();
calendar.set(Calendar.DAY_OF_MONTH, 15);
long end = calendar.getTimeInMillis();
fisrtDays = (int) ((end - start) / dayOfMillisecond);
}
syOFmon = investAmt.multiply(dayRate).multiply(new BigDecimal(fisrtDays)).setScale(2, BigDecimal.ROUND_HALF_UP);
//最后一期
}else if(i == qx){
bjOFmon = investAmt;
if(lastDay > 15){
long start = calendar.getTimeInMillis();
long end = endDate.getTimeInMillis();
lastDays = (int) ((end - start) / dayOfMillisecond);
calendar = endDate;
}else{
long end = calendar.getTimeInMillis();
calendar.add(Calendar.MONTH, -1);
calendar.set(Calendar.DAY_OF_MONTH, 15);
long start = endDate.getTimeInMillis();
lastDays = (int) ((end - start) / dayOfMillisecond);
}
syOFmon = investAmt.multiply(dayRate).multiply(new BigDecimal(lastDays)).setScale(2, BigDecimal.ROUND_HALF_UP);
//中间期数
}else{
long start = calendar.getTimeInMillis();
calendar.add(Calendar.MONTH, 1);
long end = calendar.getTimeInMillis();
int days = (int) ((end - start) / dayOfMillisecond);
syOFmon = investAmt.multiply(dayRate)
.multiply(new BigDecimal(days)).setScale(2, BigDecimal.ROUND_HALF_UP);
}
sy = sy.add(syOFmon);
//金额判断 金额小于0置为0
if(bjOFmon.compareTo(bg0) < 0){
bjOFmon = bg0;
}
if(syOFmon.compareTo(bg0) < 0){
syOFmon = bg0;
}
repayDate = sdf.format(calendar.getTime());
System.out.println("第"+i+"期|还款时间:"+repayDate+"|还款本金:"+df.format(bjOFmon)+"|还款利息:"+df.format(syOFmon)+"|本息和:"+df.format(syOFmon.add(bjOFmon)));
}
System.out.println("第一期:"+fisrtDays+"天|最后一期:"+lastDays+"天|其余期数按月计息");
System.out.println("总收益:"+df.format(sy));
}
}
}
/**
* 等额本金
* @param jklx 借款方式
* @param fxfs 付息方式
* @param qxdw 期限单位
* @param investAmt 投资金额
* @param yearRate 年利率
* @param qx 借款期限
*/
private static void calcDEBJ(String jklx, String fxfs, String qxdw,
BigDecimal investAmt, BigDecimal yearRate,int qx) {
if("MON".equals(fxfs) && "QXMON".equals(qxdw)){
System.out.println("等额本金,自然月付息,收益计算开始...");
BigDecimal monthRate = yearRate.divide(bg12,9,BigDecimal.ROUND_HALF_UP);
System.out.println("月利率:"+monthRate);
Calendar calendar = Calendar.getInstance();
//还款日期
String repayDate = null;
//总收益
BigDecimal sy = bg0;
//月收益
BigDecimal syOFmon = bg0;
//每月平均本金
BigDecimal bjOFmon = investAmt.divide(new BigDecimal(qx),2,BigDecimal.ROUND_DOWN);
for (int i = 1; i <= qx; i++) {
calendar.add(Calendar.MONTH, 1);
repayDate = sdf.format(calendar.getTime());
syOFmon = investAmt.multiply(monthRate).setScale(2, BigDecimal.ROUND_HALF_UP);
if(i == qx){
bjOFmon = investAmt;
}
//本金减少
investAmt = investAmt.subtract(bjOFmon);
sy = sy.add(syOFmon);
//金额判断 金额小于0置为0
if(bjOFmon.compareTo(bg0) < 0){
bjOFmon = bg0;
}
if(syOFmon.compareTo(bg0) < 0){
syOFmon = bg0;
}
System.out.println("第"+i+"期|还款时间:"+repayDate+"|还款本金:"+df.format(bjOFmon)+"|还款利息:"+df.format(syOFmon)+"|本息和:"+df.format(syOFmon.add(bjOFmon)));
}
System.out.println("总收益:"+df.format(sy));
}else if("DAY".equals(fxfs) && "QXMON".equals(qxdw)){
System.out.println("等额本金,固定日(默认15号),收益计算开始...");
BigDecimal monthRate = yearRate.divide(bg12,9,BigDecimal.ROUND_HALF_UP);
System.out.println("月利率:"+monthRate);
BigDecimal dayRate = yearRate.divide(bg360,9,BigDecimal.ROUND_HALF_UP);
System.out.println("日利率:"+dayRate);
Calendar calendar = Calendar.getInstance();
int today = calendar.get(Calendar.DAY_OF_MONTH);
Calendar endDate = Calendar.getInstance();
endDate.add(Calendar.MONTH, qx);
int lastDay = endDate.get(Calendar.DAY_OF_MONTH);
//还款日期
String repayDate = null;
//总收益
BigDecimal sy = bg0;
//月收益
BigDecimal syOFmon = bg0;
//月本金
BigDecimal bjOFmon = bg0;
//月平均本金
BigDecimal ypjbjOFmon = investAmt.divide(new BigDecimal(qx),2,BigDecimal.ROUND_HALF_UP);
//首期天数
int fisrtDays = 0;
//尾期天数
int lastDays = 0;
if(lastDay > 15){
long end = endDate.getTimeInMillis();
endDate.set(Calendar.DAY_OF_MONTH, 15);
long start = endDate.getTimeInMillis();
endDate.set(Calendar.DAY_OF_MONTH, today);
lastDays = (int) ((end - start) / dayOfMillisecond);
}else{
lastDays = lastDay;
}
if(today > 15){
long start = calendar.getTimeInMillis();
calendar.add(Calendar.MONTH, 1);
calendar.set(Calendar.DAY_OF_MONTH, 15);
long end = calendar.getTimeInMillis();
fisrtDays = (int) ((end - start) / dayOfMillisecond);
}else{
long start = calendar.getTimeInMillis();
calendar.set(Calendar.DAY_OF_MONTH, 15);
long end = calendar.getTimeInMillis();
fisrtDays = (int) ((end - start) / dayOfMillisecond);
}
//首期与尾期为一个月,则本金按实际天数计算占比
BigDecimal fisOFALL = new BigDecimal(fisrtDays)
.divide(new BigDecimal(fisrtDays)
.add(new BigDecimal(lastDays)),
5,BigDecimal.ROUND_HALF_UP);
qx = qx +1 ;
for (int i = 1; i <= qx; i++) {
//第一期
if(i == 1){
syOFmon = investAmt.multiply(dayRate).multiply(new BigDecimal(fisrtDays)).setScale(2, BigDecimal.ROUND_HALF_UP);
bjOFmon = ypjbjOFmon.multiply(fisOFALL).setScale(2, BigDecimal.ROUND_DOWN);
//最后一期
}else if(i == qx){
syOFmon = investAmt.multiply(dayRate).multiply(new BigDecimal(lastDays)).setScale(2, BigDecimal.ROUND_HALF_UP);
calendar = endDate;
bjOFmon = investAmt;
//中间期数
}else{
bjOFmon = ypjbjOFmon;
syOFmon = investAmt.multiply(monthRate).setScale(2, BigDecimal.ROUND_HALF_UP);
calendar.add(Calendar.MONTH, 1);
}
sy = sy.add(syOFmon);
investAmt = investAmt.subtract(bjOFmon);
//金额判断 金额小于0置为0
if(bjOFmon.compareTo(bg0) < 0){
bjOFmon = bg0;
}
if(syOFmon.compareTo(bg0) < 0){
syOFmon = bg0;
}
repayDate = sdf.format(calendar.getTime());
System.out.println("第"+i+"期|还款时间:"+repayDate+"|还款本金:"+df.format(bjOFmon)+"|还款利息:"+df.format(syOFmon)+"|本息和:"+df.format(syOFmon.add(bjOFmon)));
}
System.out.println("第一期:"+fisrtDays+"天|最后一期:"+lastDays+"天|第一期天数/(第一期天数+最后一期天数):"+fisOFALL+"|其余期数按月计息");
System.out.println("总收益:"+df.format(sy));
}else{
System.out.println("等额本金,不支持借款期限为天");
}
}
/**
* 按季还本
* @param jklx 借款方式
* @param fxfs 付息方式
* @param qxdw 期限单位
* @param investAmt 投资金额
* @param yearRate 年利率
* @param qx 借款期限
*/
private static void calcAJHB(String jklx, String fxfs, String qxdw,
BigDecimal investAmt, BigDecimal yearRate,int qx) {
if("MON".equals(fxfs) && "QXMON".equals(qxdw)){
System.out.println("按季还本,自然月付息,收益计算开始...");
BigDecimal monthRate = yearRate.divide(bg12,9,BigDecimal.ROUND_HALF_UP);
System.out.println("月利率:"+monthRate);
Calendar calendar = Calendar.getInstance();
//还款日期
String repayDate = null;
//总收益
BigDecimal sy = bg0;
//月收益
BigDecimal syOFmon = bg0;
//每月平均本金
BigDecimal bjOFmon = investAmt.divide(new BigDecimal(qx),2,BigDecimal.ROUND_HALF_UP);
for (int i = 1; i <= qx; i++) {
calendar.add(Calendar.MONTH, 1);
repayDate = sdf.format(calendar.getTime());
//季本金
BigDecimal bjOFquarter = bg0;
syOFmon = investAmt.multiply(monthRate).setScale(2, BigDecimal.ROUND_HALF_UP);
//最后一期
if(i == qx){
bjOFquarter = investAmt;
}else{
//减少本金
if(i % 3 == 0){
bjOFquarter = bjOFmon.multiply(bg3);
investAmt = investAmt.subtract(bjOFquarter);
}
}
//金额判断 金额小于0置为0
if(bjOFmon.compareTo(bg0) < 0){
bjOFmon = bg0;
}
if(bjOFquarter.compareTo(bg0) < 0){
bjOFquarter = bg0;
}
sy = sy.add(syOFmon);
System.out.println("第"+i+"期|还款时间:"+repayDate+"|还款本金:"+df.format(bjOFquarter)+"|还款利息:"+df.format(syOFmon)+"|本息和:"+df.format(syOFmon.add(bjOFquarter)));
}
System.out.println("总收益:"+df.format(sy));
}else{
System.out.println("按季还本,不支持固定日方式还款,不支持借款期限为天");
}
}
/**
* 一次付清
* @param jklx 借款方式
* @param fxfs 付息方式
* @param qxdw 期限单位
* @param investAmt 投资金额
* @param yearRate 年利率
* @param qx 借款期限
*/
private static void calcYCFQ(String jklx, String fxfs, String qxdw,
BigDecimal investAmt, BigDecimal yearRate,int qx) {
//累积利息
BigDecimal sy = bg0;
System.out.println("一次付清 ,收益计算开始...");
Calendar calendar = Calendar.getInstance();
//按月
if("QXMON".equals(qxdw)){
calendar.add(Calendar.MONTH, qx);
//利息 = 投资金额 * 项目年利率 *借款期限 / 12 (保留两位小数)
sy = investAmt.multiply(yearRate)
.multiply(new BigDecimal(qx))
.divide(bg12, 2, BigDecimal.ROUND_HALF_UP);
//按天
}else{
calendar.add(Calendar.DAY_OF_YEAR, qx);
//利息 = 投资金额 * 项目年利率 *借款期限 / 360 (保留两位小数)
sy = investAmt.multiply(yearRate)
.multiply(new BigDecimal(qx))
.divide(bg360, 2, BigDecimal.ROUND_HALF_UP);
}
System.out.println("还款时间:"+sdf.format(calendar.getTime())+"|还款本金:"+df.format(investAmt)+"|还款利息:"+df.format(sy)+"|本息和:"+df.format(investAmt.add(sy)));
}
/**
* 等额本息计算
* @param jklx 借款方式
* @param fxfs 付息方式
* @param qxdw 期限单位
* @param investAmt 投资金额
* @param yearRate 年利率
* @param qx 借款期限
*/
private static void calcDEBX(String jklx, String fxfs, String qxdw,
BigDecimal investAmt, BigDecimal yearRate,int qx) {
if("MON".equals(fxfs) && "QXMON".equals(qxdw)){
System.out.println("等额本息,自然月付息,收益计算开始...");
BigDecimal monthRate = yearRate.divide(bg12,9,BigDecimal.ROUND_HALF_UP);
System.out.println("月利率:"+monthRate);
BigDecimal tmp = monthRate.add(bg1).pow(qx);
BigDecimal monthPayTotal = investAmt.multiply(monthRate).multiply(tmp).divide(tmp.subtract(new BigDecimal(1)), 2,BigDecimal.ROUND_DOWN);
System.out.println("每月应付本息:"+monthPayTotal);
Calendar calendar = Calendar.getInstance();
//还款日期
String repayDate = null;
//总收益
BigDecimal sy = bg0;
//月收益
BigDecimal syOFmon = bg0;
//月本金
BigDecimal bjOFmon = bg0;
for (int i = 1; i <= qx; i++) {
calendar.add(Calendar.MONTH, 1);
repayDate = sdf.format(calendar.getTime());
//最后一期
if(i == qx){
bjOFmon = investAmt;
syOFmon = monthPayTotal.subtract(investAmt);
}else{
syOFmon = investAmt.multiply(monthRate).setScale(2, BigDecimal.ROUND_HALF_UP);
bjOFmon = monthPayTotal.subtract(syOFmon);
//减少本金
investAmt = investAmt.subtract(bjOFmon);
}
//金额判断 金额小于0置为0
if(bjOFmon.compareTo(bg0) < 0){
bjOFmon = bg0;
}
if(syOFmon.compareTo(bg0) < 0){
syOFmon = bg0;
}
sy = sy.add(syOFmon);
System.out.println("第"+i+"期|还款时间:"+repayDate+"|还款本金:"+df.format(bjOFmon)+"|还款利息:"+df.format(syOFmon)+"|本息和:"+df.format(syOFmon.add(bjOFmon)));
}
System.out.println("总收益:"+df.format(sy));
}else{
System.out.println("等额本息,不支持固定日方式还款,不支持借款期限为天");
}
}
/*public static void main(String[] args) {
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.YEAR, 2017);
calendar.set(Calendar.MONTH, 1);
calendar.set(Calendar.DAY_OF_YEAR, 31);
System.out.println(sdf.format(calendar.getTime()));
calendar.add(Calendar.MONTH, 1);
System.out.println(sdf.format(calendar.getTime()));
}*/
}