{"slug": "stop-hand-coding-the-japanese-rokuyo-calendar-llm-generated-lunar-logic-silently", "title": "Stop hand-coding the Japanese Rokuyo calendar: LLM-generated lunar logic silently breaks", "summary": "A developer has identified a critical flaw in LLM-generated code for the Japanese Rokuyo calendar: while the lunar date calculation formula is correct, the underlying lunar date conversion is frequently wrong, causing silent date shifts that cascade through an entire year. The developer recommends abandoning hand-coded or LLM-generated lunar conversion functions in favor of the Shirabe Calendar API, which provides accurate Rokuyo, rekichu, and per-purpose date judgments with a free tier of 10,000 calls per month.", "body_md": "Originally published in Japanese on\n\n[Qiita]. This is the English edition.\n\n`curl`\n\n/ `fetch`\n\n/ `requests`\n\n.**Rokuyo (六曜)** is a six-day cycle (Taian / Tomobiki / Sensho / Senbu / Butsumetsu / Shakko) still used across Japan to decide auspicious dates — weddings, funerals, ground-breakings, store openings. If you build anything for the Japanese market that recommends or scores *dates*, you will eventually need it. It looks trivial. It is not.\n\nAsk a coding assistant for \"a function that tells me whether a given date is Taian\" and you'll usually get something shaped like this:\n\n```\n// The \"naive Rokuyo\" an LLM tends to propose\nfunction getRokuyo(gregorianDate: Date): string {\n  // (1) Convert Gregorian -> lunar (year / month / day)\n  const lunar = convertToLunar(gregorianDate);   // <- this is where accidents live\n\n  // (2) Rokuyo = (lunar month + lunar day) mod 6\n  const index = (lunar.month + lunar.day) % 6;\n  return [\"Taian\", \"Shakko\", \"Sensho\", \"Tomobiki\", \"Senbu\", \"Butsumetsu\"][index];\n}\n```\n\nStep (2) is genuinely correct — that mapping is right. The bug is **always** in (1), `convertToLunar`\n\n.\n\n`convertToLunar`\n\nis written (all wrong)\n`lunar-javascript`\n\n.This is the **silent-failure** class — the most common kind of bug in the era of letting an LLM write the code.\n\nThe Rokuyo rule `(lunar month + lunar day) mod 6`\n\nis deterministic and always correct *once the lunar date is right*. The hard part is the lunar date. Japan's old calendar (Tenpō) requires:\n\nDoing this properly means computing **solar and lunar ecliptic longitude at astronomical precision** (VSOP87 and friends). Use an approximation and, on days where the new moon falls near midnight, you shift by one day — and **every subsequent lunar date that year dominoes by one day**.\n\nA widely cited reference implementation is **QREKI** (by Hideaki Takano): hundreds of lines of AWK computing apparent ecliptic longitudes via series expansion. Hand-porting that is, both in volume and in principle, **not the kind of task you should hand to an LLM**.\n\nDrop the self-implementation and hand it to an API designed for AI agents — you win on accuracy, maintenance cost, and ease of AI integration. The examples below use [Shirabe Calendar API](https://shirabe.dev). The free tier is **10,000 calls/month** and you can try it **without an API key**. The `fetch`\n\n/ `requests`\n\nexamples below still pass `X-API-Key`\n\n— it's optional, used to track usage and raise limits.\n\n``` php\n# One date -> Rokuyo, rekichu (auspicious days), kanshi, solar term, all in one response\ncurl https://shirabe.dev/api/v1/calendar/2026-04-15\n```\n\nThe JSON looks like:\n\n```\n{\n  \"date\": \"2026-04-15\",\n  \"rokuyo\": {\n    \"name\": \"大安\",\n    \"reading\": \"Taian\",\n    \"timeSlots\": { \"morning\": \"good\", \"noon\": \"good\", \"afternoon\": \"good\", \"evening\": \"good\" }\n  },\n  \"rekichu\": [\n    { \"name\": \"一粒万倍日\", \"type\": \"auspicious\" }\n  ],\n  \"context\": {\n    \"wedding\": { \"judgment\": \"excellent\", \"score\": 9,\n      \"note\": \"Taian x Ichiryu-manbai-bi. An excellent day for a wedding.\" }\n  },\n  \"summary\": \"Reiwa 8 (2026)-04-15 (Wed) Taian / Ichiryu-manbai-bi. Excellent for weddings and openings.\"\n}\n```\n\nThe key fields are ** context and summary**. Instead of a bare \"Taian\" label, you get a per-purpose judgment (8 categories, each scored 1–10) and a one-line summary. An AI agent can drop that\n\n`summary`\n\nstraight into its answer to the user.\n\n``` js\nconst res = await fetch(\n  \"https://shirabe.dev/api/v1/calendar/2026-04-15\",\n  { headers: { \"X-API-Key\": process.env.SHIRABE_API_KEY! } }\n);\nconst data = await res.json();\nconsole.log(data.rokuyo.name);   // \"大安\" (Taian)\nconsole.log(data.summary);       // \"Reiwa 8 (2026)-04-15 (Wed) Taian ...\"\npython\nimport os, requests\n\nr = requests.get(\n    \"https://shirabe.dev/api/v1/calendar/2026-04-15\",\n    headers={\"X-API-Key\": os.environ[\"SHIRABE_API_KEY\"]},\n    timeout=10,\n)\nprint(r.json()[\"rokuyo\"][\"name\"])\n```\n\nYou're not limited to a single date.\n\n```\n# All Taian/Tomobiki days in April (up to 93 days)\ncurl \"https://shirabe.dev/api/v1/calendar/range?start=2026-04-01&end=2026-04-30&filter_rokuyo=大安,友引\"\n\n# Top 5 best wedding days from April to December, by score\ncurl \"https://shirabe.dev/api/v1/calendar/best-days?purpose=wedding&start=2026-04-01&end=2026-12-31&limit=5\"\n```\n\n`best-days`\n\nis built so an **AI agent can externalize the judgment itself**. Pass a date range and a purpose (\n\n`wedding`\n\n/ `moving`\n\n/ `business`\n\nand 8 categories total) and you get a ranked list of top-scoring days with the reasoning (e.g. Taian × Tensha-bi).Publish an **OpenAPI 3.1 spec** and this kind of API can be called in one shot from ChatGPT GPTs Actions, Claude tool use, Gemini function calling, LangChain, or LlamaIndex. Shirabe serves it directly at [https://shirabe.dev/openapi.yaml](https://shirabe.dev/openapi.yaml).\n\nIn the GPT Builder, \"Create new action\" → paste the OpenAPI URL into Import URL:\n\n```\nhttps://shirabe.dev/openapi.yaml\n```\n\nChoose API Key auth (header name `X-API-Key`\n\n). That's all it takes for a custom GPT to call Shirabe automatically.\n\nFeed the same URL to an OpenAPI loader and it's turned into tools. `operationId`\n\nbecomes the function name by design, so no glue code is needed.\n\n| Dimension | Self-implementation / LLM-generated code | Japanese calendar API (Shirabe etc.) |\n|---|---|---|\n| Lunar accuracy | Approximations slip by a day at new-moon boundaries | Astronomical precision |\n| Rekichu coverage | Implementing the ~13 auspicious-day types is a separate big job | 13+ types out of the box |\n| Per-purpose judgment | Hard to spec and to build | Provided via `context.wedding.score` etc. |\n| Maintenance | Versioning the saku-calculation library, etc. | Zero on the caller side |\n| AI integration | Write your own tool/function definitions | One OpenAPI URL |\n| Initial cost | Looks like zero — but a single wrong-date liability sits behind it | Free tier, 10,000/month |\n\n\"Free because I built it myself\" is only superficially free. **Priced with the business risk of a failure, it usually doesn't pay off** in this domain.\n\n`fetch`\n\n.Sample code is also collected under the `examples`\n\nin [https://shirabe.dev/openapi.yaml](https://shirabe.dev/openapi.yaml). The same URL works whether you're calling from ChatGPT GPTs Actions, Claude tool use, or Gemini function calling.", "url": "https://wpnews.pro/news/stop-hand-coding-the-japanese-rokuyo-calendar-llm-generated-lunar-logic-silently", "canonical_source": "https://dev.to/shirabedev/stop-hand-coding-the-japanese-rokuyo-calendar-llm-generated-lunar-logic-silently-breaks-3pie", "published_at": "2026-06-06 01:37:13+00:00", "updated_at": "2026-06-06 01:42:32.359901+00:00", "lang": "en", "topics": ["artificial-intelligence", "large-language-models", "ai-tools"], "entities": ["Qiita", "Tenpō"], "alternates": {"html": "https://wpnews.pro/news/stop-hand-coding-the-japanese-rokuyo-calendar-llm-generated-lunar-logic-silently", "markdown": "https://wpnews.pro/news/stop-hand-coding-the-japanese-rokuyo-calendar-llm-generated-lunar-logic-silently.md", "text": "https://wpnews.pro/news/stop-hand-coding-the-japanese-rokuyo-calendar-llm-generated-lunar-logic-silently.txt", "jsonld": "https://wpnews.pro/news/stop-hand-coding-the-japanese-rokuyo-calendar-llm-generated-lunar-logic-silently.jsonld"}}