カレンダープログラミングにミョウガ、抜錨します!

Myoga-SB-SDF-A2

Hello~! ミョウガですっ!

Twitterでタイムラインを眺めていたら、「プロ生ちゃん #カレンダープログラミング プチコンテスト 2014」の記事を見つけ、内容に興味が湧いてきたので、わたしもそれに参加することにしました。

1. 言語は何にしよう

応募要件は

  • プログラミング言語は自由(既に応募がある言語でも OK)
  • コードを実行した当月の日曜始まりのカレンダーを出力する
  • 出力形式はサンプルを参考に、細かい点は自由

の3つなので、わたしはよく使っているC#でやってみることにしました。プロジェクトはコンソールアプリでいきます。

2. C#でカレンダーを出力してみよう

C#には、日付と時刻を扱うDateTime型という便利な構造体が.NET Frameworkの標準ライブラリとして用意されています。これを使ってコーディングしてみます。

using System;

namespace Myoga1012_Cal {
    class Program {
        static void Main( string[] args ) {

            // 現在の日付を取得し、当月1日を表すインスタンスを生成します。
            DateTime now = DateTime.Today;
            DateTime day = new DateTime( now.Year, now.Month, 1 );

            // 1日の曜日に合わせてオフセットします。 
            for( int i = 0; i < ( int )day.DayOfWeek; i++ ) Console.Write( "   " );

            // カレンダーを出力します。
            do {
            // 日付を出力します(最大2桁なので、最小フィールド幅を3と指定し、右寄せかつ日付間にスペースを開けます)。
                Console.Write( "{0, 3}", day.Day );
                // dayが土曜日または月末日であれば、改行します。
                if( day.DayOfWeek == DayOfWeek.Saturday ||
                    day.Day == DateTime.DaysInMonth( now.Year, now.Month ) ) Console.WriteLine();

                // dayを1日分進めて、月が変わるまで繰り返します。
            } while( ( day = day.AddDays( 1.0 ) ).Month == now.Month );
        }
    }
}

なお、このプログラムはhttps://gist.github.com/Nia-TN1012/51c59f7cb6661544eee6549f454851b9でも公開されています(※GitHubアカウントの統合のため、ニア側のGistに移動しました)。
(追記:最新版は「Calendar.csを繰り返し文を1つに纏めてみました」にある「Calendar2.cs(GitHub内: Calendar.cs)」です。)

手順としては、DateTime.Todayプロパティで現在の日付を取得し、そこから当月1日を表すインスタンスを生成して、1日の位置のオフセットを行い、AddDaysメソッドで1日進めつつ、コンソール画面に日付を出力します。

※AddDaysメソッドは現在のインスタンス自体の値を変更するのではなく、結果を新しいインスタンスとして返します。従ってdayを1日進めるには、dayにday.AddDays( 1.0 )の戻り値を代入します。
参考 : DateTime.Addメソッド | MSDNライブラリ

12行目の繰り返し条件判定に指定しているDayOfWeekプロパティの戻り値は、DayOfWeek列挙体なのでint型にキャストします。なお、DayOfWeekの列挙子は日曜日が0、月曜日が1、・・・と定義されています(例えば2014年10月1日は水曜日、すなわち3です)。

17行目のコンソール画面への出力で、最小3桁のフィールド幅になるように書式指定しています。日付の値が最大2桁なので、1文字スペースを空けつつ、1~9日は1の位の位置に右寄せすることができます。

19~20行目の条件式で、dayが土曜日または月末日の時に改行されます。月末日の取得には指定した年月の日数を取得するDaysInMonthメソッドを利用します。

このソースコードを実行すると、以下のような結果になります。

実行結果
実行結果

3. おわりに

今回は1日からAddDaysメソッドで進めつつ、Monthプロパティで繰り返し条件判定を行いました。

他にも1日目のDayOfWeekプロパティの値とDayInMonthメソッドの戻り値を併用して、for文などで日付を出力する手もあります。

わたしとしては、せっかくの機会だから、他の言語でもチャレンジしてみようと思います。

Extra

Calendar.csにて、23行目の繰り返し条件判定を以下の式にすると、正しく動作しません。

( day = day.AddDays( 1.0 ) ).Day <= DateTime.DaysInMonth( now.Year, now.Month )

dayが月末の時にAddDaysメソッドで1日進めると、翌月1日を表すインスタンスが返ってくるため、代入後のday.Dayの値はDaysInMonthメソッドの戻り値を超えず、無限ループになってしまいます。

但し、現在の月が2、4、6、9、11月の時は、翌月の28・29日(2月)、30日(4、6、9、11月)の出力後の判定でday.Dayの値はDaysInMonthメソッドの戻り値を超えるため、約2か月分つながったカレンダーが出力されます。

[END]

コメント

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