| | |
| | | package com.flightfeather.uav.common.utils |
| | | |
| | | import java.text.DateFormat |
| | | import java.text.SimpleDateFormat |
| | | 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 |
| | | */ |
| | | class TimeUtil { |
| | | object TimeUtil { |
| | | |
| | | companion object { |
| | | |
| | | /** |
| | | * 是否是第二天或更新的时间 |
| | | */ |
| | | fun isNextDay(oldTime: Date, newTime: Date): Boolean { |
| | | val oldC = Calendar.getInstance().apply { |
| | | time = oldTime |
| | | } |
| | | val newC = Calendar.getInstance().apply { |
| | | time = newTime |
| | | } |
| | | /** |
| | | * 是否是第二天或更新的时间 |
| | | */ |
| | | 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 |
| | | } |
| | | 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 |
| | | } |
| | | } |
| | | } |