Part of Github Copilot with Kotlin

Kotlin with Copilot: Test to see how many days there are in this month

Sandy LaneSandy Lane

Video: Kotlin with Copilot: Test to see how many days there are in this month by Taught by Celeste AI - AI Coding Coach

Take the quiz on the full lesson page
Test what you've read · interactive walkthrough

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.

Ready? Take the quiz on the full lesson page →
Test what you've learned. Watch the lesson and try the interactive quiz on the same page.