[{"data":1,"prerenderedAt":319},["ShallowReactive",2],{"content-/family-trips-gantt-buffer":3,"all-pages-for-dir":317,"og-image-/family-trips-gantt-buffer":318},{"id":4,"title":5,"body":6,"category":300,"description":301,"extension":302,"meta":303,"navigation":178,"ogImage":304,"path":305,"project_name":306,"published":307,"publishedAt":308,"seo":309,"stem":310,"tags":311,"todo":304,"unpublished":307,"updatedAt":304,"__hash__":316},"pages/2026-05/2026-05-20/family-trips-gantt-buffer.md","Astroガントで8/28最終便が見切れる問題を表示用endDate+1日バッファで直した",{"type":7,"value":8,"toc":294},"minimark",[9,13,16,22,29,33,44,57,60,63,69,72,80,87,235,250,253,256,270,273,284,287,290],[10,11,12],"p",{},"家族旅行アーカイブサイト family-trips（Astro + Cloudflare Pages）で、旅行詳細ページのガントカレンダーを見ていたら、8/28 の最終便が右端で枠の外に半分はみ出していた。",[10,14,15],{},"正確には、自分が気づいたのではなくユーザーから指摘が飛んできた。",[17,18,19],"blockquote",{},[10,20,21],{},"8月28日のところなんか見切れてるんで、カレンダーもっと縦に見切れないようにしてもらえますか。バッファを1日ぐらい取ってていいんで",[10,23,24,28],{},[25,26,27],"code",{},"pnpm dev"," でローカルを 4321 番ポートに立ち上げて該当ページを開くと、確かに「大分→羽田 (6J096) 16:50-18:35」のバーが右端の枠線にぶつかって、後半が切れていた。",[30,31,32],"h2",{"id":32},"何が起きていたか",[10,34,35,36,39,40,43],{},"該当ファイルは ",[25,37,38],{},"src/pages/trips/[...slug].astro"," 一本。ガント描画の ",[25,41,42],{},"endDate"," を、コンテンツの終了日（8/28）ジャストで渡していた。",[45,46,47,51,54],"ul",{},[48,49,50],"li",{},"8/28 の枠は 0:00 から 23:59 までの 1 日分しか確保されていない",[48,52,53],{},"8/28 18:35 着の便のバーは 18:35 まで伸びる",[48,55,56],{},"右端のラベル領域・余白に侵食して、視覚的に「見切れている」状態になっていた",[10,58,59],{},"コンテンツデータ的には正しい（旅行は 8/28 で終わる）が、描画上は1日のれんが足りない、というだけの話だった。",[30,61,62],{"id":62},"どう直したか",[10,64,65,66,68],{},"ここで一瞬迷ったのは、「コンテンツ側の ",[25,67,42],{}," を 8/29 にずらして済ませる」案だった。",[10,70,71],{},"これをやると、旅行アーカイブのメタデータが現実と1日ずれる。旅行一覧の集計や日付ラベルに影響が出るのが嫌だったので、却下した。",[10,73,74,75,79],{},"採用したのは、",[76,77,78],"strong",{},"コンテンツの正データは触らず、描画側にだけ 1 日のれんを足す","方針。",[10,81,82,83,86],{},"具体的には、ガント描画関数に渡す終点を ",[25,84,85],{},"ganttEndDate = endDate + 1日"," のダミーに差し替えるだけ。",[88,89,94],"pre",{"className":90,"code":91,"language":92,"meta":93,"style":93},"language-ts shiki shiki-themes vitesse-light vitesse-light","// src/pages/trips/[...slug].astro 内\n// コンテンツの endDate は壊さない。表示専用の終点を 1 日後ろにずらす\nconst ganttEndDate = new Date(endDate)\nganttEndDate.setDate(ganttEndDate.getDate() + 1)\n\nconst days = buildDays(startDate, ganttEndDate)\nconst bars = buildBars(events, startDate, ganttEndDate)\n","ts","",[25,95,96,105,111,141,173,180,206],{"__ignoreMap":93},[97,98,101],"span",{"class":99,"line":100},"line",1,[97,102,104],{"class":103},"sxvE3","// src/pages/trips/[...slug].astro 内\n",[97,106,108],{"class":99,"line":107},2,[97,109,110],{"class":103},"// コンテンツの endDate は壊さない。表示専用の終点を 1 日後ろにずらす\n",[97,112,114,118,122,126,129,133,136,138],{"class":99,"line":113},3,[97,115,117],{"class":116},"stQ0i","const ",[97,119,121],{"class":120},"s4oTP","ganttEndDate",[97,123,125],{"class":124},"shFtX"," =",[97,127,128],{"class":116}," new ",[97,130,132],{"class":131},"senZ8","Date",[97,134,135],{"class":124},"(",[97,137,42],{"class":120},[97,139,140],{"class":124},")\n",[97,142,144,146,149,152,154,156,158,161,164,167,171],{"class":99,"line":143},4,[97,145,121],{"class":120},[97,147,148],{"class":124},".",[97,150,151],{"class":131},"setDate",[97,153,135],{"class":124},[97,155,121],{"class":120},[97,157,148],{"class":124},[97,159,160],{"class":131},"getDate",[97,162,163],{"class":124},"()",[97,165,166],{"class":116}," +",[97,168,170],{"class":169},"sM54T"," 1",[97,172,140],{"class":124},[97,174,176],{"class":99,"line":175},5,[97,177,179],{"emptyLinePlaceholder":178},true,"\n",[97,181,183,185,188,190,193,195,198,201,204],{"class":99,"line":182},6,[97,184,117],{"class":116},[97,186,187],{"class":120},"days",[97,189,125],{"class":124},[97,191,192],{"class":131}," buildDays",[97,194,135],{"class":124},[97,196,197],{"class":120},"startDate",[97,199,200],{"class":124},",",[97,202,203],{"class":120}," ganttEndDate",[97,205,140],{"class":124},[97,207,209,211,214,216,219,221,224,226,229,231,233],{"class":99,"line":208},7,[97,210,117],{"class":116},[97,212,213],{"class":120},"bars",[97,215,125],{"class":124},[97,217,218],{"class":131}," buildBars",[97,220,135],{"class":124},[97,222,223],{"class":120},"events",[97,225,200],{"class":124},[97,227,228],{"class":120}," startDate",[97,230,200],{"class":124},[97,232,203],{"class":120},[97,234,140],{"class":124},[10,236,237,238,241,242,245,246,249],{},"これで ",[25,239,240],{},"buildDays"," と ",[25,243,244],{},"buildBars"," の表示範囲が 1 日広がる。コンテンツのフロントマター側の ",[25,247,248],{},"endDate: 2026-08-28"," はそのまま据え置き。",[30,251,252],{"id":252},"結果",[10,254,255],{},"ブラウザをリロードしたら、",[45,257,258,261,264],{},[48,259,260],{},"8/28 の最終便「大分→羽田 (6J096) 16:50-18:35」のバーが、右側の余白に収まって、最後まで読める状態になった",[48,262,263],{},"8/29(土) のバッファ行が下に追加されて、何も予定がない空行として描画されている",[48,265,266,267,269],{},"旅行一覧側の表示・日付ラベル・集計は何も変わっていない（コンテンツの ",[25,268,42],{}," を触っていないので当然）",[30,271,272],{"id":272},"振り返り",[10,274,275,276,279,280,283],{},"判断としては「",[76,277,278],{},"データの正しさ","と",[76,281,282],{},"表示の見やすさ","は別レイヤーで解決する」が正解だった。",[10,285,286],{},"データ側を1日ずらすのは一見最小修正に見えるが、後で集計や URL を組むときに「なぜ実日付と1日ずれているのか」を毎回思い出す羽目になる。今回みたいに表示の都合は表示レイヤーで吸収しておく方が、半年後の自分が事故らない。",[10,288,289],{},"修正は Claude Code に「ganttEndDate を別に作って +1 日して、描画関数2つにだけ渡し替えて」と一行で頼んで、差分は数行で終わった。気づきさえあれば直る種類のバグ。",[291,292,293],"style",{},"html pre.shiki code .sxvE3, html code.shiki .sxvE3{--shiki-default:#A0ADA0;--shiki-dark:#A0ADA0}html pre.shiki code .stQ0i, html code.shiki .stQ0i{--shiki-default:#AB5959;--shiki-dark:#AB5959}html pre.shiki code .s4oTP, html code.shiki .s4oTP{--shiki-default:#B07D48;--shiki-dark:#B07D48}html pre.shiki code .shFtX, html code.shiki .shFtX{--shiki-default:#999999;--shiki-dark:#999999}html pre.shiki code .senZ8, html code.shiki .senZ8{--shiki-default:#59873A;--shiki-dark:#59873A}html pre.shiki code .sM54T, html code.shiki .sM54T{--shiki-default:#2F798A;--shiki-dark:#2F798A}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":93,"searchDepth":107,"depth":107,"links":295},[296,297,298,299],{"id":32,"depth":107,"text":32},{"id":62,"depth":107,"text":62},{"id":252,"depth":107,"text":252},{"id":272,"depth":107,"text":272},"personal","family-trips（Astro + Cloudflare Pages）の旅行詳細ページで、ガント右端の18:35便が枠外に飛び出していた。コンテンツのendDateは触らず、描画用にganttEndDate = endDate + 1日のダミー終点を渡して右側にのれんを足した。","md",{},null,"/family-trips-gantt-buffer","family-trips",false,"2026-05-20T00:00:00.000Z",{"title":5,"description":301},"2026-05/2026-05-20/family-trips-gantt-buffer",[312,313,314,315],"Astro","Gantt","UI修正","Cloudflare Pages","mKHlu9CJuF_NI46DbcU1Xwnu-ohWtRON3Zumw3TrhGY",[],"https://log.eurekapu.com/og/blog/family-trips-gantt-buffer.png?v=2026-05-20T00%3A00%3A00.000Z&title=Astro%E3%82%AC%E3%83%B3%E3%83%88%E3%81%A78%2F28%E6%9C%80%E7%B5%82%E4%BE%BF%E3%81%8C%E8%A6%8B%E5%88%87%E3%82%8C%E3%82%8B%E5%95%8F%E9%A1%8C%E3%82%92%E8%A1%A8%E7%A4%BA%E7%94%A8endDate%2B1%E6%97%A5%E3%83%90%E3%83%83%E3%83%95%E3%82%A1%E3%81%A7%E7%9B%B4%E3%81%97%E3%81%9F&author=Kei%20Komatsu&sig=e48c80a52a183c03",1782528840082]