<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Shirabe Dev</title>
    <description>The latest articles on DEV Community by Shirabe Dev (@shirabedev).</description>
    <link>https://dev.to/shirabedev</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3968954%2F1fb13ea7-e1e9-4667-9f66-51e98e4296f3.png</url>
      <title>DEV Community: Shirabe Dev</title>
      <link>https://dev.to/shirabedev</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/shirabedev"/>
    <language>en</language>
    <item>
      <title>Stop hand-coding the Japanese Rokuyo calendar: LLM-generated lunar logic silently breaks</title>
      <dc:creator>Shirabe Dev</dc:creator>
      <pubDate>Sat, 06 Jun 2026 01:37:13 +0000</pubDate>
      <link>https://dev.to/shirabedev/stop-hand-coding-the-japanese-rokuyo-calendar-llm-generated-lunar-logic-silently-breaks-3pie</link>
      <guid>https://dev.to/shirabedev/stop-hand-coding-the-japanese-rokuyo-calendar-llm-generated-lunar-logic-silently-breaks-3pie</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Originally published in Japanese on &lt;a href="https://qiita.com/yosikawa-techwell/items/f21d666a7fad06cdbb51" rel="noopener noreferrer"&gt;Qiita&lt;/a&gt;. This is the English edition.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Business requirements that touch the Japanese &lt;strong&gt;Rokuyo&lt;/strong&gt; calendar are surging in the LLM era — wedding-date pickers, moving-day scorers, fortune-telling chatbots.&lt;/li&gt;
&lt;li&gt;But if you &lt;strong&gt;compute Rokuyo yourself&lt;/strong&gt;, you get a class of bug that &lt;em&gt;silently&lt;/em&gt; miscalculates on specific dates.&lt;/li&gt;
&lt;li&gt;The root cause is &lt;strong&gt;not&lt;/strong&gt; the Rokuyo formula. It's the step before it: converting the &lt;strong&gt;Gregorian date to the Japanese lunar calendar requires astronomical precision&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;The fix is to put an AI-agent-oriented Japanese calendar API in front of it (e.g. &lt;a href="https://shirabe.dev" rel="noopener noreferrer"&gt;Shirabe Calendar API&lt;/a&gt;). It's 3 lines of &lt;code&gt;curl&lt;/code&gt; / &lt;code&gt;fetch&lt;/code&gt; / &lt;code&gt;requests&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What is Rokuyo, briefly
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Rokuyo (六曜)&lt;/strong&gt; 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 &lt;em&gt;dates&lt;/em&gt;, you will eventually need it. It looks trivial. It is not.&lt;/p&gt;

&lt;h2&gt;
  
  
  Who this is for
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Full-stack engineers building LLM agents / AI SaaS.&lt;/li&gt;
&lt;li&gt;Anyone who once thought "Rokuyo? I can just write that myself."&lt;/li&gt;
&lt;li&gt;Anyone who has shipped LLM-generated date logic to production.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  The problem: what happens when you ask an AI to "compute Rokuyo"
&lt;/h2&gt;

