kotlin日期时间戳计算相关

最近碰到一个问题,给定两个时间戳参数(可能间隔不止一天),计算两个参数相差的分钟数。

限制条件:

1、开始时间不能晚于当天8点30分,结束时间不能晚于当天17点30分

2、11点30至13点30这部分的时间若包含需要去除

用到的几个关键方法:

(1)将时间戳转换为一个带有时区信息的日期和时间对象(ZonedDateTime)。

Instant.ofEpochMilli(startMillis).atZone(ZoneId.systemDefault())

(2)计算开始和结束时间相差的分钟数

var totalMinutes = Duration.between(adjustedStart, adjustedEnd).toMinutes()

(3)计算开始和结束时间间隔的天数

val daysBetween = ChronoUnit.DAYS.between(adjustedStart.toLocalDate(), adjustedEnd.toLocalDate())

进入正题:

结合两条限制条件说明:

1、当开始时间早于当天8点30分,开始时间取值为当天8点30分;开始时间晚于当天17点30分,开始时间取值为当天17点30分;开始时间早于当天13点30分且开始时间晚于11点30分,开始时间取值为当天13点30分。

2、当结束时间早于当天8点30分,结束时间取值为当天8点30分;结束时间晚于当天17点30分,结束时间取值当天17点30分;结束时间早于当天13点30分且结束时间晚于当天11点30分,结束时间取值为当天11点30分。

3、当开始时间位于当天8点30分至当天11点30分之间,结束时间位于当天13点30分至当天17点30分之间,若间隔0天,则减去120分钟,若间隔n+1天,则减去(n-1)*120分钟和当天17点30分到次日8点30分相差的的分钟数n*900

新建一个adjustTime()函数用于以上1、2点判定:

fun adjustTime(dateTime: ZonedDateTime): ZonedDateTime {
    val localTime = dateTime.toLocalTime()
    val localDate = dateTime.toLocalDate()

    var adjustedTime = localTime
    if (localTime.isBefore(LocalTime.of(8, 30))) {
        adjustedTime = LocalTime.of(8, 30)
    } else if (localTime.isAfter(LocalTime.of(11, 30)) && localTime.isBefore(LocalTime.of(13, 30))) {
        adjustedTime = LocalTime.of(13, 30)
    } else if (localTime.isAfter(LocalTime.of(17, 30))) {
        adjustedTime = LocalTime.of(17, 30)
    }

    return localDate.atTime(adjustedTime).atZone(dateTime.zone)
}

新建isAfterOrEqualTo()和isBeforeOrEqualTo()函数判定时间是否在某个区间内

fun isAfterOrEqualTo(adjustedStart: ZonedDateTime,a:Int,b:Int):Boolean{
    if(adjustedStart.toLocalTime().isAfter(LocalTime.of(a, b)) || adjustedStart.toLocalTime().equals(LocalTime.of(a, b))){
        return true
    }else{
        return false
    }
}

fun isBeforeOrEqualTo(adjustedStart: ZonedDateTime,a:Int,b:Int):Boolean{
    if(adjustedStart.toLocalTime().isBefore(LocalTime.of(a, b)) || adjustedStart.toLocalTime().equals(LocalTime.of(a, b))){
        return true
    }else{
        return false
    }
}

写完整的函数,计算相差分钟数:

fun calculateMinutesDifference(startMillis: Long, endMillis: Long): Long {
    val startDateTime = Instant.ofEpochMilli(startMillis).atZone(ZoneId.systemDefault())
    val endDateTime = Instant.ofEpochMilli(endMillis).atZone(ZoneId.systemDefault())

    val adjustedStart = adjustTime(startDateTime)
    val adjustedEnd = adjustTime(endDateTime)

    // 检查是否为同一天
    val sameDay = adjustedStart.toLocalDate() == adjustedEnd.toLocalDate()
    var totalMinutes = Duration.between(adjustedStart, adjustedEnd).toMinutes()
    if(sameDay){
        if (isWithinWorkPeriod(adjustedStart, 8, 30, 11, 30) &&
            isWithinWorkPeriod(adjustedEnd, 13, 30, 17, 30)) {
            totalMinutes -= 120
        }
    }else {
        // 不同天
        if (isWithinWorkPeriod(adjustedStart, 8, 30, 11, 30)) totalMinutes -= 120
        if (isWithinWorkPeriod(adjustedEnd, 13, 30, 17, 30)) totalMinutes -= 120

        val daysBetween = ChronoUnit.DAYS.between(adjustedStart.toLocalDate(), adjustedEnd.toLocalDate())
        totalMinutes -= (daysBetween * 900 + (daysBetween - 1) * 120)
    }
    return totalMinutes
}

fun isWithinWorkPeriod(dateTime: ZonedDateTime, startHour: Int, startMinute: Int, endHour: Int, endMinute: Int): Boolean {
    return isAfterOrEqualTo(dateTime, startHour, startMinute) && isBeforeOrEqualTo(dateTime, endHour, endMinute)
}
totalMinutes的值就是两个时间戳在限定条件下相差的分钟数
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值