181 lines
5.3 KiB
JavaScript
181 lines
5.3 KiB
JavaScript
.pragma library
|
|
|
|
var MS_PER_DAY = 86400000
|
|
|
|
var WEEKDAY_NAMES = ["sunday", "monday", "tuesday", "wednesday", "thursday", "friday", "saturday"]
|
|
|
|
function pad2(value) {
|
|
var n = Number(value)
|
|
return (n < 10 ? "0" : "") + n
|
|
}
|
|
|
|
function dateKey(year, month, day) {
|
|
return year + "-" + pad2(Number(month) + 1) + "-" + pad2(day)
|
|
}
|
|
|
|
function keyForDate(date) {
|
|
return dateKey(date.getFullYear(), date.getMonth(), date.getDate())
|
|
}
|
|
|
|
function coerceWeekStart(value) {
|
|
if (value === undefined || value === null) return null
|
|
if (typeof value === "number")
|
|
return isFinite(value) ? ((Math.round(value) % 7) + 7) % 7 : null
|
|
|
|
var text = String(value).replace(/^\s+|\s+$/g, "").toLowerCase()
|
|
if (text === "") return null
|
|
|
|
for (var i = 0; i < WEEKDAY_NAMES.length; i++)
|
|
if (WEEKDAY_NAMES[i] === text || WEEKDAY_NAMES[i].substr(0, 3) === text) return i
|
|
|
|
var parsed = parseInt(text, 10)
|
|
return isFinite(parsed) ? ((parsed % 7) + 7) % 7 : null
|
|
}
|
|
|
|
function normalizedWeekStart(value, fallback) {
|
|
var configured = coerceWeekStart(value)
|
|
if (configured !== null) return configured
|
|
var fallbackStart = coerceWeekStart(fallback)
|
|
return fallbackStart === null ? 1 : fallbackStart
|
|
}
|
|
|
|
function weekStartSettingName(index) {
|
|
return WEEKDAY_NAMES[normalizedWeekStart(index, 1)]
|
|
}
|
|
|
|
function toggledWeekStart(index) {
|
|
return normalizedWeekStart(index, 1) === 1 ? 0 : 1
|
|
}
|
|
|
|
function weekdayOrder(weekStart) {
|
|
var start = normalizedWeekStart(weekStart, 1)
|
|
var order = []
|
|
for (var i = 0; i < 7; i++) order.push((start + i) % 7)
|
|
return order
|
|
}
|
|
|
|
function isoWeek(year, month, day) {
|
|
var date = new Date(Date.UTC(year, month, day))
|
|
var weekday = date.getUTCDay() || 7
|
|
date.setUTCDate(date.getUTCDate() + 4 - weekday)
|
|
var yearStart = new Date(Date.UTC(date.getUTCFullYear(), 0, 1))
|
|
return Math.ceil(((date.getTime() - yearStart.getTime()) / MS_PER_DAY + 1) / 7)
|
|
}
|
|
|
|
function isoWeekLiteral(year, month, day) {
|
|
return pad2(isoWeek(year, month, day))
|
|
}
|
|
|
|
function dayOfYear(year, month, day) {
|
|
return Math.round((Date.UTC(year, month, day) - Date.UTC(year, 0, 1)) / MS_PER_DAY) + 1
|
|
}
|
|
|
|
function daysInYear(year) {
|
|
return dayOfYear(year, 11, 31)
|
|
}
|
|
|
|
function daysInMonth(year, month) {
|
|
return new Date(year, Number(month) + 1, 0).getDate()
|
|
}
|
|
|
|
function yearProgress(year, month, day) {
|
|
var total = daysInYear(year)
|
|
if (total <= 0) return 0
|
|
return Math.max(0, Math.min(1, (dayOfYear(year, month, day) - 1) / total))
|
|
}
|
|
|
|
function yearProgressPercent(year, month, day) {
|
|
return Math.round(yearProgress(year, month, day) * 100)
|
|
}
|
|
|
|
function stepMonth(year, month, delta) {
|
|
var target = new Date(year, Number(month) + Number(delta), 1)
|
|
return { year: target.getFullYear(), month: target.getMonth() }
|
|
}
|
|
|
|
function stepDay(year, month, day, delta) {
|
|
var target = new Date(year, month, Number(day) + Number(delta))
|
|
return { year: target.getFullYear(), month: target.getMonth(), day: target.getDate() }
|
|
}
|
|
|
|
function clampDay(year, month, day) {
|
|
return Math.max(1, Math.min(Number(day), daysInMonth(year, month)))
|
|
}
|
|
|
|
function daysBetween(fromYear, fromMonth, fromDay, toYear, toMonth, toDay) {
|
|
return Math.round((Date.UTC(toYear, toMonth, toDay) - Date.UTC(fromYear, fromMonth, fromDay)) / MS_PER_DAY)
|
|
}
|
|
|
|
function relativeDayLabel(offset) {
|
|
if (offset === 0) return "Today"
|
|
if (offset === 1) return "Tomorrow"
|
|
if (offset === -1) return "Yesterday"
|
|
if (offset > 0) return "In " + offset + " days"
|
|
return (-offset) + " days ago"
|
|
}
|
|
|
|
function monthGrid(year, month, weekStart, todayKey, selectedKey) {
|
|
var start = normalizedWeekStart(weekStart, 1)
|
|
var leading = (new Date(year, month, 1).getDay() - start + 7) % 7
|
|
var cursor = new Date(year, month, 1 - leading)
|
|
var today = String(todayKey || "")
|
|
var selected = String(selectedKey || "")
|
|
var weeks = []
|
|
|
|
for (var row = 0; row < 6; row++) {
|
|
var days = []
|
|
var thursday = null
|
|
for (var column = 0; column < 7; column++) {
|
|
var cellYear = cursor.getFullYear()
|
|
var cellMonth = cursor.getMonth()
|
|
var cellDay = cursor.getDate()
|
|
var weekday = cursor.getDay()
|
|
var key = dateKey(cellYear, cellMonth, cellDay)
|
|
if (weekday === 4) thursday = { year: cellYear, month: cellMonth, day: cellDay }
|
|
days.push({
|
|
key: key,
|
|
year: cellYear,
|
|
month: cellMonth,
|
|
day: cellDay,
|
|
weekday: weekday,
|
|
inMonth: cellMonth === month && cellYear === year,
|
|
weekend: weekday === 0 || weekday === 6,
|
|
today: key === today,
|
|
selected: key === selected
|
|
})
|
|
cursor.setDate(cursor.getDate() + 1)
|
|
}
|
|
var anchor = thursday || days[0]
|
|
weeks.push({
|
|
week: isoWeek(anchor.year, anchor.month, anchor.day),
|
|
days: days
|
|
})
|
|
}
|
|
return weeks
|
|
}
|
|
|
|
if (typeof module !== "undefined") {
|
|
module.exports = {
|
|
pad2: pad2,
|
|
dateKey: dateKey,
|
|
keyForDate: keyForDate,
|
|
normalizedWeekStart: normalizedWeekStart,
|
|
weekStartSettingName: weekStartSettingName,
|
|
toggledWeekStart: toggledWeekStart,
|
|
weekdayOrder: weekdayOrder,
|
|
isoWeek: isoWeek,
|
|
isoWeekLiteral: isoWeekLiteral,
|
|
dayOfYear: dayOfYear,
|
|
daysInYear: daysInYear,
|
|
daysInMonth: daysInMonth,
|
|
yearProgress: yearProgress,
|
|
yearProgressPercent: yearProgressPercent,
|
|
stepMonth: stepMonth,
|
|
stepDay: stepDay,
|
|
clampDay: clampDay,
|
|
daysBetween: daysBetween,
|
|
relativeDayLabel: relativeDayLabel,
|
|
monthGrid: monthGrid
|
|
}
|
|
}
|