时间段的拼接

时间:2022-06-23 17:16:00
package com.lihong.DDPush.pms;

import com.lihong.DDPush.mybatis.Parser;
import org.junit.Test;

import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
* Created by lihong10 on 2017/9/30.
*/

public class SplitJoinTest {


public static final String YYYY_MM_DD = "yyyy-MM-dd";
public static final String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss";
public static final long MIN_SECOND = 60 * 1000;
public static final long DAY_OF_MILLISECOND = 24 * 60 * 60 * 1000;
private static final Integer COMPLEMENT = 1;


@Test
public void test() {


List<Integer[]> li01 = new ArrayList<Integer[]>() {{
add(new Integer[]{420, 900});
add(new Integer[]{900, 1140});
add(new Integer[]{1140, 420});
}};

splitTime(stringToDate("2017-09-28 08:10:00", YYYY_MM_DD_HH_MM_SS).getTime(),
stringToDate("2017-09-30 23:10:00", YYYY_MM_DD_HH_MM_SS).getTime(),
li01);

}


/**
* @param crossBeginTime
* @param crossEndTime
* @param timeList 一天中的离散时间段列表, 该列表中的元素, 只有最后一个元素有可能出现开始时间大于结束时间的情况,
* 比如: [07:00 - 15:00, 15:00 - 19:00, 19:00 - 07:00]
* @Author: lihong10
* @Description:
* @Date: 2017/9/30 16:08
*/

public static List<TimePair> splitTime(Long crossBeginTime, Long crossEndTime, List<Integer[]> timeList) {

Date crossBeginDate = new Date(crossBeginTime);
Date crossEndDate = new Date(crossEndTime);

Integer[] first = timeList.get(0);
if (first[0] > first[1]) {
Collections.reverse(timeList);
first = timeList.get(0);
}
Integer firstStart = first[0];

List<String> dates = getDatesBetween(crossBeginDate, crossEndDate);
List<TimePair> pairs = new ArrayList<TimePair>();

for (int i = 0; i < dates.size(); i++) {

String baseDateStr = dates.get(i);

Date baseDate = stringToDate(baseDateStr + " 00:00:00", YYYY_MM_DD_HH_MM_SS);


for (int j = 0; j < timeList.size(); j++) {

Integer[] time = timeList.get(j);
Integer start = time[0];
Integer end = time[1];
String startTimeStr = getTimeStr(start);
String endTimeStr = getTimeStr(end);

if (start < end) {

TimePair.Builder tb = new TimePair.Builder();
tb.startTime(baseDate.getTime() + start * MIN_SECOND)
.endTime(baseDate.getTime() + end * MIN_SECOND)
.startTimeStr(baseDateStr + " " + startTimeStr)
.endTimeStr(baseDateStr + " " + endTimeStr);
pairs.add(tb.build());

}
/*
* 事实上只有最后一项会进入该分支,开始时间如果大于结束时间,则属于跨天的情况,举例:如果timeList是{07:00 ~ 19:00, 19:00~07:00}, 日期(baseDateStr)是2017-04-08,
则 19:00~07:00 这个时间段会被拼接为2017-04-08 19:00 ~ 2017-04-09 07:00
*/

else if (start > end) {


Integer fixedEndTime = 0;
if (end > firstStart) {//此处目的是为了保证时段不会重复
fixedEndTime = firstStart;
} else if (end < firstStart) {//这里有似乎无用的if else , 目的是为了做成可以配置的

fixedEndTime = COMPLEMENT == 1 ? firstStart : end;
} else {
fixedEndTime = firstStart;//相等的情况,随意取其中一个的值
}

String nextDateStr = dateToString(new Date(baseDate.getTime() + DAY_OF_MILLISECOND), YYYY_MM_DD);

TimePair.Builder tb = new TimePair.Builder();
tb.startTime(baseDate.getTime() + firstStart * MIN_SECOND)
.endTime(baseDate.getTime() + DAY_OF_MILLISECOND + fixedEndTime * MIN_SECOND)
.startTimeStr(baseDateStr + " " + startTimeStr)
.endTimeStr(nextDateStr + " " + getTimeStr(fixedEndTime));

pairs.add(tb.build());
}

}
}

Integer[] last = timeList.get(timeList.size() - 1);
/*
* 最后一段如果跨天,举例,如果timeList是{07:00 ~ 19:00, 19:00~07:00},入场出场日期都是2017-04-08,则最终拼接结果是
* {
* 2017-04-08 00:00 ~ 2017-04-08 07:00,
* 2017-04-08 07:00 ~ 2017-04-08 19:00,
* 2017-04-08 19:00 ~ 2017-04-09 07:00
* },
*
* 这里if语句的目的是添加2017-04-08 00:00 ~ 2017-04-08 07:00这一段时间
* */

if (last[0] > last[1]) {

String baseDateStr = dates.get(0);

Date baseDate = stringToDate(baseDateStr + " 00:00:00", YYYY_MM_DD_HH_MM_SS);

TimePair.Builder tb = new TimePair.Builder();
tb.startTime(baseDate.getTime())
.endTime(baseDate.getTime() + firstStart * MIN_SECOND)
.startTimeStr(baseDateStr + " 00:00:00").endTimeStr(baseDateStr + " " + getTimeStr(firstStart));

pairs.add(0, tb.build());

}


System.out.println("拼接得到的时间串是:\n" + pairs);
return pairs;

}


private static List<String> getDatesBetween(Date startDate, Date endDate) {
String startDateStr = dateToString(startDate, YYYY_MM_DD);
String endDateStr = dateToString(endDate, YYYY_MM_DD);
startDate = stringToDate(startDateStr + " 00:00:00", YYYY_MM_DD_HH_MM_SS);
endDate = stringToDate(endDateStr + " 00:00:00", YYYY_MM_DD_HH_MM_SS);
List<String> dates = new ArrayList();
Calendar startCalendar = Calendar.getInstance();
startCalendar.clear();
startCalendar.setTime(startDate);
Calendar endCalendar = Calendar.getInstance();
endCalendar.clear();
endCalendar.setTime(endDate);
while (startCalendar.compareTo(endCalendar) <= 0) {
dates.add(dateToString(startCalendar.getTime(), YYYY_MM_DD));
startCalendar.add(Calendar.DAY_OF_YEAR, 1);
}

System.out.println(Parser.parse1("开始日期{}到结束日期{}之间的所有日期是:{}", startDateStr, endDateStr, dates));
return dates;
}


private static String getTimeStr(Integer time) {
time = time == null ? 0 : time;
String hour = time / 60 > 9 ? ("" + time / 60) : ("0" + time / 60);
String minute = time % 60 > 9 ? ("" + time % 60) : ("0" + time % 60);
return hour + ":" + minute + ":00";
}


public static Date stringToDate(String strValue, String strFormat) {
Date date = null;
try {
date = new SimpleDateFormat(strFormat).parse(strValue);
} catch (ParseException e) {
}
return date;
}

public static String dateToString(Date dateValue, String strFormat) {
return new SimpleDateFormat(strFormat).format(dateValue);
}
}


