Calendarクラスを使ってカレンダーを作成しよう!

Java

今回はJavaを使ってコンソールで動くカレンダーを作成していく。アプリ制作時に日付を扱うことも多い、この機会にしっかりと慣れていこう。

作成

今回はターミナルにてVimでの作成を前提としてるが、もちろんエクリプスなどのIDEを使ってもOKだ。

日付部分の作成

まずは基本となる日付の部分を作っていこう。

○以下のようにメインメソッドのあるMyCalendar1.javaを作成する。

import java.util.Calendar;

public class MyCalendar1 {

	public static void main(String[] args) {
		//実行時の日付/時刻情報を持つカレンダーインスタンス作成(ex 2021/01/08 22:00:00)
		Calendar cal=Calendar.getInstance();
		//インタンスの持つ日付情報を1日に変更(ex 2021/01/01 22:00:00)
		cal.set(Calendar.DATE, 1);
		//DAY_OF_WEEKでその日の曜日を返す2021/01/01は金曜なので6
		//(日曜:1,月:2,火:3,,,,土:7)
		//カレンダー的な最初のブランクの数は以下の式で表せる(1日が金なら空白は日、月、火、水、木の5個)
		int beforeBlank=cal.get(Calendar.DAY_OF_WEEK)-1;
		//その月が何日まであるかは以下のメソッドで求められる(1月は31日)
		int daysCount=cal.getActualMaximum(Calendar.DAY_OF_MONTH);
		//ブランクと日数分ループを回す
		for(int i=0;i<beforeBlank+daysCount;i++) {
			String str="";//ブランクは空文字
			//最初のブランク分すぎたら日付
			if(i>=beforeBlank) {
				//カウンター変数iから求める実際の日付
				int date=i+1-beforeBlank;
				str=String.valueOf(date);
			}
			//4文字分のスペースを使って描画
			System.out.printf("%4s", str);
			//7個出力したら改行
			if((i+1) % 7 == 0) {
				System.out.println();
			}
		}
		System.out.println();
	}
}

コンパイルして実行してみよう。以下のように表示されれば成功だ。

曜日見出しの作成

Sum,Monなどの曜日見出しを追加しよう。MyCalendar1.javaをMyCalnedar2.javaと複製してまずはコメントを削除。その後以下を追記する。ファイル名を変えたらクラス名も変えることを忘れないこと。

import java.util.Calendar;

public class MyCalendar2 {

	public static void main(String[] args) {
		Calendar cal=Calendar.getInstance();
		cal.set(Calendar.DATE, 1);
		int beforeBlank=cal.get(Calendar.DAY_OF_WEEK)-1;
		int daysCount=cal.getActualMaximum(Calendar.DAY_OF_MONTH);
		String[] weeks= {"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};
		for(String s:weeks) {
			System.out.printf("%4s",s);
		}
		System.out.println();
		for(int i=0;i<beforeBlank+daysCount;i++) {
			String str="";
			if(i>=beforeBlank) {
				int date=i+1-beforeBlank;
				str=String.valueOf(date);
			}
			System.out.printf("%4s", str);
			if((i+1) % 7 == 0) {
				System.out.println();
			}
		}
		System.out.println();
	}
}

曜日の入った配列を作って拡張forで出力しているだけだ。特に難しい部分はないだろう。以下のようになれば成功だ。だいぶカレンダーらしくなってきた。

年/月表示の追加

このカレンダーがいつのカレンダーなのかを表示しよう。
MyCalendar2.javaをMyCalendar3.javaと複製して
以下の部分を追記する。

import java.util.Calendar;

public class MyCalendar3 {

	public static void main(String[] args) {
		Calendar cal=Calendar.getInstance();
		int year=cal.get(Calendar.YEAR);
		int month=cal.get(Calendar.MONTH)+1;
		cal.set(Calendar.DATE, 1);
		int beforeBlank=cal.get(Calendar.DAY_OF_WEEK)-1;
		int daysCount=cal.getActualMaximum(Calendar.DAY_OF_MONTH);
		System.out.printf("%16d/%d%n",year,month);
		String[] weeks= {"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};
		for(String s:weeks) {
			System.out.printf("%4s",s);
		}
		System.out.println();
		for(int i=0;i<beforeBlank+daysCount;i++) {
			String str="";
			if(i>=beforeBlank) {
				int date=i+1-beforeBlank;
				str=String.valueOf(date);
			}
			System.out.printf("%4s", str);
			if((i+1) % 7 == 0) {
				System.out.println();
			}
		}
		System.out.println();
	}
}

Calendarクラスのインスタンスはgetメソッドを使って情報を個別に取り出せる。
以下は与える引数の一例

Calendar.YEAR //->年
Calendar.MONTH //->月(0~11)
Calendar.DATE //->日(1~31)

私は怒っている!

ここで注目すべきはMONTHを指定したときの戻り値だ。
1月は0
12月は11
で返ってくる。この直感に反する仕様は驚くべきところだ。
しかも
Calendar.DAY_OF_WEEK
で返ってくる曜日は
日:1,月:2…土:7
とこちらは1から始まっている。
この統一感のない仕様を思いついた人、それを止めなかった関係者全員を2~3時間問いただしたい。
コード中8行目に
int month=cal.get(Calendar.MONTH)+1;
と1を足しているのはこの仕様の為だ。

この仕様はわかっていても本当によく間違える。あなたも気をつけてもらいたい。
ここまでで以下のようになっていれば成功だ。

今日に印をつける

今日に印がついているのも面白いさっそくやってみよう。
MyCalendar3.javaをMyCalendar4.javaと複製して以下のように追記する。

import java.util.Calendar;

public class MyCalendar4 {

	public static void main(String[] args) {
		Calendar cal=Calendar.getInstance();
		int year=cal.get(Calendar.YEAR);
		int month=cal.get(Calendar.MONTH)+1;
		int today=cal.get(Calendar.DATE);
		cal.set(Calendar.DATE, 1);
		int beforeBlank=cal.get(Calendar.DAY_OF_WEEK)-1;
		int daysCount=cal.getActualMaximum(Calendar.DAY_OF_MONTH);
		System.out.printf("%16d/%d%n",year,month);
		String[] weeks= {"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};
		for(String s:weeks) {
			System.out.printf("%4s",s);
		}
		System.out.println();
		for(int i=0;i<beforeBlank+daysCount;i++) {
			String str="";
			if(i>=beforeBlank) {
				int date=i+1-beforeBlank;
				str=String.valueOf(date);
				if(date==today) {
					str="*"+str;
				}
			}
			System.out.printf("%4s", str);
			if((i+1) % 7 == 0) {
				System.out.println();
			}
		}
		System.out.println();
	}
}

実行してみよう。以下のように実行日に*がつけば成功だ。

完成

以上で終了だ。今回はカレンダークラスの使い方をメインテーマとし処理自体は手続き型で記述したが、次回はこれにオブジェクト指向を取り入れてアプリ仕立てにする。お楽しみに!

関連記事

オブジェクト指向を使って次の月なども見られるアプリを作ります。

Java
スポンサーリンク
シェアする
mjpurinをフォローする
ジョイタスネット

コメント

タイトルとURLをコピーしました