&lt;p&gt;Ask a coding assistant for "a function that tells me whether a given date is Taian" and you'll usually get something shaped like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// The "naive Rokuyo" an LLM tends to propose&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getRokuyo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;gregorianDate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// (1) Convert Gregorian -&amp;gt; lunar (year / month / day)&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;lunar&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;convertToLunar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;gregorianDate&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;   &lt;span class="c1"&gt;// &amp;lt;- this is where accidents live&lt;/span&gt;

  &lt;span class="c1"&gt;// (2) Rokuyo = (lunar month + lunar day) mod 6&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;lunar&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;month&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;lunar&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;day&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Taian&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Shakko&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Sensho&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Tomobiki&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Senbu&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Butsumetsu&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Step (2) is genuinely correct — that mapping is right. The bug is &lt;strong&gt;always&lt;/strong&gt; in (1), &lt;code&gt;convertToLunar&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  The usual ways &lt;code&gt;convertToLunar&lt;/code&gt; is written (all wrong)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Counting days from the last new moon using a 29.5-day period.&lt;/strong&gt; The synodic month actually varies between 29.27 and 29.84 days. Even using the mean 29.5306, run it for a year and you drift by days.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Embedding some lunar-conversion table found online.&lt;/strong&gt; Past the table's terminal year it silently drifts, and leap-month handling differs table to table.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reusing a Chinese-lunar (农历) library like &lt;code&gt;lunar-javascript&lt;/code&gt;.&lt;/strong&gt; Japan's Tenpō calendar and the Chinese calendar differ in the reference timezone for the new moon (UTC+8 vs UTC+9) and in leap-month placement — so a few dates per year diverge.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A 30–50 line formula the LLM wrote.&lt;/strong&gt; The solar/lunar ecliptic-longitude approximation is sloppy by one digit somewhere, and &lt;strong&gt;dates landing on the new-moon day boundary&lt;/strong&gt; come out one day off.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Why the drift is scary
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;It never throws.&lt;/strong&gt; Types pass, no exception, always returns a Rokuyo-looking string.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tests miss it.&lt;/strong&gt; It's wrong on only 2–3 pinpoint days, so sampling tests pass.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;You find out on the wedding day.&lt;/strong&gt; The day you advertised as "Taian" turns out to be "Butsumetsu."&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is the &lt;strong&gt;silent-failure&lt;/strong&gt; class — the most common kind of bug in the era of letting an LLM write the code.&lt;/p&gt;




&lt;h2&gt;
  
  
  Root cause: lunar conversion needs astronomy
&lt;/h2&gt;

