Parse (ParsiDateTime) - parsicore/parsidate GitHub Wiki
ParsiDateTime::parse
Static Function Parses a string containing a Persian date and time into a ParsiDateTime
instance, based on a specified format pattern.
Description
This function attempts to interpret the input string s
as a Persian date and time according to the structure and specifiers defined by the format
string. The process involves:
- Structural Matching: Verifies that the input string
s
precisely matches the literal characters (like spaces,/
,-
,:
,T
) present in theformat
string. - Specifier Extraction: Identifies format specifiers (e.g.,
%Y
,%m
,%H
,%T
) in theformat
string and extracts the corresponding date and time components from the input strings
. The format of these components ins
must adhere to the specifier's requirements (e.g.,%m
expects 2 digits,%T
expects "HH:MM:SS"). - Validation: After successfully extracting the year, month, day, hour, minute, and second values, it validates these components by internally attempting to create a
ParsiDateTime
using logic equivalent toParsiDateTime::new
. This ensures the extracted components form both a logically valid Persian date (checking month/day ranges, leap years) and a valid time (checking hour/minute/second ranges).
Supported Format Specifiers for Parsing
The following format specifiers are supported when parsing a date and time string:
- Date Specifiers:
%Y
: Parses exactly 4 digits as the Persian year (e.g., "1403").%m
: Parses exactly 2 digits as the Persian month (01-12) (e.g., "05").%d
: Parses exactly 2 digits as the Persian day (01-31) (e.g., "02").%B
: Parses a full Persian month name (case-sensitive, must exactly match standard names like "فروردین", "بهمن").
- Time Specifiers:
%H
: Parses exactly 2 digits as the hour (24-hour clock, 00-23) (e.g., "09", "15").%M
: Parses exactly 2 digits as the minute (00-59) (e.g., "05", "30").%S
: Parses exactly 2 digits as the second (00-59) (e.g., "00", "45").%T
: Equivalent to%H:%M:%S
. Parses time in the exact format "HH:MM:SS" (e.g., "15:30:05").
- Literal Specifier:
%%
: Matches a literal percent sign (%
) character in the input strings
.
Unsupported Specifiers for Parsing
Specifiers representing calculated values or components not directly used to construct a date/time instance are not supported for parsing. Using any of the following specifiers in the format
string will lead to a ParseErrorKind::UnsupportedSpecifier
error:
%A
: Weekday name (e.g., "شنبه").%w
: Weekday number (0-6).%j
: Ordinal day of the year (001-366).%K
: Season name (e.g., "پاییز").- (Any other specifiers not listed in the "Supported" section)
Arguments
s
: The input string slice (&str
) containing the date and time representation to be parsed.format
: The format string slice (&str
) describing the expected structure ofs
, using literals and supported format specifiers.
Returns
Ok(ParsiDateTime)
: If the input strings
successfully matches theformat
string and the extracted components form a valid Persian date and time, returns the resultingParsiDateTime
instance wrapped inOk
.Err(DateError::ParseError(kind))
: If parsing fails, returns an error wrapped inErr
. Thekind
field (ParseErrorKind
) provides details:ParseErrorKind::FormatMismatch
: The structure ofs
does not match theformat
(e.g., wrong separators, missing components, extra trailing characters).ParseErrorKind::InvalidNumber
: A numeric component (%Y, %m, %d, %H, %M, %S) could not be parsed as a number or lacked the required number of digits.ParseErrorKind::InvalidMonthName
: Input did not contain a recognized Persian month name where%B
was expected.ParseErrorKind::UnsupportedSpecifier
: Theformat
string contained an unsupported specifier (e.g.,%A
,%j
,%K
).ParseErrorKind::InvalidDateValue
: Extracted Y/M/D values were syntactically correct but form an invalid date (e.g., "1404/12/30" - 1404 is common; "1403/07/31" - Mehr has 30 days). Checked via internalParsiDateTime::new
.ParseErrorKind::InvalidTimeValue
: Extracted H/M/S values were syntactically correct but outside valid ranges (e.g., Hour 24, Minute 60, Second 60). Checked via internalParsiDateTime::new
.
Examples (Rust)
use parsidate::{ParsiDateTime, ParsiDate, DateError, ParseErrorKind}; // Assuming these types exist
// --- Success Cases ---
let s1 = "1403/05/02 15:30:45";
let fmt1 = "%Y/%m/%d %H:%M:%S";
let expected1 = ParsiDateTime::new(1403, 5, 2, 15, 30, 45).unwrap();
assert_eq!(ParsiDateTime::parse(s1, fmt1), Ok(expected1));
// Using %T for the time part
let s2 = "1403-05-02T09:05:00";
let fmt2 = "%Y-%m-%dT%T"; // ISO-like format
let expected2 = ParsiDateTime::new(1403, 5, 2, 9, 5, 0).unwrap();
assert_eq!(ParsiDateTime::parse(s2, fmt2), Ok(expected2));
// Using Persian month name %B
let s3 = "22 بهمن 1399 - 23:59:59"; // Assuming "بهمن" is recognized
let fmt3 = "%d %B %Y - %T";
let expected3 = ParsiDateTime::new(1399, 11, 22, 23, 59, 59).unwrap();
assert_eq!(ParsiDateTime::parse(s3, fmt3), Ok(expected3));
// --- Error Cases ---
// InvalidTimeValue: Hour 24 is out of range (00-23)
assert_eq!(
ParsiDateTime::parse("1403/05/02 24:00:00", fmt1),
Err(DateError::ParseError(ParseErrorKind::InvalidTimeValue))
);
// InvalidDateValue: Day 30 of Esfand in a non-leap year (1404)
assert_eq!(
ParsiDateTime::parse("1404/12/30 10:00:00", fmt1),
Err(DateError::ParseError(ParseErrorKind::InvalidDateValue))
);
// InvalidNumber: Minute '3' has only 1 digit, but %M (via %T or directly) expects 2 ('03')
assert_eq!(
ParsiDateTime::parse("1403/05/02 15:3:45", fmt1),
Err(DateError::ParseError(ParseErrorKind::InvalidNumber)) // Or possibly FormatMismatch
);
// FormatMismatch: Input uses '-' for time separator, but format (%T or %H:%M:%S) expects ':'
assert_eq!(
ParsiDateTime::parse("1403/05/02 15-30-45", fmt1),
Err(DateError::ParseError(ParseErrorKind::FormatMismatch))
);
// FormatMismatch: Input string is missing the time part required by the format
assert_eq!(
ParsiDateTime::parse("1403/05/02", fmt1),
Err(DateError::ParseError(ParseErrorKind::FormatMismatch))
);
// FormatMismatch: Input string has extra characters not accounted for in the format
assert_eq!(
ParsiDateTime::parse("1403/05/02 15:30:45 extra", fmt1),
Err(DateError::ParseError(ParseErrorKind::FormatMismatch))
);
// InvalidMonthName: Using a non-Persian or misspelled month name where %B expects a valid one
assert_eq!(
ParsiDateTime::parse("22 Бахман 1399 - 23:59:59", fmt3), // Using Cyrillic 'B' for demo
Err(DateError::ParseError(ParseErrorKind::InvalidMonthName))
);
// UnsupportedSpecifier: Format string uses %A (weekday) which is not supported for parsing
assert_eq!(
ParsiDateTime::parse("Tuesday 1403 10:00:00", "%A %Y %T"), // Hypothetical input
Err(DateError::ParseError(ParseErrorKind::UnsupportedSpecifier))
);
// UnsupportedSpecifier: Format string uses %K (season)
assert_eq!(
ParsiDateTime::parse("Spring 1403 10:00:00", "%K %Y %T"), // Hypothetical input
Err(DateError::ParseError(ParseErrorKind::UnsupportedSpecifier))
);