package com.flightfeather.uav.common.utils
|
|
import java.time.Duration
|
import java.time.LocalDateTime
|
import java.time.ZoneId
|
import java.util.*
|
import kotlin.math.max
|
import kotlin.math.min
|
|
/**
|
* @author riku
|
* Date: 2019/9/16
|
*/
|
object TimeUtil {
|
|
|
/**
|
* 是否是第二天或更新的时间
|
*/
|
fun isNextDay(oldTime: Date, newTime: Date): Boolean {
|
val oldC = Calendar.getInstance().apply {
|
time = oldTime
|
}
|
val newC = Calendar.getInstance().apply {
|
time = newTime
|
}
|
|
return when {
|
newC[Calendar.YEAR] > oldC[Calendar.YEAR] -> true
|
newC[Calendar.YEAR] == oldC[Calendar.YEAR] -> newC[Calendar.DAY_OF_YEAR] > oldC[Calendar.DAY_OF_YEAR]
|
else -> false
|
}
|
}
|
|
/**
|
* 获取某段时间在每日中的时段
|
* "凌晨 0 - 6", "早上 6 - 9", "上午 9 - 12", "中午 12 - 14", "下午 14 - 17", "傍晚 17 - 20", "夜间 20 - 0"
|
* 当这段时间跨越了时段时,按照60%的时间所在时段为最终时段,否则采用后一个时段
|
* @return 时段和时段的起止时间 <时段, 开始时间, 结束时间>
|
*/
|
fun getDayTimeTag(start: Date, end: Date): Triple<String, Date, Date>? {
|
var sLocal = LocalDateTime.ofInstant(start.toInstant(), ZoneId.systemDefault())
|
var eLocal = LocalDateTime.ofInstant(end.toInstant(), ZoneId.systemDefault())
|
val duration = Duration.between(sLocal, eLocal)
|
if (duration.toDays() > 1) return null
|
if (duration.isNegative) {
|
val temp = sLocal
|
sLocal = eLocal
|
eLocal = temp
|
}
|
|
val sDay = sLocal.dayOfMonth
|
val eDay = eLocal.dayOfMonth
|
val ranges = listOf(
|
Triple(0, 6, "凌晨"), Triple(6, 9, "早上"),
|
Triple(9, 12, "上午"), Triple(12, 14, "中午"),
|
Triple(14, 17, "下午"), Triple(17, 20, "傍晚"), Triple(20, 24, "夜间")
|
)
|
val periodList = mutableListOf<Pair<Triple<String, Date, Date>, Long>>()
|
|
if (sDay < eDay) {
|
val dayStart = sLocal.plusDays(1).withHour(0).withMinute(0).withSecond(0)
|
val firstRange = sLocal to dayStart
|
val secondRange = dayStart to eLocal
|
ranges.forEachIndexed { i, r ->
|
// 判断时间范围是否和该时段有交集
|
checkPeriodTime(firstRange.first, firstRange.second, r.first to r.second)?.let {
|
val t = firstRange.first.withMinute(0).withSecond(0)
|
periodList.add(
|
Triple(
|
r.third,
|
Date.from(t.withHour(r.first).atZone(ZoneId.systemDefault()).toInstant()),
|
if (r.second == 24) {
|
Date.from(
|
t.withHour(0).plusDays(1).minusSeconds(1)
|
.atZone(ZoneId.systemDefault()).toInstant()
|
)
|
} else {
|
Date.from(t.withHour(r.second).atZone(ZoneId.systemDefault()).toInstant())
|
}
|
) to it.toMinutes()
|
)
|
}
|
checkPeriodTime(secondRange.first, secondRange.second, r.first to r.second)?.let {
|
val t = secondRange.first.withMinute(0).withSecond(0)
|
periodList.add(
|
Triple(
|
r.third,
|
Date.from(t.withHour(r.first).atZone(ZoneId.systemDefault()).toInstant()),
|
if (r.second == 24) {
|
Date.from(
|
t.withHour(0).plusDays(1).minusSeconds(1)
|
.atZone(ZoneId.systemDefault()).toInstant()
|
)
|
} else {
|
Date.from(t.withHour(r.second).atZone(ZoneId.systemDefault()).toInstant())
|
}
|
) to it.toMinutes()
|
)
|
}
|
}
|
} else {
|
val range = sLocal to eLocal
|
ranges.forEachIndexed { i, r ->
|
// 判断时间范围是否和该时段有交集
|
checkPeriodTime(range.first, range.second, r.first to r.second)?.let {
|
val t = range.first.withMinute(0).withSecond(0)
|
periodList.add(
|
Triple(
|
r.third,
|
Date.from(t.withHour(r.first).atZone(ZoneId.systemDefault()).toInstant()),
|
if (r.second == 24) {
|
Date.from(
|
t.withHour(0).plusDays(1).minusSeconds(1)
|
.atZone(ZoneId.systemDefault()).toInstant()
|
)
|
} else {
|
Date.from(t.withHour(r.second).atZone(ZoneId.systemDefault()).toInstant())
|
}
|
) to it.toMinutes()
|
)
|
}
|
}
|
}
|
if (periodList.isEmpty()) return null
|
|
periodList.sortByDescending { it.second }
|
val maxOne = periodList.first()
|
return maxOne.first
|
}
|
|
private fun checkPeriodTime(start: LocalDateTime, end: LocalDateTime, hourRange: Pair<Int, Int>): Duration? {
|
return if (start.hour in hourRange.first..hourRange.second) {
|
Duration.between(
|
start,
|
end.withHour(min(hourRange.second, end.hour)).withMinute(0).withSecond(0)
|
)
|
} else if (start.hour < hourRange.first && end.hour > hourRange.second) {
|
Duration.between(
|
start.withHour(hourRange.first).withMinute(0).withSecond(0),
|
end.withHour(hourRange.second).withMinute(0).withSecond(0),
|
)
|
} else if (end.hour in hourRange.first..hourRange.second) {
|
Duration.between(
|
start.withHour(max(hourRange.first, start.hour)).withMinute(0).withSecond(0),
|
end,
|
)
|
} else {
|
null
|
}
|
}
|
}
|