widget-calendar.go 2.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. package glance
  2. import (
  3. "context"
  4. "html/template"
  5. "time"
  6. )
  7. var calendarWidgetTemplate = mustParseTemplate("calendar.html", "widget-base.html")
  8. type calendarWidget struct {
  9. widgetBase `yaml:",inline"`
  10. Calendar *calendar
  11. StartSunday bool `yaml:"start-sunday"`
  12. }
  13. func (widget *calendarWidget) initialize() error {
  14. widget.withTitle("Calendar").withCacheOnTheHour()
  15. return nil
  16. }
  17. func (widget *calendarWidget) update(ctx context.Context) {
  18. widget.Calendar = newCalendar(time.Now(), widget.StartSunday)
  19. widget.withError(nil).scheduleNextUpdate()
  20. }
  21. func (widget *calendarWidget) Render() template.HTML {
  22. return widget.renderTemplate(widget, calendarWidgetTemplate)
  23. }
  24. type calendar struct {
  25. CurrentDay int
  26. CurrentWeekNumber int
  27. CurrentMonthName string
  28. CurrentYear int
  29. Days []int
  30. }
  31. // TODO: very inflexible, refactor to allow more customizability
  32. // TODO: allow changing between showing the previous and next week and the entire month
  33. func newCalendar(now time.Time, startSunday bool) *calendar {
  34. year, week := now.ISOWeek()
  35. weekday := now.Weekday()
  36. if !startSunday {
  37. weekday = (weekday + 6) % 7 // Shift Monday to 0
  38. }
  39. currentMonthDays := daysInMonth(now.Month(), year)
  40. var previousMonthDays int
  41. if previousMonthNumber := now.Month() - 1; previousMonthNumber < 1 {
  42. previousMonthDays = daysInMonth(12, year-1)
  43. } else {
  44. previousMonthDays = daysInMonth(previousMonthNumber, year)
  45. }
  46. startDaysFrom := now.Day() - int(weekday) - 7
  47. days := make([]int, 21)
  48. for i := 0; i < 21; i++ {
  49. day := startDaysFrom + i
  50. if day < 1 {
  51. day = previousMonthDays + day
  52. } else if day > currentMonthDays {
  53. day = day - currentMonthDays
  54. }
  55. days[i] = day
  56. }
  57. return &calendar{
  58. CurrentDay: now.Day(),
  59. CurrentWeekNumber: week,
  60. CurrentMonthName: now.Month().String(),
  61. CurrentYear: year,
  62. Days: days,
  63. }
  64. }
  65. func daysInMonth(m time.Month, year int) int {
  66. return time.Date(year, m+1, 0, 0, 0, 0, 0, time.UTC).Day()
  67. }