Hello everyone, how can i get the first, last date...
# kotlinx-datetime
l
Hello everyone, how can i get the first, last date of the week, and the first date, last date of the month from
kotlinx.datetime.LocalDate
?
h
You can't get the first and last date of the week only from a
LocalDate
, because what's the first day of a week depends on the Locale. For example, a week in
en-GB
starts on monday, while a week in
en-US
starts on sunday. AFAIK
kotlinx.datetime
has no support for Locales, and therefore also no support for calendar weeks. For first and last day of the month you can use something like this:
Copy code
val startOfMonth = LocalDate(yourLocalDate.year, yourLocalDate.monthNumber, 1)
val endOfMonth = LocalDate(yourLocalDate.year, yourLocalDate.monthNumber, yourLocalDate.month.length(yourLocalDate.year.isLeapYear()))

fun Int.isLeapYear() = this % 4 == 0 && (this % 100 != 0 || this % 400 == 0)
l
at least for now, i just need `en-US`: i have the following implementation, but i’m not sure if it’s completely right:
Copy code
fun dateRangeTest() {
    val today = Clock.System.now().toLocalDateTime(TimeZone.currentSystemDefault()).date

    val firstWeekDay = today.daysShift(-DayOfWeek.values().indexOf(today.dayOfWeek))
    val lastWeekDay = today.daysShift(DayOfWeek.SUNDAY.ordinal - today.dayOfWeek.ordinal)
    print("++dateRangeTest $firstWeekDay")
    print("++dateRangeTest $lastWeekDay")

    val firstMonthDay = today.minus(DateTimeUnit.DayBased(days =today.dayOfMonth - 1))
    val lastMonthDay =  firstMonthDay.plus(DatePeriod(months = 1)).minus(DatePeriod(days = 1))

    print("++dateRangeTest $firstMonthDay")
    print("++dateRangeTest $lastMonthDay")
}
This is what my function prints:
Copy code
firstWeekDay =  2023-08-14
lastWeekDay = 2023-08-20
firstMonthDay = 2023-08-01
lastMonthDay = 2023-08-31
@hho Thanks for the code. it’s doesn’t compile thought. what is
length
? and I missing some kind of import?
h
oh sh*t … I'm using java.time.Month inadvertently 🤦‍♂️
(because it's just typealiased in kotlinx-datetime-jvm)
👍 1
l
my code crashed on
11-01-2023
😿 with this exception:
Copy code
Uncaught Kotlin exception: kotlin.IllegalArgumentException: Unit duration must be positive, but was 0 days.
This fixed it:
Copy code
/**
 * Get the first and last day of the month.
 * adapted from [Getting days of current week using kotlinx-datetime KMM](<https://stackoverflow.com/a/71396000/7234479>)
 */
fun firstAndLastDayOfTheMonth(): Pair<LocalDate, LocalDate> {
    val today = currentDate()
    val dayOfTheWeekValues = DayOfWeek.values()
    val firstWeekDay = today.daysShift(-dayOfTheWeekValues.indexOf(today.dayOfWeek))
    val lastWeekDay = firstWeekDay.daysShift(dayOfTheWeekValues.count() - 1)
    return Pair(firstWeekDay, lastWeekDay)

}
m
Hello sorry for reviving this old thread. I was checking at the suggested method to know if a year is leap year
fun Int.isLeapYear() = this % 4 == 0 && (this % 100 != 0 || this % 400 == 0)
This seems to make sense, but how come the one provided by java.Time differs a bit?
public static boolean isLeap(long year) {
return ((year & 3) == 0) && ((year % 100) != 0 || (year % 400) == 0);
}
Also assuming the suggested version works fine, looks like a simple addition, is there any reason this is not shipped in the library by default? Cheers!
h
The difference in the Java stdlib one is just an optimization: It checks the divisibility by 4 not via modulo/remainder but instead via checking that the last two bits of the number are
0
(by doing a binary
and
with binary
11
(= decimal
3
) and checking for a result of
0
). This achieves the exact same thing: If the least two bits (for
2
and
1
) aren't set, it means that the number has to be a clean multiple of 4. As to why it's not in the library: It is! … but
internal
and the Team has already decided to keep it like that. 😞
m
Got thanks for the response!