using System.Text.RegularExpressions; namespace Core.Parsers.EventOccurrence; /// /// Parses time strings into TimeOnly objects. /// Handles various time formats including NOON, TBD, time ranges, and AM/PM formats. /// public static class TimeParser { private static readonly Regex TimeRegex = new( TimePatterns.TimeWithGroups, RegexOptions.Compiled | RegexOptions.IgnoreCase); /// /// Extracts the start time from a time range string. /// Example: "10:00 a.m. - 12:00 p.m." -> "10:00 a.m." /// public static string ExtractStartTime(string timeRange) { if (timeRange.Contains(" - ", StringComparison.Ordinal)) { return timeRange[..timeRange.IndexOf(" - ", StringComparison.Ordinal)]; } return timeRange; } /// /// Parses a time string into a TimeOnly object. /// Handles: /// - NOON -> 12:00 PM /// - TBD -> 00:00:00 (midnight as placeholder) /// - Time ranges -> extracts start time (e.g., "10:00 a.m. - 12:00 p.m." -> parses "10:00 a.m.") /// - Standard AM/PM formats (e.g., "3:00 p.m.", "10:30 am") /// /// The time string to parse. /// A TimeOnly object representing the parsed time. /// Thrown when the time format is not recognized. public static TimeOnly Parse(string time) { int hour = 0; int minute = 0; // Handle TBD (To Be Determined) times gracefully if (string.Equals(time.Trim(), "TBD", StringComparison.OrdinalIgnoreCase)) { // Use a placeholder time (midnight) for TBD - the occurrence will still be created // but with a time that indicates it's TBD return new TimeOnly(0, 0, 0); } // Extract start time from range if present var timeToParse = ExtractStartTime(time); // Handle NOON if (timeToParse == "NOON") { hour = 12; } else { // Parse time with regex var timeMatch = TimeRegex.Match(timeToParse); if (timeMatch.Success) { hour = int.Parse(timeMatch.Groups["Hour"].Captures[0].Value); if (timeMatch.Groups["Minute"].Success) { minute = int.Parse(timeMatch.Groups["Minute"].Captures[0].Value); } // Convert AM/PM times to 24-hour format var apmValue = timeMatch.Groups["APM"].Captures[0].Value.ToLower(); if (apmValue is "p.m." or "pm") { // PM: add 12 unless it's 12 PM (which stays 12) if (hour < 12) hour += 12; } else if (apmValue is "a.m." or "am") { // AM: if it's 12 AM, convert to midnight (0) if (hour == 12) hour = 0; } } else { throw new FormatException($"Time format not recognized: {time}"); } } return new TimeOnly(hour, minute, 0); } }