&lt;p&gt;The Rokuyo rule &lt;code&gt;(lunar month + lunar day) mod 6&lt;/code&gt; is deterministic and always correct &lt;em&gt;once the lunar date is right&lt;/em&gt;. The hard part is the lunar date. Japan's old calendar (Tenpō) requires:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Compute the &lt;strong&gt;instant of the new moon (saku)&lt;/strong&gt; at &lt;strong&gt;135°E, Japan Standard Time&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;The day of the new moon is lunar day 1.&lt;/li&gt;
&lt;li&gt;A month that contains no &lt;strong&gt;major solar term&lt;/strong&gt; (chūki) is a &lt;strong&gt;leap month&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Leap-month placement changes by year (7 times per ~19 years — the Metonic cycle).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Doing this properly means computing &lt;strong&gt;solar and lunar ecliptic longitude at astronomical precision&lt;/strong&gt; (VSOP87 and friends). Use an approximation and, on days where the new moon falls near midnight, you shift by one day — and &lt;strong&gt;every subsequent lunar date that year dominoes by one day&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;A widely cited reference implementation is &lt;strong&gt;QREKI&lt;/strong&gt; (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, &lt;strong&gt;not the kind of task you should hand to an LLM&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  The fix: call a Japanese-calendar API
&lt;/h2&gt;

&lt;p&gt;Drop 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 &lt;a href="https://shirabe.dev" rel="noopener noreferrer"&gt;Shirabe Calendar API&lt;/a&gt;. The free tier is &lt;strong&gt;10,000 calls/month&lt;/strong&gt; and you can try it &lt;strong&gt;without an API key&lt;/strong&gt;. The &lt;code&gt;fetch&lt;/code&gt; / &lt;code&gt;requests&lt;/code&gt; examples below still pass &lt;code&gt;X-API-Key&lt;/code&gt; — it's optional, used to track usage and raise limits.&lt;/p&gt;

&lt;h3&gt;
  
  
  Three lines that work
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# One date -&amp;gt; Rokuyo, rekichu (auspicious days), kanshi, solar term, all in one response&lt;/span&gt;
curl https://shirabe.dev/api/v1/calendar/2026-04-15
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The JSON looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"date"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2026-04-15"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"rokuyo"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"大安"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"reading"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Taian"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"timeSlots"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"morning"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"good"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"noon"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"good"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"afternoon"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"good"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"evening"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"good"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"rekichu"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"一粒万倍日"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"auspicious"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"context"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"wedding"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"judgment"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"excellent"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"score"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"note"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Taian x Ichiryu-manbai-bi. An excellent day for a wedding."&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"summary"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Reiwa 8 (2026)-04-15 (Wed) Taian / Ichiryu-manbai-bi. Excellent for weddings and openings."&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The key fields are &lt;strong&gt;&lt;code&gt;context&lt;/code&gt; and &lt;code&gt;summary&lt;/code&gt;&lt;/strong&gt;. 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 &lt;code&gt;summary&lt;/code&gt; straight into its answer to the user.&lt;/p&gt;

&lt;h3&gt;
  
  
  TypeScript
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://shirabe.dev/api/v1/calendar/2026-04-15&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;X-API-Key&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;SHIRABE_API_KEY&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rokuyo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;   &lt;span class="c1"&gt;// "大安" (Taian)&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;summary&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;       &lt;span class="c1"&gt;// "Reiwa 8 (2026)-04-15 (Wed) Taian ..."&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Python
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;

&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://shirabe.dev/api/v1/calendar/2026-04-15&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;X-API-Key&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;SHIRABE_API_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]},&lt;/span&gt;
    &lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;rokuyo&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Range queries and best-day search
&lt;/h3&gt;

&lt;p&gt;You're not limited to a single date.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# All Taian/Tomobiki days in April (up to 93 days)&lt;/span&gt;
curl &lt;span class="s2"&gt;"https://shirabe.dev/api/v1/calendar/range?start=2026-04-01&amp;amp;end=2026-04-30&amp;amp;filter_rokuyo=大安,友引"&lt;/span&gt;

&lt;span class="c"&gt;# Top 5 best wedding days from April to December, by score&lt;/span&gt;
curl &lt;span class="s2"&gt;"https://shirabe.dev/api/v1/calendar/best-days?purpose=wedding&amp;amp;start=2026-04-01&amp;amp;end=2026-12-31&amp;amp;limit=5"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;best-days&lt;/code&gt; is built so an &lt;strong&gt;AI agent can externalize the &lt;em&gt;judgment&lt;/em&gt; itself&lt;/strong&gt;. Pass a date range and a purpose (&lt;code&gt;wedding&lt;/code&gt; / &lt;code&gt;moving&lt;/code&gt; / &lt;code&gt;business&lt;/code&gt; and 8 categories total) and you get a ranked list of top-scoring days with the reasoning (e.g. Taian × Tensha-bi).&lt;/p&gt;




&lt;h2&gt;
  
  
  Integrating with AI agents
&lt;/h2&gt;

&lt;p&gt;Publish an &lt;strong&gt;OpenAPI 3.1 spec&lt;/strong&gt; 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 &lt;a href="https://shirabe.dev/openapi.yaml" rel="noopener noreferrer"&gt;https://shirabe.dev/openapi.yaml&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  ChatGPT GPTs Actions
&lt;/h3&gt;

&lt;p&gt;In the GPT Builder, "Create new action" → paste the OpenAPI URL into Import URL:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="s"&gt;https://shirabe.dev/openapi.yaml&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Choose API Key auth (header name &lt;code&gt;X-API-Key&lt;/code&gt;). That's all it takes for a custom GPT to call Shirabe automatically.&lt;/p&gt;

&lt;h3&gt;
  
  
  LangChain / LlamaIndex / Dify
&lt;/h3&gt;

&lt;p&gt;Feed the same URL to an OpenAPI loader and it's turned into tools. &lt;code&gt;operationId&lt;/code&gt; becomes the function name by design, so no glue code is needed.&lt;/p&gt;




&lt;h2&gt;
  
  
  Self-implementation vs API
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Dimension&lt;/th&gt;
&lt;th&gt;Self-implementation / LLM-generated code&lt;/th&gt;
&lt;th&gt;Japanese calendar API (Shirabe etc.)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Lunar accuracy&lt;/td&gt;
&lt;td&gt;Approximations slip by a day at new-moon boundaries&lt;/td&gt;
&lt;td&gt;Astronomical precision&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Rekichu coverage&lt;/td&gt;
&lt;td&gt;Implementing the ~13 auspicious-day types is a separate big job&lt;/td&gt;
&lt;td&gt;13+ types out of the box&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Per-purpose judgment&lt;/td&gt;
&lt;td&gt;Hard to spec and to build&lt;/td&gt;
&lt;td&gt;Provided via &lt;code&gt;context.wedding.score&lt;/code&gt; etc.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Maintenance&lt;/td&gt;
&lt;td&gt;Versioning the saku-calculation library, etc.&lt;/td&gt;
&lt;td&gt;Zero on the caller side&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AI integration&lt;/td&gt;
&lt;td&gt;Write your own tool/function definitions&lt;/td&gt;
&lt;td&gt;One OpenAPI URL&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Initial cost&lt;/td&gt;
&lt;td&gt;Looks like zero — but a single wrong-date liability sits behind it&lt;/td&gt;
&lt;td&gt;Free tier, 10,000/month&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;"Free because I built it myself" is only superficially free. &lt;strong&gt;Priced with the business risk of a failure, it usually doesn't pay off&lt;/strong&gt; in this domain.&lt;/p&gt;




&lt;h2&gt;
  
  
  Wrap-up
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;The Rokuyo formula itself is easy. The hard part is the &lt;strong&gt;lunar conversion&lt;/strong&gt; before it, which needs astronomical-precision new-moon computation.&lt;/li&gt;
&lt;li&gt;Let an LLM write the self-implementation and you get a &lt;strong&gt;silent failure&lt;/strong&gt; that's off by one day exactly on new-moon-boundary dates.&lt;/li&gt;
&lt;li&gt;In domains where you find out you were wrong &lt;em&gt;on the day itself&lt;/em&gt; — weddings, funerals, moving, contract dates — avoiding self-implementation is the cheaper choice.&lt;/li&gt;
&lt;li&gt;Use a Japanese calendar API built for AI agents (OpenAPI published, free tier) and you're done in 3 lines of &lt;code&gt;fetch&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Sample code is also collected under the &lt;code&gt;examples&lt;/code&gt; in &lt;a href="https://shirabe.dev/openapi.yaml" rel="noopener noreferrer"&gt;https://shirabe.dev/openapi.yaml&lt;/a&gt;. The same URL works whether you're calling from ChatGPT GPTs Actions, Claude tool use, or Gemini function calling.&lt;/p&gt;




&lt;h3&gt;
  
  
  Links
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://shirabe.dev" rel="noopener noreferrer"&gt;Shirabe Calendar API (official)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://shirabe.dev/openapi.yaml" rel="noopener noreferrer"&gt;OpenAPI 3.1 spec (bilingual descriptions)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://shirabe.dev/docs/rokuyo-api" rel="noopener noreferrer"&gt;Rokuyo API guide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://shirabe.dev/docs/rekichu-api" rel="noopener noreferrer"&gt;Rekichu (auspicious days) API guide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/techwell-inc-jp/shirabe-calendar-api" rel="noopener noreferrer"&gt;GitHub repository&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Japanese original: &lt;a href="https://qiita.com/yosikawa-techwell/items/f21d666a7fad06cdbb51" rel="noopener noreferrer"&gt;六曜APIを自前実装するな (Qiita)&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>ai</category>
      <category>typescript</category>
      <category>api</category>
      <category>llm</category>
    </item>
  </channel>
</rss>
