Go言語でカレンダーを出力してみた

obelisk.hatenablog.comここの Ruby 版の移植です。

出力例。

$ go run calender.go
          2018/10
sun mon tue wed thu fri sat
     1   2   3   4   5   6  
 7   8   9  10  11  12  13  
14  15  16  17  18  19  20  
21  22  23  24  25  26  27  
28  29  30  31  

 
コード。
calender.go

package main
import "fmt"
import "strconv"
import "strings"

var month_table = [...]int{0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}

//うるう年か?
func is_uruu(year int) bool {
    return (year % 4 == 0 && year % 100 != 0) || year % 400 == 0
}

//西暦1年1月1日から何日目か(すべてグレゴリオ暦で計算)
func days(year, month, day int) int {
    uruu := func(y int) int {return y / 4 - y / 100 + y / 400}
    month_days := func() int {
        d := 0
        for i := 1; i < month; i++ { d += month_table[i] }
        if is_uruu(year) && month > 2 {d++}
        return d
    }
    y1 := year - 1
    return y1 * 365 + uruu(y1) + month_days() + day - 1
}

//曜日の計算(日曜日が0、月曜日が1, ...)
func week_number(year, month, day int) int {
    return (days(year, month, day) + 1) % 7
}

//カレンダーの出力
func calender(year, month int) {
    gen := func(from, to int) (st string) {
        for i := from; i <= to; i++ {st += fmt.Sprintf("%2d  ", i)}
        return
    }
    
    st := strconv.Itoa(year) + "/" + strconv.Itoa(month)
    fmt.Println(strings.Repeat(" ", (27 - len(st)) / 2) + st)
    fmt.Println("sun mon tue wed thu fri sat")
    
    w := week_number(year, month, 1)
    fmt.Println(strings.Repeat("    ", w) + gen(1, 7 - w))
    
    i := 8 - w
    last := month_table[month]
    if is_uruu(year) && month == 2 {last++}
    for i + 6 <= last {
        fmt.Println(gen(i, i + 6))
        i += 7
    }
    st = gen(i, last)
    if st != "" {fmt.Println(st)}
}

func main() {
    calender(2018, 10)
}