Skip to main content
Glama
pshempel

MCP Time Server Node

by pshempel

get_business_days

Calculate business days between two dates, excluding weekends and custom holidays for accurate scheduling and deadline tracking.

Instructions

Calculate business days between dates

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
start_dateYesStart date
end_dateYesEnd date
exclude_weekendsNoExclude weekends (default: true)
holidaysNoArray of holiday dates
timezoneNoTimezone for calculation (default: system timezone)

Implementation Reference

  • Core handler function implementing get_business_days tool logic: validates inputs, resolves timezone, aggregates holidays, categorizes days (business/weekend/holiday), applies weekend exclusion, and returns counts with caching.
    export function getBusinessDays(params: GetBusinessDaysParams): GetBusinessDaysResult {
      const { start_date, end_date, holidays = [], holiday_calendar, custom_holidays = [] } = params;
    
      // Log entry with all parameters to show what was provided
      debug.business('getBusinessDays called with params: %O', {
        start_date,
        end_date,
        timezone: params.timezone,
        exclude_weekends: params.exclude_weekends,
        holiday_calendar,
        holidays_count: holidays.length,
        custom_holidays_count: custom_holidays.length,
      });
    
      // Important: Log if no country parameter provided but holidays expected
      if (!holiday_calendar && holidays.length === 0 && custom_holidays.length === 0) {
        debug.validation('No holiday information provided (no country/calendar, no explicit holidays)');
      }
    
      // Validate string lengths and array lengths first
      validateDateString(start_date, 'start_date');
      validateDateString(end_date, 'end_date');
      validateArrayLength(holidays, LIMITS.MAX_ARRAY_LENGTH, 'holidays');
      validateArrayLength(custom_holidays, LIMITS.MAX_ARRAY_LENGTH, 'custom_holidays');
    
      const excludeWeekends = params.exclude_weekends ?? true;
      const includeObserved = params.include_observed ?? true;
      const config = getConfig();
      const timezone = resolveTimezone(params.timezone, config.defaultTimezone);
    
      debug.timezone('Resolved timezone: %s (from: %s)', timezone, params.timezone ?? 'default');
    
      // Build cache key using new utility
      const cacheKey = buildCacheKey('business', {
        single: { timezone },
        dates: [start_date, end_date],
        flags: { excludeWeekends, includeObserved },
        arrays: { holidays, customHolidays: custom_holidays },
        optional: { calendar: holiday_calendar },
      });
    
      // Use withCache wrapper
      return withCache(cacheKey, CacheTTL.BUSINESS_DAYS, () => {
        // Validate timezone if provided
        if (timezone && !validateTimezone(timezone)) {
          debug.error('Invalid timezone: %s', timezone);
          throw new TimezoneError(`Invalid timezone: ${timezone}`, timezone);
        }
    
        // Validate holiday_calendar if provided
        if (holiday_calendar) {
          validateHolidayCalendar(holiday_calendar);
        }
    
        // Parse dates
        const startDate = parseDateWithTimezone(start_date, timezone, 'start_date');
        const endDate = parseDateWithTimezone(end_date, timezone, 'end_date');
    
        // DoS protection: Validate date range
        validateDateRange(startDate, endDate, start_date, end_date);
    
        // Log calculation context
        debug.business(
          'Business days calculation: %s to %s',
          format(startDate, 'yyyy-MM-dd'),
          format(endDate, 'yyyy-MM-dd')
        );
    
        // Use the new holidayAggregator utility
        debug.holidays('Aggregating holidays for calendar: %s', holiday_calendar ?? 'none');
        const allHolidayDates = aggregateHolidays({
          calendar: holiday_calendar,
          includeObserved,
          dateRange: {
            start: startDate,
            end: endDate,
          },
          custom: custom_holidays,
          legacy: holidays,
          timezone,
        });
        debug.holidays('Total holidays found: %d', allHolidayDates.size);
        if (allHolidayDates.size > 0) {
          debug.holidays('Holiday dates: %O', Array.from(allHolidayDates));
        }
    
        // Get all days in the interval
        const days = eachDayOfInterval({
          start: startDate,
          end: endDate,
        });
        debug.timing('Processing %d days from %s to %s', days.length, start_date, end_date);
    
        // Categorize days into business, weekend, and holiday
        const categories = categorizeDays(days, allHolidayDates);
    
        // Adjust for weekend inclusion preference
        const adjustedCategories = adjustForWeekends(categories, excludeWeekends);
    
        const { businessDays, weekendDays, holidayCount } = adjustedCategories;
    
        // Log summary
        debug.business(
          'Calculated business days: %d of %d total days (%d weekends, %d holidays)',
          businessDays,
          days.length,
          weekendDays,
          holidayCount
        );
    
        const result: GetBusinessDaysResult = {
          total_days: days.length,
          business_days: businessDays,
          weekend_days: weekendDays,
          holiday_count: holidayCount,
        };
    
        return result;
      });
    }
  • src/index.ts:266-267 (registration)
    Tool function mapping in TOOL_FUNCTIONS object that registers the getBusinessDays handler for 'get_business_days' tool name.
    get_business_days: (params: unknown) =>
      getBusinessDays(params as Parameters<typeof getBusinessDays>[0]),
  • src/index.ts:133-156 (registration)
    Tool registration in TOOL_DEFINITIONS array defining name, description, and inputSchema for get_business_days.
      name: 'get_business_days',
      description: 'Calculate business days between dates',
      inputSchema: {
        type: 'object' as const,
        properties: {
          start_date: { type: 'string' as const, description: 'Start date' },
          end_date: { type: 'string' as const, description: 'End date' },
          exclude_weekends: {
            type: 'boolean' as const,
            description: 'Exclude weekends (default: true)',
          },
          holidays: {
            type: 'array' as const,
            items: { type: 'string' as const },
            description: 'Array of holiday dates',
          },
          timezone: {
            type: 'string' as const,
            description: 'Timezone for calculation (default: system timezone)',
          },
        },
        required: ['start_date', 'end_date'],
      },
    },
  • TypeScript interfaces defining input parameters (GetBusinessDaysParams) and output structure (GetBusinessDaysResult) for the tool.
    export interface GetBusinessDaysParams {
      start_date: string;
      end_date: string;
      exclude_weekends?: boolean;
      holidays?: string[];
      timezone?: string;
      holiday_calendar?: string;
      include_observed?: boolean;
      custom_holidays?: string[];
    }
    
    export interface GetBusinessDaysResult {
      total_days: number;
      business_days: number;
      weekend_days: number;
      holiday_count: number;
    }
  • src/tools/index.ts:7-7 (registration)
    Central export of getBusinessDays handler from tools index, imported by main index.ts.
    export { getBusinessDays } from './getBusinessDays';

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/pshempel/mcp-time-server-node'

If you have feedback or need assistance with the MCP directory API, please join our Discord server