feiyu02
2025-09-30 94fee0b511279679b43e210878d3d36e5a14384b
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
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
        }
    }
}