Skip to main content
Glama

Time Tracking MCP

by markwharton
time-parser.ts4.05 kB
// src/services/time-parser.ts import { parseTime, parseDate } from '../utils/date-utils.js'; import type { ParsedTime } from '../types/index.js'; /** * Parse natural language time references into structured data * * Examples: * - "14:30" → specific time today * - "2 hours ago" → calculated time * - "yesterday afternoon" → yesterday at 14:00 * - "this morning" → today at 09:00 */ export class TimeParser { /** * Parse time and date references together */ parse(timeStr?: string, dateStr?: string): ParsedTime { const date = parseDate(dateStr); const time = parseTime(timeStr, date); return { hours: time.getHours(), minutes: time.getMinutes(), absoluteTime: time }; } /** * Parse relative time reference * Examples: "2 hours ago", "30 minutes ago" */ parseRelative(input: string): Date { const match = input.match(/^(\d+)\s*(hour|hr|h|minute|min|m)s?\s*ago$/i); if (!match) { throw new Error(`Cannot parse relative time: "${input}". Try "2 hours ago" or "30 minutes ago"`); } const [, amount, unit] = match; const value = parseInt(amount); const now = new Date(); if (unit.startsWith('h')) { now.setHours(now.getHours() - value); } else { now.setMinutes(now.getMinutes() - value); } return now; } /** * Parse absolute time (HH:MM format) */ parseAbsolute(input: string, baseDate?: Date): Date { const match = input.match(/^(\d{1,2}):(\d{2})$/); if (!match) { throw new Error(`Invalid time format: "${input}". Use HH:MM format (e.g., "14:30")`); } const [, hours, minutes] = match; const date = baseDate || new Date(); date.setHours(parseInt(hours), parseInt(minutes), 0, 0); return date; } /** * Parse contextual time references * Examples: "morning", "afternoon", "evening" */ parseContextual(input: string, baseDate?: Date): Date { const date = baseDate || new Date(); const lower = input.toLowerCase(); if (lower.includes('morning')) { date.setHours(9, 0, 0, 0); } else if (lower.includes('afternoon')) { date.setHours(14, 0, 0, 0); } else if (lower.includes('evening')) { date.setHours(18, 0, 0, 0); } else if (lower.includes('night')) { date.setHours(20, 0, 0, 0); } else { throw new Error(`Unknown time context: "${input}". Try "morning", "afternoon", or "evening"`); } return date; } /** * Smart parse - tries to determine the type of time reference */ smartParse(input: string, baseDate?: Date): Date { if (!input || input === 'now') { return baseDate || new Date(); } // Try absolute time (HH:MM) if (/^\d{1,2}:\d{2}$/.test(input)) { return this.parseAbsolute(input, baseDate); } // Try relative time if (/\d+\s*(hour|hr|h|minute|min|m)s?\s*ago/i.test(input)) { return this.parseRelative(input); } // Try contextual if (/morning|afternoon|evening|night/i.test(input)) { return this.parseContextual(input, baseDate); } // Fallback to date-utils parseTime return parseTime(input, baseDate); } /** * Validate time is reasonable (not in future, not too far in past) */ validate(time: Date, maxHoursInPast: number = 48): boolean { const now = new Date(); const hoursAgo = (now.getTime() - time.getTime()) / (1000 * 60 * 60); if (time > now) { throw new Error('Time cannot be in the future'); } if (hoursAgo > maxHoursInPast) { throw new Error(`Time is more than ${maxHoursInPast} hours in the past. Please specify the date.`); } return true; } }

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/markwharton/time-tracking-mcp'

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