Refactor event occurrence parsing by introducing modular components for improved maintainability
This commit restructures the EventOccurrenceParser by breaking down its functionality into modular components, including EventDefinitionResolver, LineClassifier, LocationPatternMatcher, SectionHeaderMatcher, TimeLocationParser, and TimeParser. This refactoring enhances code readability and maintainability, allowing for easier updates and testing. Additionally, the TextUtil class has been updated to include input sanitization methods. Comprehensive unit tests have been added to ensure the correctness of the new parsing logic and to validate the handling of various event occurrence scenarios.
This commit is contained in:
@@ -1,7 +1,48 @@
|
||||
namespace Core.Utility;
|
||||
using Core.Parsers;
|
||||
|
||||
namespace Core.Utility;
|
||||
|
||||
public static class TextUtil
|
||||
{
|
||||
/// <summary>
|
||||
/// Sanitizes input by normalizing hyphens (en-dash, em-dash -> regular hyphen).
|
||||
/// This allows parsers to assume normalized input.
|
||||
/// </summary>
|
||||
/// <param name="input">The input string to sanitize.</param>
|
||||
/// <returns>The sanitized string with normalized hyphens.</returns>
|
||||
public static string SanitizeInput(string input)
|
||||
{
|
||||
input = input.Replace("–", "-"); // en-dash
|
||||
input = input.Replace("—", "-"); // em-dash
|
||||
return input;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parses a date from month name, day of month, and year.
|
||||
/// </summary>
|
||||
/// <param name="month">The month name (e.g., "January", "February"). Case-insensitive.</param>
|
||||
/// <param name="dayOfMonth">The day of the month as a string (e.g., "15", "3").</param>
|
||||
/// <param name="year">The year (e.g., 2025).</param>
|
||||
/// <returns>A <see cref="DateOnly"/> representing the parsed date.</returns>
|
||||
/// <exception cref="ArgumentException">Thrown when the month name is invalid.</exception>
|
||||
/// <exception cref="FormatException">Thrown when the day of month cannot be parsed as an integer.</exception>
|
||||
/// <exception cref="ArgumentOutOfRangeException">Thrown when the resulting date is invalid (e.g., February 30).</exception>
|
||||
public static DateOnly ParseDate(string month, string dayOfMonth, int year)
|
||||
{
|
||||
// Use normalized MonthNames array from grammar
|
||||
var monthLower = month.ToLower();
|
||||
var monthIndex = Array.FindIndex(EventOccurrenceGrammar.MonthNames,
|
||||
m => m.ToLower() == monthLower);
|
||||
|
||||
if (monthIndex < 0)
|
||||
throw new ArgumentException($"Invalid month: {month}", nameof(month));
|
||||
|
||||
// Month index is 0-based, month number is 1-based
|
||||
int monthNum = monthIndex + 1;
|
||||
var day = int.Parse(dayOfMonth);
|
||||
return new DateOnly(year, monthNum, day);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the ordinal value of positive integers.
|
||||
/// </summary>
|
||||
|
||||
Reference in New Issue
Block a user