カレンダー作成

例えば2026年2月

日 月 火 水 木 金 土

 1  2  3  4  5  6  7
 8  9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
                        
                        

なら

[
 1, 2, 3, 4, 5, 6, 7,
 8, 9,10,11,12,13,14,
15,16,17,18,19,20,21,
22,23,24,25,26,27,28,
null,null,null,null,null,null,null,
null,null,null,null,null,null,null
]

という42個のリストを作ります。

データ生成関数

まずは日付だけ表示する版です。

private fun createCalendarCells(
    year: Int,
    month: Int
): List<Int?> {

    val firstDay = LocalDate.of(year, month, 1)

    val firstColumn =
        firstDay.dayOfWeek.value % 7

    val daysInMonth =
        firstDay.lengthOfMonth()

    val cells = mutableListOf<Int?>()

    repeat(firstColumn) {
        cells.add(null)
    }

    for (day in 1..daysInMonth) {
        cells.add(day)
    }

    while (cells.size < 42) {
        cells.add(null)
    }

    return cells
}

実際に生成されるデータ

例えば

createCalendarCells(2025, 9)

なら

[
null, 1, 2, 3, 4, 5, 6,
7, 8, 9,10,11,12,13,
14,15,16,17,18,19,20,
21,22,23,24,25,26,27,
28,29,30,null,null,null,null,
null,null,null,null,null,null,null
]

になります。

画面表示

42個を7列ずつ表示します。

val cells = createCalendarCells(
    today.year,
    today.monthValue
)

Column {

    for (week in 0 until 6) {

        Row {

            for (day in 0 until 7) {

                val value =
                    cells[week * 7 + day]

                Button(
                    onClick = {},
                    modifier = Modifier.width(cellWidth)
                ) {
                    Text(
                        text = value?.toString() ?: ""
                    )
                }
            }
        }
    }
}

さらにおすすめ

日付だけではなく

data class CalendarCell(
    val date: LocalDate?,
    val isCurrentMonth: Boolean
)

を使います。

すると

CalendarCell(
    date = LocalDate.of(2025, 9, 15),
    isCurrentMonth = true
)

のように保持できます。

JSON保存

LocalDate は ISO-8601形式の文字列にできます。

val date = LocalDate.of(2026, 7, 13)

val str = date.toString()

結果

2026-07-13

JSON

{
  "date": "2026-07-13"
}

この形式は

  • 人間が読める
  • ソートできる
  • 復元が簡単

ので非常に便利です。

復元

val date = LocalDate.parse("2026-07-13")

だけです。

年月日の比較

例えば

val d1 = LocalDate.of(2026, 7, 13)
val d2 = LocalDate.of(2026, 7, 20)

なら

d1 == d2
d1.isBefore(d2)
d1.isAfter(d2)

が使えます。

年だけ比較

if (d1.year == d2.year) {
}

年月だけ比較

if (
    d1.year == d2.year &&
    d1.monthValue == d2.monthValue
) {
}

ただし後述する YearMonth の方がおすすめです。

月移動で便利な YearMonth

カレンダーでは

2026/07

だけを扱う場面が非常に多いです。

そんな時は

import java.time.YearMonth

val currentMonth = YearMonth.now()

を使います。

前月

currentMonth.minusMonths(1)

次月

currentMonth.plusMonths(1)

表示

currentMonth.format(
    DateTimeFormatter.ofPattern("yyyy/MM")
)

その月の1日

val firstDay = currentMonth.atDay(1)

月末

val lastDay = currentMonth.atEndOfMonth()
タイトルとURLをコピーしました