62,621
社区成员
发帖
与我相关
我的任务
分享package 停车场计费;
//FareRule是计费时段的计费规则的类
public class FareRule {
private int begin; //计费段起始小时
private int end; //计费段结束小时
private int unitPrice; //计费单价
int minute;//0:按小时计费;1:按分钟计费;2:表示该计费规则结束且本条规则也无效
public FareRule() {
}
public FareRule(int begin, int end, int unitPrice, int minute) {
this.begin = begin;
this.end = end;
this.unitPrice = unitPrice;
this.minute = minute;
}
public int getBegin() {
return begin;
}
public void setBegin(int begin) {
this.begin = begin;
}
public int getEnd() {
return end;
}
public void setEnd(int end) {
this.end = end;
}
public int getUnitPrice() {
return unitPrice;
}
public void setUnitPrice(int unitPrice) {
this.unitPrice = unitPrice;
}
public int isMinute() {
return minute;
}
public void setMinute(int minute) {
this.minute = minute;
}
}
//SetFareRule是设置计费规则的类,根据你的题目要求:“时间段计费规则可能调整”
class SetFareRule {//设置规则
static FareRule[] rules = {//题目要求的计费规则
new FareRule(0, 5, 2, 0),
new FareRule(5, 7, 10, 0),
new FareRule(7, 12, 6, 0),
new FareRule(12, 14, 10, 0),
new FareRule(14, 18, 2, 0),
new FareRule(18, 19, 1, 1),
new FareRule(19, 21, 20, 0),
new FareRule(21, 24, 6, 0),
new FareRule(0,0,0,3),
};
public static void setRule(FareRule rule,int index) {//用于修改1条规则
rules[index] = rule;
}
//默认设置,一天24小时,每小时一个时段,清零为下面设置规则准备容器。
public void setRules() {
rules = new FareRule[24];
for(int i=0;i<24;i++) {
rules[i] = new FareRule();
}
}
//修改多条规则
public static void setRules(FareRule[] rs,int beginIdex,int num) {
for(int i=0;i<num;i++) {
rules[beginIdex+i]=rs[i];
}
}
public static void showPriceList() { //打印收费表
System.out.printf("停车收费价格表\n");
for (int i=0; i<rules.length; i++) {
if(rules[i].minute==1)
System.out.printf("%d\t%d点——%d点%d元/分钟\n",
i+1, rules[i].getBegin(),rules[i].getEnd(),
rules[i].getUnitPrice());
else System.out.printf("%d\t%d点——%d点%d元/小时\n",
i+1, rules[i].getBegin(),rules[i].getEnd(),
rules[i].getUnitPrice());
}
}
}
// Fare是计费类
//停车场计费:计费起始时间=(入场时间-免费时间)
//停车超过1年则:计费天数=年数*365;
//(剩余)不满1年:计费天数+=(剩余)天数;
//(剩余)不满24小时,则按时段进行计费。
package 停车场计费;
import java.util.Calendar;
public class Fare {
Calendar enterTime; //入场时间
Calendar begin = Calendar.getInstance();//阶段起始时间
Calendar fareBegin; //计费起始时间
Calendar now = Calendar.getInstance();//汽车出场时间取当前时间
private int freeMinute; //免费时间
private double maxFarePreDay; //1日最大费用
public Fare(int freeMinute, double maxFarePreDay) {
this.freeMinute = freeMinute;
this.maxFarePreDay = maxFarePreDay;
}
public Calendar getEnterTime() {
return enterTime;
}
public void setEnterTime(Calendar enterTime) {
this.enterTime = enterTime;
}
public int getFreeMinute() {
return freeMinute;
}
public void setFreeMinute(int freeMinute) { //根据题目要求这个可变
this.freeMinute = freeMinute;
}
public double getMaxFarePreDay() {
return maxFarePreDay;
}
public void setMaxFareDay(double maxFarePreDay) { //根据题目要求这个可变
this.maxFarePreDay = maxFarePreDay;
}
public void listParkPrice() { //打印收费表
System.out.printf("停车收费价格表\n");
for (int i=0; i<SetFareRule.rules.length; i++) {
if(SetFareRule.rules[i].minute==2) break;
System.out.printf("%d %s\n", i+1, SetFareRule.rules[i]);
}
}
Calendar getBegin() {//获取计费起始时间=入场时间+免费时间
fareBegin = Calendar.getInstance();
fareBegin.setTimeInMillis(enterTime.getTimeInMillis()+freeMinute*60*1000);
return fareBegin;
}
protected double getPrice() {//计费
int day=0; //停车天数
int year=0; //停车年数
double price=0;
/*下面是准备工作*/
getBegin(); //获取计费起始时间
fareBegin.set(Calendar.SECOND,0); //秒不计费,所以计费起始清零
now.set(Calendar.SECOND,0); //出场时间秒也清零
begin.setTimeInMillis(fareBegin.getTimeInMillis()); //初始化阶段计费起始时间
if(begin.getTimeInMillis()>now.getTimeInMillis())
return price; //如果在免费时间段内则收费为0
year=(now.get(Calendar.YEAR) - begin.get(Calendar.YEAR));
if(year>0) {//如果停车超过1年,则停车天数+=年数*365
day = year * 365;
begin.set(Calendar.YEAR,begin.get(Calendar.YEAR)+year);
}
//如果停车未超过1年,则停车天数+=天数
day+=now.get(Calendar.DAY_OF_YEAR)-begin.get(Calendar.DAY_OF_YEAR);
price+=day*maxFarePreDay; //计算按天收费的收费值
//下面是通过查询计费时段规则表(数组)按时段计算收费值
for (FareRule rule : SetFareRule.rules) {
switch (rule.minute) {
case 0: //按小时计费
if (begin.get(Calendar.HOUR_OF_DAY) >= rule.getBegin() &&
begin.get(Calendar.HOUR_OF_DAY) <= rule.getEnd()) {
if(now.get(Calendar.HOUR_OF_DAY)>=rule.getEnd())
price += (rule.getEnd()-begin.get(Calendar.HOUR_OF_DAY)) * rule.getUnitPrice();
else if(begin.get(Calendar.MINUTE)==now.get(Calendar.MINUTE))
price+= (now.get(Calendar.HOUR_OF_DAY)-begin.get(Calendar.HOUR_OF_DAY))*rule.getUnitPrice();
else
price+= (now.get(Calendar.HOUR_OF_DAY)-begin.get(Calendar.HOUR_OF_DAY)+1)*rule.getUnitPrice();
begin.set(Calendar.HOUR_OF_DAY,rule.getEnd());
}
break;
case 1: //按分钟计费
if (begin.get(Calendar.HOUR_OF_DAY) >= rule.getBegin() &&
begin.get(Calendar.HOUR_OF_DAY) <= rule.getEnd()) {
if (begin.getTimeInMillis() != fareBegin.getTimeInMillis())
begin.set(Calendar.MINUTE, 0); //将begin分钟清零
if (now.get(Calendar.HOUR_OF_DAY) >= rule.getEnd())
price += rule.getUnitPrice() * (rule.getEnd() - rule.getBegin()) * 60;
else price += (now.get(Calendar.MINUTE) - begin.get(Calendar.MINUTE)) * rule.getUnitPrice();
begin.set(Calendar.HOUR_OF_DAY, rule.getEnd()); //更新阶段计费起始时间
begin.set(Calendar.MINUTE, 0); //已经按分钟计费了,则分钟数清零
}
break;
}
if(begin.getTimeInMillis()>=now.getTimeInMillis()) break;//计费完成
}
return price;
}
}
package 停车场计费;
import java.text.SimpleDateFormat;
import java.util.Calendar;
public class ParkFare {//模拟停车计费主类
public static void main(String[] args) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
//新进场了一辆车
Fare car = new Fare(15,120.0);
SetFareRule.showPriceList(); //输出停车场收费价目表
try {
System.out.printf("模拟停车\n");
Calendar c1 = Calendar.getInstance();
String[] testData = { //测试数据,汽车入场时间
"20200411184501", "20200411180000",
"20200412151501", "20200412190000",
"20200411114501", "20200411100001",
"20200411114500", "20200411120001",
"20200410234501", "20200411240000",
"20200411214500", "20200411220000"};
for (int i=0; i<testData.length; i++) {
c1.setTime(sdf.parse(testData[i]));
car.setEnterTime(c1); //设置汽车入场时间
System.out.printf("开始时间: %tF %tT\n结束时间: %tF %tT\n",
c1.getTime(), c1.getTime(), car.now.getTime(), car.now.getTime());
System.out.printf("总停车费: %.0f\n", car.getPrice());
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
import exception.IndexException;
// FareRule是计费时段的计费规则的类
public class FareRule {
public static final int MINUTE=1;
private int begin; //计费段起始小时
private int end; //计费段结束小时
private int unitPrice; //计费单价
int minute;//0:按小时计费;1:按分钟计费。
public FareRule() {
}
public FareRule(int begin, int end, int unitPrice, int minute) {
this.begin = begin;
this.end = end;
this.unitPrice = unitPrice;
this.minute = minute;
}
public int getBegin() {
return begin;
}
public void setBegin(int begin) {
this.begin = begin;
}
public int getEnd() {
return end;
}
public void setEnd(int end) {
this.end = end;
}
public int getUnitPrice() {
return unitPrice;
}
public void setUnitPrice(int unitPrice) {
this.unitPrice = unitPrice;
}
public boolean isMinute() {
if(minute==MINUTE) return true;
return false;
}
public void setMinute(int minute) {
this.minute = minute;
}
}
// SetFareRule是设置计费规则的类,根据你的题目要求:“时间段计费规则可能调整”
class SetFareRule {//设置规则
public static final int INIRULE=0;
public static final int RULE=1;
//题目要求的计费规则,为初始规则表,为了程序便于处理,将被转换为按每小时分段规则:rules[]
static FareRule[] iniRules = {
new FareRule(0, 5, 2, 0),
new FareRule(5, 7, 10, 0),
new FareRule(7, 12, 6, 0),
new FareRule(12, 14, 10, 0),
new FareRule(14, 18, 2, 0),
new FareRule(18, 19, 1, 1),
new FareRule(19, 21, 20, 0),
new FareRule(21, 24, 6, 0),
};
//每小时分段计费规则表
static FareRule[] rules;
public static void setRule(FareRule rule,int index) {//用于修改1条规则
rules[index] = rule;
}
//默认设置,一天24小时,每小时一个时段,清零为下面设置规则准备容器。
public static void setRules(int num) {
rules = new FareRule[num];
for(int i=0;i<num;i++) {
rules[i] = new FareRule();
}
}
//初始化规则表rules[]
public static void iniRules(){
setRules(24);
for(FareRule rule: iniRules) {
for(int i=rule.getBegin();i<rule.getEnd();i++) {
rules[i].setBegin(i);
rules[i].setEnd(i+1);
rules[i].setUnitPrice(rule.getUnitPrice());
rules[i].minute = rule.minute;
}
}
}
//修改多条规则
public static void setRules(FareRule[] rs,int beginIdex,int num,int rsType) throws IndexException{
if(beginIdex<0) throw new IndexException(beginIdex);
if (rsType==INIRULE) {
for (int i = 0; i < num; i++) {
iniRules[beginIdex + i] = rs[i];
}
} else {
for (int i = 0; i < num; i++) {
rules[beginIdex + i] = rs[i];
}
}
}
public static void showPriceList() { //打印收费表
System.out.printf("停车收费价格表\n");
for (int i=0; i<rules.length; i++) {
if(rules[i].minute==1)
System.out.printf("%d\t%d点——%d点%d元/分钟\n",
i+1, rules[i].getBegin(),rules[i].getEnd(),
rules[i].getUnitPrice());
else System.out.printf("%d\t%d点——%d点%d元/小时\n",
i+1, rules[i].getBegin(),rules[i].getEnd(),
rules[i].getUnitPrice());
}
}
}
//Fare是计费类
//停车场计费:计费起始时间=(入场时间-免费时间)
//停车超过1年则:计费天数=年数*365;
//(剩余)不满1年:计费天数+=(剩余)天数;
//(剩余)不满24小时,则按时段进行计费。
import java.util.Calendar;
public class Fare {
Calendar enterTime; //入场时间
Calendar begin = Calendar.getInstance();//时段起始时间
Calendar fareBegin; //计费起始时间
Calendar now = Calendar.getInstance();//汽车出场时间取当前时间
private int freeMinute; //免费时间
private double maxFarePreDay; //1日最大费用
public Fare(int freeMinute, double maxFarePreDay) {
this.freeMinute = freeMinute;
this.maxFarePreDay = maxFarePreDay;
}
public Calendar getEnterTime() {
return enterTime;
}
public void setEnterTime(Calendar enterTime) {
this.enterTime = enterTime;
}
public int getFreeMinute() {
return freeMinute;
}
public void setFreeMinute(int freeMinute) { //根据题目要求这个可变
this.freeMinute = freeMinute;
}
public double getMaxFarePreDay() {
return maxFarePreDay;
}
public void setMaxFareDay(double maxFarePreDay) { //根据题目要求这个可变
this.maxFarePreDay = maxFarePreDay;
}
public void listParkPrice() { //打印收费表
System.out.printf("停车收费价格表\n");
for (int i=0; i<SetFareRule.rules.length; i++) {
if(SetFareRule.rules[i].minute==2) break;
System.out.printf("%d %s\n", i+1, SetFareRule.rules[i]);
}
}
Calendar getBegin() {//获取计费起始时间=入场时间+免费时间
fareBegin = Calendar.getInstance();
fareBegin.setTimeInMillis(enterTime.getTimeInMillis()+freeMinute*60*1000);
return fareBegin;
}
protected double getPrice() {//计费
int day=0; //停车天数
int year=0; //停车年数
double price=0; //总停车费
double price24=0; //(剩余)不满24小时停车费,如果该费用超过日封顶停车费,则计封顶停车费
/*下面是准备工作*/
getBegin(); //获取计费起始时间
now.set(Calendar.SECOND,0); //出场时间秒也清零
if(fareBegin.getTimeInMillis()>now.getTimeInMillis())
return price; //如果在免费时间段内则收费为0
year=(now.get(Calendar.YEAR) - fareBegin.get(Calendar.YEAR));
if(year>0) {//如果停车超过1年,则停车天数+=年数*365
day = year * 365;
fareBegin.set(Calendar.YEAR,fareBegin.get(Calendar.YEAR)+year);
}
//如果停车未超过1年,则停车天数+=天数
day+=now.get(Calendar.DAY_OF_YEAR)-fareBegin.get(Calendar.DAY_OF_YEAR);
//时间需要考虑跨0点的情况
if(fareBegin.get(Calendar.HOUR_OF_DAY)>now.get(Calendar.HOUR_OF_DAY)) day--;
price+=day*maxFarePreDay; //计算按天收费的收费值
//下面是通过查询计费时段规则表(数组)按时段计算收费值
FareRule[] rules = SetFareRule.rules; //声明一个局部变量指向计费规则表
begin.setTimeInMillis(fareBegin.getTimeInMillis()); //初始化时段计费起始时间
for (int i=fareBegin.get(Calendar.HOUR_OF_DAY);i<(rules.length+fareBegin.get(Calendar.HOUR_OF_DAY));i++) {
//利用i%rules.length解决了回环(跨0点)问题
switch (rules[i%rules.length].minute) {
case 0: //按小时计费
price24 += rules[i%rules.length].getUnitPrice();
//跟新计费起始时段
begin.set(Calendar.HOUR_OF_DAY, begin.get(Calendar.HOUR_OF_DAY) + 1);
break;
case 1: //按分钟计费
if (begin.get(Calendar.HOUR_OF_DAY) == rules[i%rules.length].getBegin()) {
if (now.get(Calendar.HOUR_OF_DAY) >= rules[i%rules.length].getEnd()) {
price24 += rules[i%rules.length].getUnitPrice() * 60;
//跟新计费起始时段
begin.set(Calendar.HOUR_OF_DAY,begin.get(Calendar.HOUR_OF_DAY)+1);
}
else {
price24 += now.get(Calendar.MINUTE) * rules[i%rules.length].getUnitPrice();
begin.setTimeInMillis(now.getTimeInMillis());
}
}
break;
}
if(begin.getTimeInMillis()>=now.getTimeInMillis()) break;//计费完成
}
if(price24>maxFarePreDay) price+=maxFarePreDay;
else price+=price24;
return price;
}
}
import java.text.SimpleDateFormat;
import java.util.Calendar;
public class ParkFare {//模拟停车计费主类
public static void main(String[] args) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
//新进场了一辆车
Fare car = new Fare(15,120.0);
SetFareRule.iniRules(); //初始化规则表
//SetFareRule.showPriceList(); //输出停车场收费价目表
try {
System.out.printf("模拟停车\n");
Calendar c1 = Calendar.getInstance();
String[] testData = { //测试数据,汽车入场时间
"20200412124501", "2020041220000",
"20200412151501", "20200412190000",
"20200412114501", "20200412100001",
"20200412164500", "20200412120001",
"20200410234501", "20200412240000",
"20200412211500", "20200412203000"};
for (int i=0; i<testData.length; i++) {
c1.setTime(sdf.parse(testData[i]));
car.setEnterTime(c1); //设置汽车入场时间
System.out.printf("开始时间: %tF %tT\t结束时间: %tF %tT\t",
c1.getTime(), c1.getTime(), car.now.getTime(), car.now.getTime());
System.out.printf("总停车费: %.0f\n", car.getPrice());
}
} catch (Exception e) {
e.printStackTrace();
}
}
}

package com.paullbm.timingcost.entity;
/**
* @author paullbm
*/
public class PriceItem {
private int no;
private int start;
private int end;
private int price;
public PriceItem(int no, int start, int end, int price) {
this.no = no;
this.start = start;
this.end = end;
this.price = price;
}
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("[");
sb.append("no=").append(no);
sb.append(",start=").append(start);
sb.append(",end=").append(end);
sb.append(",price=").append(price);
sb.append("]");
return sb.toString();
}
public int getStart() {
return start;
}
public int getEnd() {
return end;
}
public int getPrice() {
return price;
}
}
2.定义一个接口
package com.paullbm.timingcost;
/**
* @author paullbm
*/
public interface ICountCost {
//获取总价
public int getTotalPrice();
}
3.定义一个功能实现类
package com.paullbm.timingcost.impl;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import com.paullbm.timingcost.ICountCost;
import com.paullbm.timingcost.entity.PriceItem;
/**
* @author paullbm
*/
public class CountCost implements ICountCost {
private int freeTimeSecond = 15 * 60; // 15分钟免费时间(秒数)
private int oneDayLimitCost = 120; // 1天的封顶费用
private int oneHourSecond = 60 * 60; // 1小时包含的秒数
private long oneDaySecond = 24 * oneHourSecond; // =86400秒
private long east8ZoneSecond = 8 * oneHourSecond; // 东八区附加秒数
private int[][] listPrices = {
{ 1, 0, 5, 2 },
{ 2, 5, 7, 10 },
{ 3, 7, 12, 6 },
{ 4, 12, 14, 10 },
{ 5, 14, 18, 2 },
{ 6, 18, 19, 1 },
{ 7, 19, 21, 20 },
{ 8, 21, 24, 6 }
};
private String fmtDateStr="yyyy-MM-dd HH:mm:ss";
private ArrayList<PriceItem> itemList = new ArrayList<PriceItem>();
private Date startDate;
private Date endDate;
public CountCost(String startTime, String endTime) {
Date startDate = null;
Date endDate = null;
SimpleDateFormat simdate = new SimpleDateFormat(this.fmtDateStr);
try {
startDate = simdate.parse(startTime);
endDate = simdate.parse(endTime);
} catch (ParseException e) {
e.printStackTrace();
}
this.init(startDate, endDate);
}
public CountCost(Date startDate, Date endDate) {
this.init(startDate, endDate);
}
private void init(Date startDate, Date endDate) {
this.startDate = startDate;
this.endDate = endDate;
for (int i = 0; i < 8; i++) {
PriceItem struct = new PriceItem(
this.listPrices[i][0],
this.listPrices[i][1] * this.oneHourSecond,
this.listPrices[i][2] * this.oneHourSecond,
this.listPrices[i][3]);
this.itemList.add(i, struct);
}
}
@Override
public int getTotalPrice() {
long startTimeSecond = this.startDate.getTime() / 1000;
long endTimeSecond = this.endDate.getTime() / 1000;
if (isFreeTime(startTimeSecond, endTimeSecond)) // 如果是免费时间内
return 0;
int totalPrice = 0;
int limitCost=getLimitCost(startTimeSecond, endTimeSecond);
int normalCost = getWithin1DayCost(startTimeSecond, endTimeSecond);
totalPrice += (limitCost+normalCost);
System.out.println("封顶消费="+limitCost + "元");
System.out.println("普通消费="+normalCost + "元");
return totalPrice;
}
// 判断是否是在免费时间范围内
private boolean isFreeTime(long startTimeSecond, long endTimeSecond) {
long timeDiff = endTimeSecond - startTimeSecond;
if (timeDiff <= freeTimeSecond)
return true;
return false;
}
// 计算封顶费用
private int getLimitCost(long startTimeSecond, long endTimeSecond) {
int limitPrice = 0;
while (true) {
if (endTimeSecond - startTimeSecond >= oneDaySecond) {
limitPrice += oneDayLimitCost;
startTimeSecond += oneDaySecond;
} else {
break;
}
}
return limitPrice;
}
//计算1天以内的小时数的消费金额(要注意跨天问题)
private int getWithin1DayCost(long startTimeSecond, long endTimeSecond) {
int normalPrice = 0;
long relativeStartTimeSecond = (startTimeSecond + east8ZoneSecond) % oneDaySecond
+ freeTimeSecond; //东八区调整再累加免费时长
long relativeEndTimeSecond = (endTimeSecond + east8ZoneSecond) % oneDaySecond;
if (relativeEndTimeSecond < relativeStartTimeSecond) {
//考虑跨天问题,相对结束时间则需要累加1天
relativeEndTimeSecond += oneDaySecond;
}
long offsetTimeSecond = oneHourSecond - (relativeStartTimeSecond % oneHourSecond) + 1; // 计算时间偏移量
boolean isFirst = true;
int index = 0;
int size=itemList.size();
while (relativeStartTimeSecond < relativeEndTimeSecond) {
while(index < size) {
if(relativeStartTimeSecond >= relativeEndTimeSecond)
break;
PriceItem item = itemList.get(index);
if (relativeStartTimeSecond > item.getStart()
&& relativeStartTimeSecond < item.getEnd()) {
normalPrice += item.getPrice();
if (isFirst) { // 首次要添加时间偏移量
relativeStartTimeSecond += offsetTimeSecond;
isFirst = false;
} else { // 之后可进行整小时添加
relativeStartTimeSecond += oneHourSecond;
}
System.out.print(item + ", 阶段性累计消费=" + normalPrice + "元\n");
// System.out.println(", relativeStartTimeSecond=" + relativeStartTimeSecond
// + ", relativeEndTimeSecond=" + relativeEndTimeSecond);
}else{
if(relativeStartTimeSecond > item.getEnd())
index++;
}
}
if (relativeEndTimeSecond > oneDaySecond) {
//如果按条件迭代完this.itemList还能进入此处
//说明存在跨天情况,则需要进行相关调整
relativeStartTimeSecond = 1;
relativeEndTimeSecond -= oneDaySecond;
index = 0;
}
}
return normalPrice;
}
}
4.测试类
package com.paullbm.timingcost.test;
import com.paullbm.timingcost.ICountCost;
import com.paullbm.timingcost.impl.CountCost;
/**
* @author paullbm
*/
public class CountCostTest {
public static void main(String[] args) {
String startTime = "2020-04-01 18:00:01";
String endTime = "2020-04-03 10:00:00";
// String startTime = "2020-04-01 10:15:01";
// String endTime = "2020-04-01 17:00:02";
ICountCost cc = new CountCost(startTime, endTime);
int totalPrice = cc.getTotalPrice();
System.out.println("总消费金额=" + totalPrice+ "元");
}
}
class PriceUnit { //单价类(考虑到单价的单位不同,有按小时的,有按分钟,所以特别做了个单价类以进行单价换算)
private double price;
private int unit; //0:hore, 1:minute
PriceUnit(double price, int unit) {
this.price = price;
this.unit = unit;
}
public double getPrice() {return price;}
public void setPrice(double price) {this.price = price;}
public int getUnit() {return unit;}
public void setUnit(int unit) {this.unit = unit;}
public String toString() {
return String.format("%.0f/%s", price, (unit==0 ? "小时" : "分钟"));
}
public PriceUnit convertUnit(int toUnit) { //单价换算
switch(toUnit) {
case 0:
switch(this.unit) {
case 1:
this.price *= 60;
break;
}
break;
case 1:
switch(this.unit) {
case 0:
this.price /= 60;
break;
}
break;
}
this.unit = toUnit;
return this;
}
}
class ParkPrice extends PriceUnit { //停车时间区间单价类
private int start;
private int end;
public ParkPrice(int start, int end, double price) {
this(start, end, price, 0);
}
public ParkPrice(int start, int end, double price, int unit) {
super(price, unit);
this.start = start;
this.end = end;
}
public int getStart() {return start;}
public int getEnd() {return end;}
public String toString() {
return String.format("%02d:00~%02d:00 %s", start, end, super.toString());
}
public ParkPrice convertUnit(int toUnit) {
super.convertUnit(toUnit);
return this;
}
}
public class ParkFeeSimulator { //模拟停车计费主类
private static ParkPrice parkPrice[] = { //【重点1】:构造一个时间段的价格表数组
new ParkPrice(0, 5, 2),
new ParkPrice(5, 7, 10),
new ParkPrice(7, 12, 6),
new ParkPrice(12, 14, 10),
new ParkPrice(14, 18, 2),
new ParkPrice(18, 19, 1, 1).convertUnit(0), //这个需求不明确,题目要求不足1小时按小时收费,所以统一转成小时单价
new ParkPrice(19, 21, 20),
new ParkPrice(21, 24, 6)
};
private int freeMinute; //免费时间
private double maxFeePreDay; //1日最大费用
public ParkFeeSimulator(int freeMinute, double maxFeePreDay) {
this.freeMinute = freeMinute;
this.maxFeePreDay = maxFeePreDay;
}
public void setFreeMinute(int freeMinute) { //根据题目要求这个可变
this.freeMinute = freeMinute;
}
public void setMaxFeereDay(double maxFeePreDay) { //根据题目要求这个可变
this.maxFeePreDay = maxFeePreDay;
}
public void listParkPrice() { //打印收费表
System.out.printf("停车收费价格表\n");
for (int i=0; i<parkPrice.length; i++) {
System.out.printf("%d %s\n", i+1, parkPrice[i]);
}
}
protected double getParkPrice(int hour) { //【重点2】:通过时间参数从价格表数组查找并取得相应的时区价格
for (ParkPrice pp : parkPrice) {
if (hour > pp.getStart() && hour <= pp.getEnd()) {
return pp.getPrice();
}
}
return 0;
}
public double caculatePartFee(Calendar start, Calendar end) { //根据开始时间,停止时间计费(核心代码)
double fee = 0.0;
int days = 0, hour = 0;
start.add(Calendar.MINUTE, freeMinute); //开始时间修正(加上免费时间)
if (!start.before(end)) { //如果在免费区间
return fee;
}
for (; start.before(end); start.add(Calendar.DATE, 1)) { //【重点3】:算出满整天的日数
days++;
}
if (start.after(end)) { //【重点4】:如果算出跨天后的时间大于结束时间,则说明最后一次跨天计算不满一天
start.add(Calendar.DATE, -1); //所以要回退一天,按小时来计算
days--;
hour = start.get(Calendar.HOUR_OF_DAY); //取出开始时间
if (start.get(Calendar.MINUTE) == 0
&& start.get(Calendar.SECOND) == 0
&& start.get(Calendar.MILLISECOND) == 0) { //如果开始时间刚为整点小时数
hour++; //则修正计费基准为下一小时(因为计时区间是(开始时间,结束时间],不包含整点的开始时间,所以修正为下一小时,确保在计时区间内)
} else { //否则修正时间为整点小时数
start.add(Calendar.HOUR, 1); //即把小时进位
start.set(Calendar.MINUTE, 0); //分钟以下清0
start.set(Calendar.SECOND, 0);
start.set(Calendar.MILLISECOND, 0);
}
fee += getParkPrice(hour); //【重点5】:计算第1小时的费用(放在这里计算是为了避免不满1小时而不进入for循环的情况)
start.add(Calendar.HOUR, 1); //计费后时间累加1小时
for (; !start.after(end); start.add(Calendar.HOUR, 1)) { //【重点6】:循环时间,累加每小时的费用
hour = start.get(Calendar.HOUR_OF_DAY);
fee += getParkPrice(hour); //【重点7】:如果收费编号6按分钟收费,可以改善这里
}
}
fee += days * maxFeePreDay; //【重点8】:最后加上满1整天的最大停车费用
return fee;
}
public static void main(String[] args) {
try {
ParkFeeSimulator ps = new ParkFeeSimulator(15, 120);
ps.listParkPrice();
System.out.printf("模拟停车小例子\n");
Calendar c1 = Calendar.getInstance();
Calendar c2 = Calendar.getInstance();
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
/*
// 从控制台输入数据的情况
Scanner sc = new Scanner(System.in);
System.out.printf("请输入开始时间(格式: yyyyMMddHHmmss):");
String str = sc.nextLine();
c1.setTime(sdf.parse(str));
System.out.printf("请输入结束时间(格式: yyyyMMddHHmmss):");
str = sc.nextLine();
c2.setTime(sdf.parse(str));
*/
String[][] testData = { //测试数据
{"20200401100001", "20200403180000"},
{"20200401110001", "20200401120000"},
{"20200401114501", "20200401120001"},//这个边界数据,这个算不算免费区间?
{"20200401114500", "20200401120001"},//还是这个才算免费区间?根据需求自行修改caculatePartFee方法
{"20200331234501", "20200401240000"},//这两个边界数据,这个算不算24小时满1整天?
{"20200331234500", "20200401240000"} //还是这个才算24小时满一整天?根据需求自行修改caculatePartFee方法
};
for (int i=0; i<testData.length; i++) {
c1.setTime(sdf.parse(testData[i][0]));
c2.setTime(sdf.parse(testData[i][1]));
System.out.printf("开始时间: %tF %tT\n结束时间: %tF %tT\n", c1.getTime(), c1.getTime(), c2.getTime(), c2.getTime());
System.out.printf("总停车费: %.0f\n", ps.caculatePartFee(c1, c2));
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
这个是原题