prayer-timetable-lib
Version:
Prayer timetable calc library.
258 lines (230 loc) • 7.86 kB
text/typescript
// @ts-ignore
import {
toDate,
addDays,
addHours,
addMinutes,
getYear,
getMonth,
getDate,
startOfDay,
endOfDay,
isBefore,
isAfter,
isWithinInterval,
differenceInSeconds,
} from 'date-fns'
const isDST = function (d: Date) {
const jan = new Date(d.getFullYear(), 0, 1).getTimezoneOffset()
const jul = new Date(d.getFullYear(), 6, 1).getTimezoneOffset()
return Math.max(jan, jul) !== d.getTimezoneOffset()
}
const dayCalc = (offsetDay = 0, offSetHour = 0, hijrioffset: any = 0, city = 'Europe/Dublin') => {
const now = addHours(new Date(), offSetHour + offsetDay * 24)
const month = getMonth(now)
const date = getDate(now)
const hijri = addDays(now, hijrioffset)
const start = startOfDay(now)
const end = endOfDay(now)
const dstAdjust = isDST(now) ? 1 : 0
return { now, month, date, start, end, hijri, dstAdjust }
}
const prayerCalc = (
hourMinute: [number, number],
hourMinuteNext: [number, number],
index: number,
now: Date,
when: string,
jamaahmethods: { [x: string]: string },
jamaahoffsets: { [x: number]: number[] },
dstAdjust: number
) => {
const [hour, minute] = hourMinute
const [hourNext, minuteNext] = hourMinuteNext
let time = addHours(toDate(new Date(getYear(now), getMonth(now), getDate(now), hour, minute)), dstAdjust)
/* *********************** */
/* JAMAAH CALC */
/* *********************** */
const hourOffset = jamaahoffsets[index][0]
const minuteOffset = jamaahoffsets[index][1]
const jamaahmethod = jamaahmethods[index]
let jtime
switch (jamaahmethod) {
case 'afterthis':
jtime = addMinutes(time, hourOffset * 60 + minuteOffset)
break
case 'fixed':
jtime = toDate(new Date(getYear(now), getMonth(now), getDate(now), hourOffset, minuteOffset))
break
case 'beforenext':
const rawjtime = toDate(new Date(getYear(now), getMonth(now), getDate(now), hourNext, minuteNext))
jtime = addMinutes(rawjtime, -hourOffset * 60 - minuteOffset + dstAdjust * 60)
break
default:
jtime = time
}
// if jtime before adhan / ie. summer time
if (isBefore(jtime, time)) {
time = jtime
}
/* *********************** */
/* NAMES */
/* *********************** */
const names = ['fajr', 'shurooq', 'dhuhr', 'asr', 'maghrib', 'isha']
const name = names[index]
const hasPassed = isAfter(now, time)
const isJamaahPending = isWithinInterval(now, { start: time, end: jtime })
const isNext = false
const result = { time, isJamaahPending, jtime, index, hasPassed, name, when, dstAdjust, isNext }
return result
}
const prayersCalc = (
timetable: any,
settings: { hijrioffset: any, jamaahmethods: any, jamaahoffsets: any },
showJamaah = true,
city = 'Europe/Dublin'
) => {
const { hijrioffset, jamaahmethods, jamaahoffsets } = settings
const { now, month, date, start, hijri, dstAdjust } = dayCalc(0, 0, hijrioffset, city)
const {
now: nowYesterday,
month: monthYesterday,
date: dateYesterday,
dstAdjust: dstAdjustYesterday,
} = dayCalc(-1, 0, hijrioffset, city)
const {
now: nowTomorrow,
month: monthTomorrow,
date: dateTomorrow,
dstAdjust: dstAdjustTomorrow,
} = dayCalc(1, 0, hijrioffset, city)
/* *********************** */
/* SET PRAYERS */
/* *********************** */
const prayersToday = timetable[month + 1][date].map((hourMinute: [number, number], index: number) => {
const hourMinuteNext = index < 5 ? timetable[month + 1][date][index + 1] : [24, 0]
return prayerCalc(hourMinute, hourMinuteNext, index, now, 'today', jamaahmethods, jamaahoffsets, dstAdjust)
})
const prayersYesterday = timetable[monthYesterday + 1][dateYesterday].map(
(hourMinute: [number, number], index: number) => {
const hourMinuteNext = index < 5 ? timetable[month + 1][date][index + 1] : [24, 0]
return prayerCalc(
hourMinute,
hourMinuteNext,
index,
nowYesterday,
'yesterday',
jamaahmethods,
jamaahoffsets,
dstAdjustYesterday
)
}
)
const prayersTomorrow = timetable[monthTomorrow + 1][dateTomorrow].map((hourMinute: [any, any], index: number) => {
const hourMinuteNext = index < 5 ? timetable[month + 1][date][index + 1] : [24, 0]
return prayerCalc(
hourMinute,
hourMinuteNext,
index,
nowTomorrow,
'tomorrow',
jamaahmethods,
jamaahoffsets,
dstAdjustTomorrow
)
})
/* *********************** */
/* PREVIOUS, CURRENT, NEXT */
/* *********************** */
let current
let next
let previous
if (isWithinInterval(now, { start, end: prayersToday[0].time })) {
previous = prayersYesterday[4]
current = prayersYesterday[5]
next = prayersToday[0]
} else if (isWithinInterval(now, { start: prayersToday[0].time, end: prayersToday[1].time })) {
previous = prayersYesterday[5]
current = prayersToday[0]
next = prayersToday[1]
} else if (isWithinInterval(now, { start: prayersToday[1].time, end: prayersToday[2].time })) {
previous = prayersToday[0]
current = prayersToday[1]
next = prayersToday[2]
} else if (isWithinInterval(now, { start: prayersToday[2].time, end: prayersToday[3].time })) {
previous = prayersToday[1]
current = prayersToday[2]
next = prayersToday[3]
} else if (isWithinInterval(now, { start: prayersToday[3].time, end: prayersToday[4].time })) {
previous = prayersToday[2]
current = prayersToday[3]
next = prayersToday[4]
} else if (isWithinInterval(now, { start: prayersToday[4].time, end: prayersToday[5].time })) {
previous = prayersToday[3]
current = prayersToday[4]
next = prayersToday[5]
} else {
previous = prayersToday[4]
current = prayersToday[5]
next = prayersTomorrow[0]
}
/* *********************** */
/* COUNTDOWN/UP */
/* *********************** */
const countUp = {
name:
current.isJamaahPending || !showJamaah ? current.name : `${current.name}${current.index !== 1 ? ' jamaah' : ''}`,
time: current.isJamaahPending || !showJamaah ? current.time : current.jtime,
duration:
current.isJamaahPending || !showJamaah
? differenceInSeconds(now, current.time)
: differenceInSeconds(now, current.jtime),
}
const countDown = {
name: current.isJamaahPending && showJamaah ? `${current.name}${current.index !== 1 ? ' jamaah' : ''}` : next.name,
time: current.isJamaahPending && showJamaah ? current.jtime : next.time,
duration:
current.isJamaahPending && showJamaah
? differenceInSeconds(current.jtime, now) + 1
: differenceInSeconds(next.time, now) + 1,
}
const totalDuration = countUp.duration + countDown.duration
const percentageRaw = 10000 - (countDown.duration / totalDuration) * 10000
const percentage = Math.floor(percentageRaw) / 100
const isAfterIsha = isAfter(now, prayersToday[5].jtime)
const isJamaahPending = isWithinInterval(now, { start: current.time, end: current.jtime })
const focus = current.isJamaahPending ? current : next
// focused prayer - add isNext
if (isAfterIsha) {
prayersTomorrow[focus.index].isNext = true
} else {
prayersToday[focus.index].isNext = true
}
// add day if after isha
const trueNow = now
const trueHijri = hijri
const newNow = isAfterIsha ? addDays(now, 1) : now
const newHijri = isAfterIsha ? addDays(hijri, 1) : hijri
const result = {
prayers: {
today: prayersToday,
yesterday: prayersYesterday,
tomorrow: prayersTomorrow,
},
previous,
current,
next,
countUp,
countDown,
now: newNow,
hijri: newHijri,
trueNow,
trueHijri,
percentage,
isAfterIsha,
isJamaahPending,
focus,
}
return result
}
export { prayersCalc, dayCalc }