计算接下来 30 天隔天的 TimeInMillis 值会给我错误的 Kotlin 日期

Calculating TimeInMillis value for alternate days for the next 30 days gives me wrong dates in Kotlin

我想获取从任何选定日期开始的接下来 30 天的备用日期的 TimeInMillis 值。我尝试使用 for 循环获取日期的值。但是代码总是 returns 最后 3 个日期是错误的。有没有其他更好的方法来完成我正在做的事情?

fun calculateDates(startDate: Long) {
        val singeDateDifference = 86400000
        val cancelledDates = arrayListOf<Long>()
            for (i in 2..30 step 2) {
                val difference = i * singeDateDifference
                cancelledDates.add(startDate + difference)
            }
}

我得到的以上答案是这样的。为了更好地理解,我将 Long 值记录为日期。

startDate: 01/01/2022

[02/01/2022, 04/01/2022, 06/01/2022, 08/01/2022, 10/01/2022, 12/01/2022, 14/01/2022, 16/01/2022, 18/01/2022, 20/01/2022, 22/01/2022, 24/01/2022, 07/12/2021, 09/12/2021, 11/12/2021]

我总是得到上个月的最后 3 个日期。我不知道代码有什么问题。

在行

val difference = i * singeDateDifference

您使用的是整数类型(Kotlin 中的 Int),因此对于足够大的乘法结果,您将得到 integer overflow(因为 Int.MAX_VALUE2147483647 ),这意味着乘法的结果将是一个负值。 最后 3 个差异值会发生这种情况,这会导致最后 3 个日期落后 1 个月。

只要确保乘法是用 Long 类型完成的,一种简单的方法是将日期差异因子设置为 Long。

// ensure we use Long when calculating with epoch millis
val singeDateDifference = 86400000L 

这将导致用 Long 值执行乘法,结果也将是 Long 值。 这将修复错误并按预期打印日期。

在一般情况下,时间、日期和日历都不容易准确,并且多年的工作已经投入 API,例如时间 API。 在处理时间和日期时,我的建议是改用时间 API 类 和方法。它们在包 java.time (java.time.*) 中。 文档在这里:https://developer.android.com/reference/java/time/package-summary

这将防止像您遇到的错误,因为它允许您使用更高级别的概念,例如 .plusHours(24).plusDays(1)(并非在所有情况下都相同! ) 而不是手动进行所有计算。即使您有自己的测试,您迟早会弄错时间、日期和日历。并非所有的日子都是 24 小时,令人震惊,我知道 :) 而这只是 a long list of things that we believe about time, that are simply not true.

上的第一个

如果你必须支持旧的 Android API 级别(低于 26)你需要 Android Gradle 插件至少 v4.0.0+ for the Time API 可用(支持核心库脱糖)。

如果由于某种原因您不能使用它,请将 JSR-310 Android Backport (ThreeTen ABP) 添加为依赖项。 这将在包 org.threeten.bp.* 下添加相同的时间 API,具有与时间 API 相同的 类 和方法,否则只能在 Android 上从 API 26+级(不支持核心库脱糖)。请注意,推荐的方法是切换到最新版本的 Android Gradle 插件,因为该库的支持即将结束。

看这里: https://github.com/JakeWharton/ThreeTenABP