3ヶ月表示をしてみる

投稿者: | 2015年6月3日

来月が表示できるということは先月の表示もできるはず。であれば今月を挟んで前後の月も表示するcal -3に相当する表示も可能です。

#! /usr/bin/swift
import Foundation
// Date型の引数を受け取り、DateComponents型を返す関数
func getCalComp(date: Date) -> DateComponents {
    let cal: NSCalendar = NSCalendar(calendarIdentifier: NSCalendar.Identifier.gregorian)!
    let components: DateComponents = cal.components([.year, .month, .day, .weekday], from:date)
    return components
}
// 一日始まりのDateComponents型の引数を受け取り、その月を表示する関数
func dispCalendar(components: DateComponents) {
    var cal_seq: [String] = ["日","月","火","水","木","金","土"]
    print("      \(components.month!)月 \(components.year!)")
    var endofmonth: [Int] = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
    if (components.year! % 4) == 0 && (components.year! % 100) != 0 || (components.year! % 400) == 0 {
        endofmonth[2]+=1
    }
    for _ in 0..<42 {
        cal_seq.append("  ")
    }
    var datestring: String
    for var i in 1..<endofmonth[components.month!]+1 {
        if i < 10 {
            datestring = " \(i)"
        } else {
            datestring = "\(i)"
        }
        cal_seq[ (6 + i) + (components.weekday! - 1) ] = datestring
    }
    for var i in 0..<7 {
        for var j in 0..<7 {
            print("\(cal_seq[i * 7 + j]) ", terminator:"")
        }
        print("")
    }
}
// 実質プログラムの始まり
let now: Date = Date()
var cal_comp: DateComponents = getCalComp(date:now)
cal_comp.month!-=1
cal_comp.day! = 1
for var i in 0..<3 {
    var calen: Date = Calendar.current.date(from:cal_comp)!
    cal_comp = getCalComp(date:calen)
    dispCalendar(components:cal_comp)
    cal_comp.month!+=1
}

Date型のデータから年月日と曜日情報を取り出す処理をgetCalCompという関数に、DateComponents型のデータからその月を表示する処理をdispCalendarという関数にまとめることで同じコードの繰り返しを回避します。

関数の書き方については別途解説するとして、38行目で一旦今日時点での日付からgetCalComp関数で得た情報を、39,40行目で先月の1日に置き換えます。これを41〜46行目で各月のカレンダー表示と月送り処理を3回繰り返してやれば、3ヶ月表示の完成です。

macOSのcalには-3オプションはないので、拡張版のxcalでの3ヶ月表示と比較してみます。縦に並んでいるか横に並んでいるかの違いはあるものの、同じ結果が得られました。

threemonths.swift実行結果

※インタープリターで実行するとforループのところで警告が出るのでコンパイルして実行しました。

$ ./threemonths.swift 
./threemonths.swift:21:13: warning: variable 'i' was never mutated; consider changing to 'let' constant
    for var i in 1..<endofmonth[components.month!]+1 {
        ~~~ ^
        let
./threemonths.swift:29:13: warning: variable 'i' was never mutated; consider changing to 'let' constant
    for var i in 0..<7 {
        ~~~ ^
        let
./threemonths.swift:30:17: warning: variable 'j' was never mutated; consider changing to 'let' constant
        for var j in 0..<7 {
            ~~~ ^
            let