@tour-kit/schedulingUtilities
Scheduling Utilities
Pure scheduling functions: evaluate schedules, check business hours, handle blackouts, and convert timezones without React
Scheduling Utilities
Framework-agnostic functions for evaluating schedules and working with dates, times, and timezones.
Categories
Schedule Evaluation
Core functions for checking if a schedule is active:
checkSchedule- Simple boolean checkisScheduleActive- Returns result with reasongetScheduleStatus- Detailed status with next times
Timezone
Convert and validate timezones:
getUserTimezone- Detect browser timezoneisValidTimezone- Validate IANA timezoneformatDateString- Format date in timezonegetDateInTimezone- Get date componentsparseDateString/parseTimeString- Parse strings
Date Range
Check if a date falls within a range:
isWithinDateRange- Check date range
Time Range
Check time-of-day constraints:
isWithinTimeRange- Check single time rangeisWithinAnyTimeRange- Check multiple ranges
Day of Week
Work with days of the week:
getDayOfWeek- Get day number (0-6)isAllowedDay- Check allowed daysdayNameToNumber- Convert name to numberdayNumberToName- Convert number to name
Blackout Periods
Check if in a blackout:
isInBlackoutPeriod- Check single blackoutisInAnyBlackout- Check multiple blackoutsgetCurrentBlackout- Get active blackoutgetBlackoutEndTime- Get blackout end
Business Hours
Evaluate business hours:
isWithinBusinessHours- Check business hoursisHoliday- Check if date is holidaygetDayBusinessHours- Get hours for day
Recurring Patterns
Match recurring schedules:
matchesRecurringPattern- Check if date matches pattern
When to Use Utilities vs Hooks
Use utilities when:
- Building server-side logic
- One-time checks (e.g., in event handlers)
- Non-React environments
- Testing
- You need precise control over evaluation timing
Use hooks when:
- Building React components
- Need automatic updates when time changes
- Want reactive UI based on schedule status
Example: Server-Side Evaluation
import { isScheduleActive } from '@tour-kit/scheduling'
export async function GET(request: Request) {
const schedule = {
daysOfWeek: [1, 2, 3, 4, 5],
timeOfDay: { start: '09:00', end: '17:00' },
}
const { isActive, reason } = isScheduleActive(schedule, {
now: new Date(),
userTimezone: request.headers.get('x-timezone') || 'UTC',
})
if (!isActive) {
return new Response('Feature not available', { status: 403 })
}
return new Response('Feature available')
}Example: Testing
import { checkSchedule } from '@tour-kit/scheduling'
import { describe, it, expect } from 'vitest'
describe('Tour Schedule', () => {
it('should be active during business hours', () => {
const schedule = {
daysOfWeek: [1, 2, 3, 4, 5],
timeOfDay: { start: '09:00', end: '17:00' },
}
// Tuesday at 10am
const isActive = checkSchedule(schedule, {
now: new Date('2024-01-09T10:00:00Z'),
userTimezone: 'UTC',
})
expect(isActive).toBe(true)
})
it('should be inactive on weekends', () => {
const schedule = {
daysOfWeek: [1, 2, 3, 4, 5],
}
// Saturday
const isActive = checkSchedule(schedule, {
now: new Date('2024-01-13T10:00:00Z'),
userTimezone: 'UTC',
})
expect(isActive).toBe(false)
})
})Example: Event Handler
import { isScheduleActive } from '@tour-kit/scheduling'
function FeatureButton() {
const handleClick = () => {
const schedule = {
timeOfDay: { start: '09:00', end: '17:00' },
}
const { isActive, reason } = isScheduleActive(schedule)
if (!isActive) {
alert(`Feature not available: ${reason}`)
return
}
// Proceed with feature
}
return <button onClick={handleClick}>Use Feature</button>
}Common Patterns
Combine Multiple Checks
import { isWithinDateRange, isWithinTimeRange, isAllowedDay } from '@tour-kit/scheduling'
function isAvailable(date: Date): boolean {
const timezone = 'America/New_York'
return (
isWithinDateRange(date, '2024-01-01', '2024-12-31', timezone) &&
isAllowedDay(date, [1, 2, 3, 4, 5], timezone) &&
isWithinTimeRange(date, { start: '09:00', end: '17:00' }, timezone)
)
}Build Custom Evaluation
import { getDayOfWeek, isWithinTimeRange } from '@tour-kit/scheduling'
function isWorkingHours(date: Date, timezone: string): boolean {
const day = getDayOfWeek(date, timezone)
// Weekend - closed
if (day === 0 || day === 6) {
return false
}
// Friday - short day
if (day === 5) {
return isWithinTimeRange(date, { start: '09:00', end: '15:00' }, timezone)
}
// Regular weekday
return isWithinTimeRange(date, { start: '09:00', end: '17:00' }, timezone)
}