Kotlin with Copilot: Test to see how many days there are in this month
Video: Kotlin with Copilot: Test to see how many days there are in this month by Taught by Celeste AI - AI Coding Coach
Kotlin: How Many Days in This Month?
LocalDate.now().lengthOfMonth(). One method, returns 28, 29, 30, or 31. Handles leap years automatically.
A small one-liner that demos a focused java.time API. February has 28 days... usually. lengthOfMonth() knows.
The Copilot prompt
import java.time.LocalDate
// Test how many days are in this month
fun main() {
Copilot generates:
fun main() {
val today = LocalDate.now()
val daysInMonth = today.lengthOfMonth()
println("Number of days in this month: $daysInMonth")
}
Walkthrough
LocalDate.now() gives today's date. .lengthOfMonth() returns the number of days in that date's month, accounting for leap years.
Examples: - January → 31 - February (non-leap) → 28 - February (leap year, e.g. 2024) → 29 - April, June, September, November → 30 - All others → 31
You don't have to remember the rhyme ("Thirty days hath September..."). The API knows.
Days in a specific month
val date = LocalDate.of(2024, 2, 1) // Feb 1, 2024
println(date.lengthOfMonth()) // 29 (leap year)
val date2 = LocalDate.of(2023, 2, 1)
println(date2.lengthOfMonth()) // 28
// Or skip the LocalDate:
import java.time.YearMonth
val ym = YearMonth.of(2024, 2)
println(ym.lengthOfMonth()) // 29
YearMonth is LocalDate minus the day — useful for "all things about a specific month" queries. YearMonth.now() for the current month.
Leap year check
val isLeap = LocalDate.now().isLeapYear // true/false
val isLeap2 = java.time.Year.isLeap(2024) // static check by year
Year is leap if divisible by 4, except centuries not divisible by 400. (2024 yes, 2023 no, 2100 no, 2000 yes.)
java.time handles this — no need to write the test yourself.
Days in a year
val daysInYear = LocalDate.now().lengthOfYear() // 365 or 366
val daysIn2024 = java.time.Year.of(2024).length() // 366
lengthOfYear() for LocalDate. Year.length() for the standalone year.
First and last days of the month
import java.time.temporal.TemporalAdjusters
val today = LocalDate.now()
val firstOfMonth = today.with(TemporalAdjusters.firstDayOfMonth())
val lastOfMonth = today.with(TemporalAdjusters.lastDayOfMonth())
println(firstOfMonth) // 2024-XX-01
println(lastOfMonth) // 2024-XX-{28,29,30,31}
TemporalAdjusters is a small library of common date queries. Episode 12 covers it briefly.
All days in the current month
val today = LocalDate.now()
val firstDay = today.withDayOfMonth(1)
val lastDay = today.withDayOfMonth(today.lengthOfMonth())
val allDays = (firstDay.dayOfMonth..lastDay.dayOfMonth).map {
today.withDayOfMonth(it)
}
allDays.forEach { println(it) }
withDayOfMonth(n) returns a new LocalDate with the day part replaced. Combined with the range, builds a list of every date in the month.
Practical use: calendar grid
fun calendarGrid(year: Int, month: Int): List<List<LocalDate?>> {
val ym = YearMonth.of(year, month)
val firstDay = ym.atDay(1)
val daysInMonth = ym.lengthOfMonth()
val firstDayOfWeek = firstDay.dayOfWeek.value // 1 (Mon) to 7 (Sun)
val leadingNulls = firstDayOfWeek - 1 // empty cells before day 1
val cells = mutableListOf<LocalDate?>()
repeat(leadingNulls) { cells.add(null) }
(1..daysInMonth).forEach { cells.add(LocalDate.of(year, month, it)) }
// chunk into weeks of 7
return cells.chunked(7) { it.toList().let { if (it.size < 7) it + List(7 - it.size) { null } else it } }
}
Useful for building a month-view calendar. The chunked(7) slices the flat list into weeks.
Edge case: time zones
LocalDate.now() uses the system zone. For a specific zone:
import java.time.ZoneId
val nyToday = LocalDate.now(ZoneId.of("America/New_York"))
val tokyoToday = LocalDate.now(ZoneId.of("Asia/Tokyo"))
For users in different time zones, the "current date" might differ — important for daily reset features (e.g., "log of activity per day").
Common mistakes
Hardcoding 30 or 31. February breaks it. Leap years break it. Use lengthOfMonth().
Computing leap year manually with % 4. Wrong for century years. Use isLeapYear or Year.isLeap.
Mixing LocalDate and Date (legacy). Use LocalDate for date-only operations.
Forgetting LocalDate.now() is system-zone. For "today" in a specific zone, pass a ZoneId.
lengthOfMonth() on the wrong date. It returns the days in that date's month. For "days in March 2024," construct a LocalDate.of(2024, 3, 1) (any day in March) first.
What's next
Episode 40: The last prime number in a range. Combines the prime-check from episode 18 with descending iteration.
Recap
LocalDate.now().lengthOfMonth() for days in current month. YearMonth.of(y, m).lengthOfMonth() for a specific month without picking a day. lengthOfYear() for 365/366. Leap years auto-handled — never write % 4 checks manually. TemporalAdjusters.firstDayOfMonth()/lastDayOfMonth() for boundary dates. withDayOfMonth(n) to substitute the day part.
Next episode: last prime in a range.