最近有小伙伴给我发了一道题目,闲来没事写了一下,如果有什么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); } }