aboutsummaryrefslogtreecommitdiffstats
path: root/desktop/island/calendar/Cal.js
diff options
context:
space:
mode:
Diffstat (limited to 'desktop/island/calendar/Cal.js')
-rw-r--r--desktop/island/calendar/Cal.js52
1 files changed, 45 insertions, 7 deletions
diff --git a/desktop/island/calendar/Cal.js b/desktop/island/calendar/Cal.js
index 6ec7bb3..d12ed29 100644
--- a/desktop/island/calendar/Cal.js
+++ b/desktop/island/calendar/Cal.js
@@ -83,10 +83,42 @@ function dots(events, day, calendars) {
return calendars.filter(c => events.some(e => e.calendar === c.name && onDay(e, day)));
}
-function timeLabel(ev, day) {
+// The island's clock settings (Prefs.island): h12 for a 12-hour clock, and
+// dateFormat, the clock pill's date as one of DATE_FORMATS (Qt format
+// strings). The calendar's longer dates follow its order, day or month
+// first. clockTime formats calctl's "HH:MM", compact ("9:30p") where width
+// is short.
+var DATE_GROUPS = [
+ { title: "Day first", formats: ["ddd dd/MM", "dd/MM", "dd/MM/yy", "dd/MM/yyyy", "ddd dd/MM/yyyy",
+ "dd.MM.yyyy", "dd-MM-yyyy", "d MMM", "ddd d MMM", "d MMM yyyy"] },
+ { title: "Month first", formats: ["ddd MM/dd", "MM/dd", "MM/dd/yy", "MM/dd/yyyy", "ddd MM/dd/yyyy",
+ "MMM d", "ddd MMM d", "MMM d, yyyy"] },
+ { title: "Year first", formats: ["yyyy-MM-dd", "ddd yyyy-MM-dd", "yyyy/MM/dd", "ddd MM-dd"] }];
+var DATE_FORMATS = DATE_GROUPS.reduce((a, g) => a.concat(g.formats), []);
+function timeFmt(h12) { return h12 ? "h:mm AP" : "HH:mm"; }
+function shortDateFmt(fmt) { return DATE_FORMATS.includes(fmt) ? fmt : DATE_FORMATS[0]; }
+// Day first unless the month comes before the day, the weekday name aside.
+function dayFirst(fmt) {
+ const f = shortDateFmt(fmt).replace(/ddd+/, "");
+ return f.indexOf("d") < f.indexOf("M");
+}
+function dayFmt(fmt, long) {
+ if (dayFirst(fmt)) return long ? "dddd d MMMM" : "ddd d MMM";
+ return long ? "dddd, MMMM d" : "ddd MMM d";
+}
+function clockTime(hhmm, h12) {
+ if (!h12 || !validTime(hhmm)) return hhmm;
+ const h = +hhmm.slice(0, 2);
+ return (h % 12 || 12) + hhmm.slice(2) + (h < 12 ? "a" : "p");
+}
+function hourLabel(h, h12) {
+ return h12 ? (h % 12 || 12) + (h < 12 ? "a" : "p") : pad(h);
+}
+
+function timeLabel(ev, day, h12) {
if (ev.allDay) return "all day";
- const s = ev.start.slice(0, 10) === day ? ev.start.slice(11, 16) : "…";
- const e = ev.end.slice(0, 10) === day ? ev.end.slice(11, 16) : "…";
+ const s = ev.start.slice(0, 10) === day ? clockTime(ev.start.slice(11, 16), h12) : "…";
+ const e = ev.end.slice(0, 10) === day ? clockTime(ev.end.slice(11, 16), h12) : "…";
return s + "–" + e;
}
@@ -94,12 +126,18 @@ function validTime(s) {
return /^([01]\d|2[0-3]):[0-5]\d$/.test(s);
}
-// Loose typing as HH:MM: "9.30", "9:30", "930" and "9" mean what they look
-// like. Anything else comes back unchanged, for validTime to reject.
+// Loose typing as HH:MM: "9.30", "9:30", "930", "9", and with am or pm
+// ("9.30pm", "12am") for the 12-hour clock, mean what they look like.
+// Anything else comes back unchanged, for validTime to reject.
function normTime(s) {
- const m = /^\s*(\d{1,2})(?:[:.,h ]?(\d{2}))?\s*$/.exec(s);
+ const m = /^\s*(\d{1,2})(?:[:.,h ]?(\d{2}))?\s*(?:([ap])\.?m?\.?)?\s*$/i.exec(s);
if (!m) return s;
- const t = pad(+m[1]) + ":" + (m[2] || "00");
+ let h = +m[1];
+ if (m[3]) {
+ if (h < 1 || h > 12) return s;
+ h = h % 12 + (m[3].toLowerCase() === "p" ? 12 : 0);
+ }
+ const t = pad(h) + ":" + (m[2] || "00");
return validTime(t) ? t : s;
}