I wanted to get the TimeInMillis value for alternate dates for the next 30 days from any selected date. I tried to get value for the dates using a for loop. But the code always returns the last 3 dates as wrong. Is there any alternate better way to get what i'm doing?
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)
}
}
The answer i'm getting for the above is this. I have logged the Long value as dates for better understanding.
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]
I'm always getting the last 3 dates from previous month. I can't figure out what is wrong with the code.
CodePudding user response:
In the line
val difference = i * singeDateDifference
you are using integer types (Int
in Kotlin), so for large enough results of your multiplication you will get an integer overflow (because Int.MAX_VALUE
is 2147483647
), which means that the result of the multiplication will be a negative value.
That happens for the last 3 difference values, which causes the last 3 dates to be 1 month behind.
Just ensure that the multiplication is done with Long types, one simple way to do that would be to set the date difference factor to Long.
// ensure we use Long when calculating with epoch millis
val singeDateDifference = 86400000L
This will cause the multiplication to be performed with the Long
values and the result will also be a Long
value.
That will fix the bug and print the dates as you would expect.
In general cases time, dates and calendars are not easy to get right and years of work have been put into APIs such as the Time API.
When working with times and dates, my suggestion would be, to use the Time API classes and methods instead. They are in the package java.time
(java.time.*
).
The documentation is here: https://developer.android.com/reference/java/time/package-summary
That will prevent bugs like the one you had, because it allows you to work with higher-level concepts, such as .plusHours(24)
or .plusDays(1)
(which is not the same in all cases!) instead of doing all the calculations manually. Even if you have your own tests, sooner or later you will get something wrong with time, dates and calendars. Not all days are 24 hours long, shocking, I know :) And this is just the first one on a long list of things that we believe about time, that are simply not true.
If you have to support older Android API levels (lower than 26) you need Android Gradle plugin of at least v4.0.0 for the Time API to be available (support for core library desugaring).
If you cannot use that for some reason, add the JSR-310 Android Backport (ThreeTen ABP) as a dependency.
This will add the same Time API under the package org.threeten.bp.*
with same classes and methods as the Time API, which is otherwise only available on Android from API level 26 (without support for core library desugaring). Note that the recommended way is to switch to the newest version of the Android Gradle plugin, because this library's support is winding down.