Switching My Go Holiday Library shukujitsu from the Google Calendar API to Japan's Official Cabinet Office CSV
I switched the data source of shukujitsu, my Go library for Japanese national holidays, from the Google Calendar API to the official CSV published by Japan’s Cabinet Office (the primary source).
This freed me from maintaining a manual exclusion list and an API key, and slashed the dependency tree. Here’s the story.
What is shukujitsu?
A library that embeds a date-to-holiday-name map (shukujitsu.yml) via go:embed and provides IsHoliday(t) / HolidayName(t). The data is auto-updated by a weekly GitHub Actions cron.
What Was Wrong with the Google Calendar API
The library used to fetch from Google Calendar’s Japanese holiday calendar (ja.japanese#holiday@group.v.calendar.google.com), which had these problems:
- Non-holiday events leak in. The calendar includes Tanabata, Mother’s Day, Setsubun, Christmas and so on, so I maintained an exclusion list by hand:
1 | var excludedSummaries = map[string]bool{ |
- A
GOOGLE_CALENDAR_API_KEYhad to be managed in GitHub Secrets - The
google.golang.org/apidependency tree is heavy - The data range depended on whatever Google returned
The Cabinet Office’s national holiday CSV is the primary source itself — no event noise, so the exclusion list disappears entirely.
Implementation
Decoding Shift_JIS
The Cabinet Office CSV is encoded in Shift_JIS. I decode the stream with transform.NewReader from golang.org/x/text before parsing with encoding/csv.
1 | // fetchHolidays : fetch the Cabinet Office CSV (Shift_JIS) and return records minus the header row |
The date format trap
Dates in the CSV look like 2021/7/22 — slash-separated without zero padding. The Go time layout must be "2006/1/2" (parsing fails with "2006/01/02").
1 | for _, row := range rows { |
Removing Secrets from CI
The workflow no longer needs an API key — it just runs go run:
1 | - - name: auto update shukujitsu.yml by google calendar api |
Dependencies went from google.golang.org/api v0.97.0 plus 15 indirect packages down to just golang.org/x/text, removing 675 lines from go.sum.
Behavioral Changes (Caveats)
- Holiday name strings changed. Substitute holidays and citizens’ holidays are now uniformly named 「休日」 following the government CSV (previously they had detailed Google-derived names like 「海の日 振替休日」). If you depend on the strings returned by
HolidayName, this is close to a breaking change - The data range changed. It now extends back to 1955 (previously from 2021), and forward only to the years officially confirmed by the government (2027 at the moment, previously 2030)
Summary
- Switched the holiday data source to the primary source (Cabinet Office CSV), eliminating the exclusion list, the API key, and heavy dependencies
- Key points: decode with
japanese.ShiftJIS.NewDecoder(), parse dates with layout"2006/1/2" - Watch out for the changed holiday name strings and data range
I hope you find it useful.
- Repository: kenzo0107/shukujitsu
