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);
}
}