aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/components/ScheduleInteractive.astro29
1 files changed, 28 insertions, 1 deletions
diff --git a/src/components/ScheduleInteractive.astro b/src/components/ScheduleInteractive.astro
index f0bd73c..8877d9d 100644
--- a/src/components/ScheduleInteractive.astro
+++ b/src/components/ScheduleInteractive.astro
@@ -1,7 +1,7 @@
<script>
// URLは src/data/schedule/config.ts で一元管理している(ページ移転時はそこだけ変える)
import { scheduleAbsoluteUrl } from '@/data/schedule/config';
- import { parseDates, applyExclusions, toKey, keyToDate, entryDates, mainStartMonth } from '@/lib/schedule-dates';
+ import { parseDates, applyExclusions, toKey, keyToDate, entryDates, mainStartMonth, normalizeDigits } from '@/lib/schedule-dates';
const CATEGORY_DEFS = [
{ icon: '👶', label: '子育て' },
@@ -262,6 +262,26 @@
});
}
+ // 「午前9時から」「午後1時30分から」などの開始時刻を分にして返す。
+ // 時刻の記載がないもの(「現地視察のあとに委員会」「予約制」「資料配布のみ」など)は null。
+ // 終了時刻が先に出てくる文(「…午後5時まで。開館時間は…午前10時から」)があるため、
+ // 「から」「開演」「開始」が続く時刻を優先する。
+ function startMinutes(text: string): number | null {
+ const t = normalizeDigits(text);
+ const re = /(午前|午後)\s*(\d{1,2})\s*時\s*(?:(\d{1,2})\s*分)?/g;
+ const found: { minutes: number; end: number }[] = [];
+ let m: RegExpExecArray | null;
+ while ((m = re.exec(t)) !== null) {
+ let hour = Number(m[2]);
+ if (m[1] === '午後' && hour < 12) hour += 12;
+ if (m[1] === '午前' && hour === 12) hour = 0;
+ found.push({ minutes: hour * 60 + (m[3] ? Number(m[3]) : 0), end: m.index + m[0].length });
+ }
+ if (found.length === 0) return /正午/.test(t) ? 12 * 60 : null;
+ const start = found.find((f) => /^\s*(から|開演|開始|受付)/.test(t.slice(f.end)));
+ return (start ?? found[0]).minutes;
+ }
+
function showDayDetails(key) {
if (!key) return;
const date = keyToDate(key);
@@ -269,6 +289,13 @@
const list = visibleEntries(key)
.slice()
.sort((a, b) => {
+ // 開始時刻が分かるものを時刻順に並べ、分からないものは後ろに回す。
+ const ta = startMinutes(a.time);
+ const tb = startMinutes(b.time);
+ if (ta !== null && tb !== null && ta !== tb) return ta - tb;
+ if (ta === null && tb !== null) return 1;
+ if (ta !== null && tb === null) return -1;
+ // 同時刻や時刻不明のものは、会議を先にして名前順。
if (a.type !== b.type) return a.type === 'meeting' ? -1 : 1;
return a.name.localeCompare(b.name, 'ja');
});