Parse - parsicore/parsidate GitHub Wiki
ParsiDate::parse
Function Parses a string representation of a Persian date into a ParsiDate
instance, guided by a provided format pattern.
Description
This function attempts to interpret the input string s
according to the structure defined by the format
string. The parsing process involves several key steps:
- Structural Matching: It requires an exact match between literal characters (like
/
,-
, spaces, etc.) present in theformat
string and the corresponding characters in the input strings
. - Specifier Extraction: It identifies format specifiers (like
%Y
,%m
) in theformat
string and expects to find corresponding date components in the input strings
. The format of these components ins
must match the specifier's requirements (e.g.,%Y
expects exactly 4 digits). - Validation: After successfully extracting the numerical or textual year, month, and day values based on the specifiers, it validates these values by internally attempting to create a
ParsiDate
using logic equivalent toParsiDate::new
. This ensures the extracted components form a logically valid date within the Persian calendar (e.g., checking month ranges, day ranges considering leap years).
Supported Format Specifiers for Parsing
Only the following format specifiers are supported when parsing a date string:
%Y
: Parses exactly 4 digits as the Persian year (e.g., "1403").%m
: Parses exactly 2 digits as the Persian month (e.g., "01", "05", "12").%d
: Parses exactly 2 digits as the Persian day (e.g., "01", "09", "30").%B
: Parses a full Persian month name. This is case-sensitive and must exactly match one of the standard Persian month names used by the library (e.g., "فروردین", "اردیبهشت", ..., "اسفند").%%
: Matches a literal percent sign (%
) character in the input strings
.
Unsupported Specifiers for Parsing
Specifiers that represent calculated values derived from a date, rather than constituting the date itself, are not supported for parsing. Using any of the following specifiers in the format
string will result in a ParseErrorKind::UnsupportedSpecifier
error:
%A
: Weekday name (e.g., "شنبه") - Cannot be used to construct a date.%w
: Weekday number (0-6) - Cannot be used to construct a date.%j
: Ordinal day of the year (001-366) - Cannot be used to construct a date.%K
: Season name (e.g., "بهار") - Cannot be used to construct a date.- (Any other specifiers not listed in the "Supported" section)
Arguments
s
: The input string slice (&str
) containing the date representation to be parsed.format
: The format string slice (&str
) describing the expected structure ofs
, including literals and supported format specifiers.
Returns
Ok(ParsiDate)
: If the input strings
successfully matches theformat
string and the extracted components form a valid Persian date, returns the resultingParsiDate
instance wrapped inOk
.Err(DateError::ParseError(kind))
: If parsing fails at any stage, returns an error wrapped inErr
. Thekind
field (ParseErrorKind
) provides specific details about the failure:ParseErrorKind::FormatMismatch
: The structure of the input strings
does not match the literal characters or overall pattern of theformat
string. This includes cases like incorrect separators, missing components, or extra unexpected characters at the end ofs
.ParseErrorKind::InvalidNumber
: A numeric component expected by a specifier (%Y
,%m
,%d
) could not be parsed as a valid number, or it did not contain the exact required number of digits (4 for%Y
, 2 for%m
, 2 for%d
).ParseErrorKind::InvalidMonthName
: The input strings
did not contain a valid, recognized Persian month name at the position where a%B
specifier was expected in theformat
.ParseErrorKind::UnsupportedSpecifier
: Theformat
string contained one or more specifiers (like%A
,%j
,%K
) that are not supported for parsing dates.ParseErrorKind::InvalidDateValue
: The year, month, and day values were successfully extracted froms
according to theformat
, but they fail the final validation check (internalParsiDate::new
). This occurs for logically impossible dates, such as "1404/12/30" (since 1404 is not a leap year) or "1403/07/31" (since Mehr only has 30 days).
Examples (Rust)
use parsidate::{ParsiDate, DateError, ParseErrorKind}; // Assuming these types exist
// --- Success Cases ---
// Standard YYYY/MM/DD format
assert_eq!(
ParsiDate::parse("1403/05/02", "%Y/%m/%d"),
Ok(ParsiDate::new(1403, 5, 2).unwrap()) // 2nd Mordad 1403
);
// Standard YYYY-MM-DD format (leap day)
assert_eq!(
ParsiDate::parse("1399-12-30", "%Y-%m-%d"),
Ok(ParsiDate::new(1399, 12, 30).unwrap()) // 30th Esfand 1399 (leap)
);
// Format with full month name (%B)
assert_eq!(
ParsiDate::parse("02 مرداد 1403", "%d %B %Y"),
Ok(ParsiDate::new(1403, 5, 2).unwrap()) // 2nd Mordad 1403
);
// Format with literal %
assert_eq!(
ParsiDate::parse("Year: 1403 % Month: 01 % Day: 01", "Year: %Y %% Month: %m %% Day: %d"),
Ok(ParsiDate::new(1403, 1, 1).unwrap())
);
// --- Error Cases ---
// FormatMismatch: Input uses '-' but format expects '/'
assert_eq!(
ParsiDate::parse("1403-05-02", "%Y/%m/%d"),
Err(DateError::ParseError(ParseErrorKind::FormatMismatch))
);
// FormatMismatch: Input has extra trailing characters not in format
assert_eq!(
ParsiDate::parse("1403/05/02 extra data", "%Y/%m/%d"),
Err(DateError::ParseError(ParseErrorKind::FormatMismatch))
);
// InvalidNumber: Day '2' has only 1 digit, but %d expects 2 ('02')
assert_eq!(
ParsiDate::parse("1403/05/2", "%Y/%m/%d"),
Err(DateError::ParseError(ParseErrorKind::InvalidNumber)) // Or could be FormatMismatch depending on impl.
);
// InvalidNumber: Year 'abcd' is not numeric, but %Y expects digits
assert_eq!(
ParsiDate::parse("abcd/05/02", "%Y/%m/%d"),
Err(DateError::ParseError(ParseErrorKind::InvalidNumber))
);
// InvalidMonthName: "Mordd" is not a valid month name for %B
assert_eq!(
ParsiDate::parse("02 Mordd 1403", "%d %B %Y"), // Assuming "مرداد" is the correct name
Err(DateError::ParseError(ParseErrorKind::InvalidMonthName))
);
// InvalidDateValue: Date components parse ok, but 1404/12/30 is invalid (1404 not leap)
assert_eq!(
ParsiDate::parse("1404/12/30", "%Y/%m/%d"),
Err(DateError::ParseError(ParseErrorKind::InvalidDateValue))
);
// InvalidDateValue: Date components parse ok, but 1403/07/31 is invalid (Mehr has 30 days)
assert_eq!(
ParsiDate::parse("1403/07/31", "%Y/%m/%d"),
Err(DateError::ParseError(ParseErrorKind::InvalidDateValue))
);
// UnsupportedSpecifier: Format string uses %A (weekday name) which is not allowed for parsing
assert_eq!(
ParsiDate::parse("Saturday 1403", "%A %Y"), // Hypothetical input
Err(DateError::ParseError(ParseErrorKind::UnsupportedSpecifier))
);
// UnsupportedSpecifier: Format string uses %K (season name) which is not allowed for parsing
assert_eq!(
ParsiDate::parse("Summer 1403", "%K %Y"), // Hypothetical input
Err(DateError::ParseError(ParseErrorKind::UnsupportedSpecifier))
);
// UnsupportedSpecifier: Format string uses %j (ordinal day)
assert_eq!(
ParsiDate::parse("Day 180 of 1403", "Day %j of %Y"), // Hypothetical input
Err(DateError::ParseError(ParseErrorKind::UnsupportedSpecifier))
);