最近有小伙伴给我发了一道题目,闲来没事写了一下,如果有什么bug或者更简便的方法,欢迎提出,谢谢!

package com.zxstech.demo.domain.bo;
import lombok.extern.slf4j.Slf4j;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
/**
* 停车场
*
* @author allen
* @date 2021/9/18 14:12
*/
@Slf4j
public class ParkingLot {
//免费停车时间 默认15分钟内免费,包含15分钟
private static final Integer FREE_TIME = 15;
//24小时封顶停车费 默认封顶费用120元
private static final Integer CAPPING_COST = 120;
//入场时间
private static final String START_TIME = "2020-04-01 04:15:12";
//离场时间
private static final String END_TIME = "2020-04-03 05:10:39";
private static Date time = null;
/**
* 字符串转换成日期
*
* @param str String格式日期
* @return date Date格式日期
*/
private static Date strToDate(String str) {
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date date = null;
try {
date = format.parse(str);
} catch (ParseException e) {
e.printStackTrace();
}
return date;
}
/**
* 日期转换成字符串
*
* @param date Date格式日期
* @return str String格式日期
*/
private static String dateToStr(Date date) {
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String str = format.format(date);
return str;
}
/**
* 计算两个时间相隔分钟数
*
* @param startTime 开始时间
* @param endTime 结束时间
* @return 相隔分钟
*/
private static Long getMinute(Date startTime, Date endTime) {
Calendar dateOne = Calendar.getInstance();
Calendar dateTwo = Calendar.getInstance();
dateOne.setTime(endTime);
dateTwo.setTime(startTime);
Long timeOne = dateOne.getTimeInMillis();
Long timeTwo = dateTwo.getTimeInMillis();
Long minute = (timeOne - timeTwo) / (1000 * 60);//转化minute
//判断如果超过,都算下一分钟
if ((timeOne - timeTwo) % (1000 * 60) != 0) {
minute++;
}
return minute;
}
/**
* 计算两个时间相隔秒数
*
* @param startTime 开始时间
* @param endTime 结束时间
* @return 相隔秒
*/
private static Long getSecond(Date startTime, Date endTime) {
Calendar dateOne = Calendar.getInstance();
Calendar dateTwo = Calendar.getInstance();
dateOne.setTime(endTime);
dateTwo.setTime(startTime);
Long timeOne = dateOne.getTimeInMillis();
Long timeTwo = dateTwo.getTimeInMillis();
Long second = (timeOne - timeTwo) / 1000;
return second;
}
/**
* 计算费用
*
* @param startTime 开始时间
* @param endTime 结束时间
* @return 所需费用
*/
private static Integer charging(Date startTime, Date endTime) {
Integer money = 0;
//小于免费时间免费
if (getMinute(startTime, endTime) <= FREE_TIME) {
return money = 0;
}
//开始时间加上免费的时间
Calendar calendar = Calendar.getInstance();
calendar.setTime(startTime);
calendar.add(Calendar.MINUTE, FREE_TIME);
startTime = calendar.getTime();
log.info("开始时间加上免费的时间:{}", dateToStr(startTime));
//计算封顶天数的费用
money = fullChargingDay(startTime, endTime, money);
//不足一天的费用计算
Integer moneyDay = judgementPeriod(time, endTime, 0);
if (moneyDay > CAPPING_COST) {
log.info("单天停车超出封顶金额{}", CAPPING_COST);
moneyDay = CAPPING_COST;
}
money += moneyDay;
return money;
}
/**
* 递归计算封顶费用
*
* @param startTime 开始时间
* @param endTime 结束时间
* @param money 费用
* @return 费用总数
*/
private static Integer fullChargingDay(Date startTime, Date endTime, Integer money) {
//判断时间有没有超过24个小时
if (getMinute(startTime, endTime) > 24 * 60) {
money += CAPPING_COST;
} else {
time = startTime;
return money;
}
//收费时间加上一天以后的时间
Calendar calendar = Calendar.getInstance();
calendar.setTime(startTime);
calendar.add(Calendar.MINUTE, 24 * 60);
startTime = calendar.getTime();
log.info("开始时间加上一天的时间:{},需要交费{}", dateToStr(startTime), money);
money = fullChargingDay(startTime, endTime, money);
return money;
}
/**
* 每天不同时间段费用判断
*
* @param startTime 开始时间
* @param endTime 结束时间
* @param money 费用
* @return 费用总额
*/
private static Integer judgementPeriod(Date startTime, Date endTime, Integer money) {
Calendar calendar = Calendar.getInstance();
calendar.setTime(startTime);
Integer hour = calendar.get(Calendar.HOUR_OF_DAY);
if (hour < 5) {
money += oneDayCharging(startTime, endTime, 0, 5, 2, 'h');
} else if (hour < 7) {
money += oneDayCharging(startTime, endTime, 5, 7, 10, 'h');
} else if (hour < 12) {
money += oneDayCharging(startTime, endTime, 7, 12, 6, 'h');
} else if (hour < 14) {
money += oneDayCharging(startTime, endTime, 12, 14, 10, 'h');
} else if (hour < 18) {
money += oneDayCharging(startTime, endTime, 14, 18, 2, 'h');
} else if (hour < 19) {
money += oneDayCharging(startTime, endTime, 18, 19, 1, 'm');
} else if (hour < 21) {
money += oneDayCharging(startTime, endTime, 19, 21, 20, 'h');
} else {
money += oneDayCharging(startTime, endTime, 21, 24, 6, 'h');
}
if (!endTime.before(time) && !endTime.after(time)) {
return money;
}
money = judgementPeriod(time, endTime, money);
return money;
}
/**
* 一天中不同时间段收费计算
*
* @param startTime 开始时间
* @param endTime 结束时间
* @param startHour 开始小时
* @param endHour 结束小时
* @param m 收费标准
* @param hourOrMin 收费小时或分钟
* @return 收费金额
*/
private static Integer oneDayCharging(Date startTime, Date endTime, Integer startHour, Integer endHour, Integer m, char hourOrMin) {
Integer money = 0;
Calendar calendar = Calendar.getInstance();
calendar.setTime(startTime);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.HOUR_OF_DAY, startHour);
Date startSegment = calendar.getTime();
calendar.set(Calendar.HOUR_OF_DAY, endHour);
Date endSegment = calendar.getTime();
log.info("段开始时间:{},段结束时间:{}", dateToStr(startSegment), dateToStr(endSegment));
if (endTime.before(endSegment)) {
endSegment = endTime;
}
money = segmentTimeCharging(startTime, endSegment, m, hourOrMin);
time = endSegment;
return money;
}
/**
* 小时收费标准计算
*
* @param startTime 开始时间
* @param segmentTime 结束时间
* @param m 金额
* @param hourOrMin 收费小时或分钟
* @return 总额
*/
private static Integer segmentTimeCharging(Date startTime, Date segmentTime, Integer m, char hourOrMin) {
Integer money = 0;
Integer min = 0;
String msg = "";
if (hourOrMin == 'h') {
min = getMinute(startTime, segmentTime).intValue();
msg = "小时";
} else {
min = getSecond(startTime, segmentTime).intValue();
msg = "分钟";
}
if (min % 60 == 0) {
money = (min / 60) * m;
} else {
money = ((min / 60) + 1) * m;
}
log.info("按{}收费:{}元", msg, money);
return money;
}
public static void main(String[] args) {
Date startTime = strToDate(START_TIME);
log.info("本次停车开始时间:{}", dateToStr(startTime));
Date endTime = strToDate(END_TIME);
log.info("本次停车结束时间:{}", dateToStr(endTime));
Integer money = charging(startTime, endTime);
log.info("=================================================================");
Long minute = getMinute(startTime, endTime);
log.info("本次停车共计停了{}天,{}小时,{}分钟", minute / (60 * 24), (minute % (60 * 24)) / 60, (minute % (60 * 24)) % 60);
log.info("所需要缴纳停车费{}元", money);
}
}