3ヶ月表示を整えてみる(1)

投稿者: | 2015年6月8日

さて、とりあえず動かした3ヶ月表示をしてみるですが、本物のcalコマンドと同じく横並び表示をしてみましょう。

#! /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 getCalendar(components: DateComponents) -> [String] {
    var cal_seq: [String] = ["日","月","火","水","木","金","土"]
    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
    }
    return cal_seq
}
// 実質プログラムの始まり
let je_flag = 1
let now: Date = Date()
var cal_comp: DateComponents = getCalComp(date:now)
cal_comp.month!-=1
cal_comp.day! = 1
var sequence: [String] = []
var header: String = ""
var header_y: String = ""
var header_m: [String] = ["", "", ""]
for var i in 0..<3 {
    var calen: Date = Calendar.current.date(from:cal_comp)!
    cal_comp = getCalComp(date:calen)
    sequence += getCalendar(components:cal_comp)
    if i == 1 { header_y += "\(cal_comp.year!)" }
    header_m[i] = "\(cal_comp.month!)月"
    cal_comp.month!+=1
}
var length: Int = (65 - header_y.characters.count) / 2
for var i in 0..<length+1 {
    header_y = " " + header_y
}
print("\(header_y)\n")
for var i in 0..<3 {
    length = (21 - (header_m[i].characters.count + je_flag)) / 2
    for var j in 0..<length {
        header_m[i] = " " + header_m[i]
    }
    length = 22 - (header_m[i].characters.count + je_flag)
    for var j in 0..<length {
        header_m[i] = header_m[i] + " "
    }
    header += header_m[i]
}
print(header)
for var i in 0..<7 {
    for var j in 0..<3 {
        for var k in 0..<7 {
            print("\(sequence[i * 7 + (j * 49 + k)]) ", terminator:"")
        }
        print(" ", terminator:"")
    }
    print("")
}

前回のものはカレンダーの計算と表示をひとまとめにした関数でしたが、今回は3ヶ月分の計算が終わったらまとめて表示をしたいので、関数から表示部を取り除きました。

とりあえずカレンダー計算部のgetCalendarを解説します。実は前回のdispCalendarの時点で、少し振る舞いを変えていました。

今月の第1週を表示してみるでは、今日の日付と曜日から第1週中に先月が何日分あるかを計算しましたが、カレンダー計算用の関数は常に毎月1日の日付から計算を始めるので、そこから導き出された曜日を見れば先月が何日あるかがすぐにわかります。

曜日はとりあえず今日を表示してみるにあったように、weekDayにセットされた1から7の値が日曜から土曜に相当するので、26行目のように

weekday - 1

が第1週中の先月の日数になります。これを配列cal_seq[]の添え字に加算することで、今月の始まりを調整しています。この辺は今月を表示してみるに説明してある内容ですね。

こうして導き出された、最初の7つが日から土まであって、残りの42個中の適切な位置から今月が始まり、先月と来月の値が空白である49個の要素を持つ配列cal_seq[]を返す関数がgetCalendar関数です。

長くなったので、実質プログラムの部分はまた別項にて。