class TimePair {


private Long startTime;

private Long endTime;

private String startTimeStr;

private String endTimeStr;

private Long freeTime;

private Long thresholdTime;

private BigDecimal inThresholdTimeFee;

private BigDecimal overThresholdTimeFee;

private BigDecimal feeBetween;

public TimePair() {
super();
}


public TimePair(Long startTime, Long endTime) {
super();
this.startTime = startTime;
this.endTime = endTime;
}


public void setStartTimeStr(String startTimeStr) {
this.startTimeStr = startTimeStr;
}

public void setEndTimeStr(String endTimeStr) {
this.endTimeStr = endTimeStr;
}


public Long getStartTime() {
return startTime;
}


public void setStartTime(Long startTime) {
this.startTime = startTime;
}


public Long getEndTime() {
return endTime;
}


public void setEndTime(Long endTime) {
this.endTime = endTime;
}


public String getStartTimeStr() {
return startTimeStr;
}


public String getEndTimeStr() {
return endTimeStr;
}

public Long getFreeTime() {
return freeTime;
}


public void setFreeTime(Long freeTime) {
this.freeTime = freeTime;
}


public Long getThresholdTime() {
return thresholdTime;
}


public void setThresholdTime(Long thresholdTime) {
this.thresholdTime = thresholdTime;
}


public BigDecimal getInThresholdTimeFee() {
return inThresholdTimeFee;
}


public void setInThresholdTimeFee(BigDecimal inThresholdTimeFee) {
this.inThresholdTimeFee = inThresholdTimeFee;
}


public BigDecimal getOverThresholdTimeFee() {
return overThresholdTimeFee;
}


public void setOverThresholdTimeFee(BigDecimal overThresholdTimeFee) {
this.overThresholdTimeFee = overThresholdTimeFee;
}

public BigDecimal getFeeBetween() {
return feeBetween;
}


public void setFeeBetween(BigDecimal feeBetween) {
this.feeBetween = feeBetween;
}


/**
* 根据进场时间和出场时间,计算车辆在 startTime ~ endTime 之间的时段内停留了多久
*
* @param crossBeginTime
* @param crossEndTime
* @return
*/

public Long getParkTime(Long crossBeginTime, Long crossEndTime) {

if (crossBeginTime >= crossEndTime) { //入场时间大于出场时间,直接返回
return 0L;
}

if (crossEndTime <= startTime || crossBeginTime >= endTime) {
return 0L;
}

if (crossBeginTime <= startTime && crossEndTime >= startTime && crossEndTime <= endTime) {//
return crossEndTime - startTime >= 0 ? crossEndTime - startTime : 0;
} else if (crossBeginTime <= startTime && crossEndTime >= endTime) {//
return endTime - startTime >= 0 ? endTime - startTime : 0;
} else if (crossBeginTime >= startTime && crossEndTime <= endTime) {//
return crossEndTime - crossBeginTime >= 0 ? crossEndTime - crossBeginTime : 0;
} else if (crossBeginTime >= startTime && crossBeginTime <= endTime && crossEndTime >= endTime) {
return endTime - crossBeginTime >= 0 ? endTime - crossBeginTime : 0;
}

return 0L;

}


/**
* 覆盖父类方法,目的是为了打印详细日志信息
*/

@Override
public String toString() {
return "(" + startTimeStr + " - " + endTimeStr + ")\n";
}


public static class Builder {

private Long startTime;

private Long endTime;

private String startTimeStr;

private String endTimeStr;

private Long freeTime;

private Long thresholdTime;

private BigDecimal inThresholdTimeFee;

private BigDecimal overThresholdTimeFee;

private BigDecimal feeBetween;

public Builder() {
super();
}

// 构建的步骤
public Builder(Long startTime, Long endTime) {
this.startTime = startTime;
this.endTime = endTime;
}

public Builder startTime(Long startTime) {
this.startTime = startTime;
return this;
}

public Builder endTime(Long endTime) {
this.endTime = endTime;
return this;
}

public Builder startTimeStr(String startTimeStr) {
this.startTimeStr = startTimeStr;
return this;
}

public Builder endTimeStr(String endTimeStr) {
this.endTimeStr = endTimeStr;
return this;
}

public Builder freeTime(Long freeTime) {
this.freeTime = freeTime;
return this;
}

public Builder thresholdTime(Long thresholdTime) {
this.thresholdTime = thresholdTime;
return this;
}


public Builder inThresholdTimeFee(BigDecimal inThresholdTimeFee) {
this.inThresholdTimeFee = inThresholdTimeFee;
return this;
}

public Builder overThresholdTimeFee(BigDecimal overThresholdTimeFee) {
this.overThresholdTimeFee = overThresholdTimeFee;
return this;
}


public Builder feeBetween(BigDecimal feeBetween) {
this.feeBetween = feeBetween;
return this;
}

public TimePair build() { // 构建,返回TimePair对象
TimePair pair = new TimePair(startTime, endTime);
pair.setStartTimeStr(startTimeStr);
pair.setEndTimeStr(endTimeStr);
pair.setFreeTime(freeTime);
pair.setThresholdTime(thresholdTime);
pair.setInThresholdTimeFee(inThresholdTimeFee);
pair.setOverThresholdTimeFee(overThresholdTimeFee);
pair.setFeeBetween(feeBetween);
return pair;
}
}


}