You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

108 lines
2.0 KiB

package calendar
import (
"fmt"
"strconv"
)
// this is basically the same as Haskell's "derive Show"
//go:generate stringer -type dayOfWeek
type dayOfWeek int
const (
Sunday dayOfWeek = iota
Monday
Tuesday
Wednesday
Thursday
Friday
Saturday
)
//go:generate stringer -type month
type month int
const (
January month = iota
February
March
April
May
June
July
August
September
October
November
December
)
func next(x dayOfWeek) dayOfWeek {
switch x {
case Saturday: // reset to 0
return Sunday
default:
return dayOfWeek(int(x) + 1)
}
}
func pad(n int) string {
switch {
case n < 10:
return " " + strconv.Itoa(n)
default:
return strconv.Itoa(n)
}
}
const weekHeader = "Su Mo Tu We Th Fr Sa"
func calendarMonth(m month, startDay dayOfWeek, maxDay int) string {
var days func(dayOfWeek, int) string
days = func(d dayOfWeek, n int) string {
switch {
case d == Sunday && n > maxDay:
return "\n"
case n > maxDay:
return "\n\n"
case d == Saturday:
return pad(n) + "\n" + days(Sunday, n+1)
default:
return pad(n) + " " + days(next(d), n+1)
}
}
// spaces is used to add the initial padding in every month,
// depending on the starting day
var spaces func(dayOfWeek) string
spaces = func(currDay dayOfWeek) string {
switch currDay {
case startDay:
return days(startDay, 1)
default:
return " " + spaces(next(currDay))
}
}
return fmt.Sprintf("%v 2020\n%v\n%v", m, weekHeader, spaces(Sunday))
}
func Calendar() {
year := calendarMonth(January, Wednesday, 31) +
calendarMonth(February, Saturday, 29) +
calendarMonth(March, Sunday, 31) +
calendarMonth(April, Wednesday, 30) +
calendarMonth(May, Friday, 31) +
calendarMonth(June, Monday, 30) +
calendarMonth(July, Wednesday, 31) +
calendarMonth(August, Saturday, 31) +
calendarMonth(September, Tuesday, 30) +
calendarMonth(October, Thursday, 31) +
calendarMonth(November, Sunday, 30) +
calendarMonth(December, Tuesday, 31)
fmt.Println(year)
}