• 追加された行はこの色です。
  • 削除された行はこの色です。
---
category: swing
folder: CalendarViewTable
title: JTableにLocaleを考慮したLocalDateを適用してカレンダーを表示する
tags: [JTable, LocalDate, Locale, Calendar]
author: aterai
pubdate: 2018-01-29T14:57:32+09:00
description: JTableに週の最初の曜日がLocaleに応じて変化するカレンダーを表示します。
image: https://drive.google.com/uc?id=1jXZtiYFaA5ABWsdaRBnPUKqS2_VBDkFqQA
hreflang:
    href: https://java-swing-tips.blogspot.com/2018/01/apply-localdate-considering-locale-to.html
    lang: en
---
* 概要 [#summary]
`JTable`に週の最初の曜日が`Locale`に応じて変化するカレンダーを表示します。

#download(https://drive.google.com/uc?id=1jXZtiYFaA5ABWsdaRBnPUKqS2_VBDkFqQA)

* サンプルコード [#sourcecode]
#code(link){{
class CalendarViewTableModel<T extends LocalDate> extends DefaultTableModel {
class CalendarViewTableModel extends DefaultTableModel {
  private final LocalDate startDate;
  private final WeekFields weekFields = WeekFields.of(Locale.getDefault());
  public CalendarViewTableModel(T date) {
  public CalendarViewTableModel(LocalDate date) {
    super();
    LocalDate firstDayOfMonth = YearMonth.from(date).atDay(1);
    int dowv = firstDayOfMonth.get(weekFields.dayOfWeek()) - 1;
    startDate = firstDayOfMonth.minusDays(dowv);
  }
  @Override public Class<?> getColumnClass(int column) {
    return LocalDate.class;
  }
  @Override public String getColumnName(int column) {
    return weekFields.getFirstDayOfWeek().plus(column)
      .getDisplayName(TextStyle.SHORT_STANDALONE, Locale.getDefault());
  }
  @Override public int getRowCount() {
    return 6;
  }
  @Override public int getColumnCount() {
    return 7;
  }
  @Override public Object getValueAt(int row, int column) {
    return startDate.plusDays(row * getColumnCount() + column);
  }
  @Override public boolean isCellEditable(int row, int column) {
    return false;
  }
}
}}

* 解説 [#explanation]
上記のサンプルでは、`Java 8`から`java.time`パッケージに追加された`LocalDate`を`JTable`のモデルとして使用し、月のカレンダーを表示しています。

- [https://docs.oracle.com/javase/jp/8/docs/api/java/time/temporal/WeekFields.html#getFirstDayOfWeek-- WeekFields#getFirstDayOfWeek()]メソッドで`Locale`に応じた週の最初の曜日を取得して、`JTable`の`0`列目を設定
-- 例: フランスと`ISO-8601`標準では月曜日が週の最初の曜日になる
--- `java -Duser.language=fr -jar example.jar`

#img2(https://drive.google.com/uc?id=1SmGpl6oxRwwb8tZM2Vc0C7oFS_UCT_Ck6Q)

- 土曜と日曜の位置も`6`列目と`0`列目固定ではないので、以下のように`LocalDate.getDayOfWeek()`メソッドで曜日を確認してその背景色を変更する必要がある

#code{{
private class CalendarTableRenderer extends DefaultTableCellRenderer {
  @Override public Component getTableCellRendererComponent(
      JTable table, Object value, boolean selected, boolean focused,
      int row, int column) {
    super.getTableCellRendererComponent(table, value, selected, focused, row, column);
    setHorizontalAlignment(SwingConstants.CENTER);
    if (value instanceof LocalDate) {
      LocalDate d = (LocalDate) value;
      setText(String.valueOf(d.getDayOfMonth()));
      if (YearMonth.from(d).equals(YearMonth.from(currentLocalDate))) {
        setForeground(Color.BLACK);
      } else {
        setForeground(Color.GRAY);
      }
      DayOfWeek dow = d.getDayOfWeek();
      if (d.isEqual(realLocalDate)) {
        setBackground(new Color(220, 255, 220));
      } else if (dow == DayOfWeek.SUNDAY) {
        setBackground(new Color(255, 220, 220));
      } else if (dow == DayOfWeek.SATURDAY) {
        setBackground(new Color(220, 220, 255));
      } else {
        setBackground(Color.WHITE);
      }
    }
    return this;
  }
}
}}

* 参考リンク [#reference]
- [https://docs.oracle.com/javase/jp/8/docs/api/java/time/temporal/WeekFields.html#getFirstDayOfWeek-- WeekFields#getFirstDayOfWeek() (Java Platform SE 8)]
- [https://tips4java.wordpress.com/2015/04/22/local-date-combo/ Local Date Combo « Java Tips Weblog]
- [[JListで月のカーソルキー移動や、週を跨いた日付を範囲選択が可能なカレンダーを作成する>Swing/CalendarViewList]]
-- `JTable`ではなく、`JList`を使用すると上下カーソルキーで週を跨いだ日付の範囲選択が可能

* コメント [#comment]
#comment
#comment