whichtime_sys/refiners/
merge_weekday_date.rs1use crate::components::Component;
9use crate::context::ParsingContext;
10use crate::refiners::Refiner;
11use crate::results::ParsedResult;
12
13pub struct MergeWeekdayDateRefiner;
15
16impl MergeWeekdayDateRefiner {
17 fn has_explicit_date(result: &ParsedResult) -> bool {
18 result.start.is_certain(Component::Month) && result.start.is_certain(Component::Day)
19 }
20
21 fn merge_results(
22 context: &ParsingContext,
23 first: &ParsedResult,
24 second: &ParsedResult,
25 weekday_source: &ParsedResult,
26 date_source: &ParsedResult,
27 ) -> ParsedResult {
28 let mut merged_components = date_source.start;
29
30 if let Some(weekday) = weekday_source.start.get(Component::Weekday) {
31 merged_components.assign(Component::Weekday, weekday);
32 }
33
34 let merged_end = if date_source.end.is_some() {
35 date_source.end
36 } else {
37 weekday_source.end
38 };
39
40 let range_start = first.index.min(second.index);
41 let range_end = first.end_index.max(second.end_index);
42
43 ParsedResult::new(
44 context.reference,
45 range_start,
46 &context.text[range_start..range_end],
47 merged_components,
48 merged_end,
49 )
50 }
51}
52
53impl Refiner for MergeWeekdayDateRefiner {
54 fn refine(&self, context: &ParsingContext, results: Vec<ParsedResult>) -> Vec<ParsedResult> {
55 if results.len() < 2 {
56 return results;
57 }
58
59 let mut merged = Vec::with_capacity(results.len());
60 let mut i = 0;
61
62 while i < results.len() {
63 let current = &results[i];
64
65 if i + 1 < results.len() {
67 let next = &results[i + 1];
68
69 let gap_start = current.end_index;
71 let gap_end = next.index;
72
73 if gap_end >= gap_start {
74 let gap = if gap_end > gap_start {
75 &context.text[gap_start..gap_end]
76 } else {
77 ""
78 };
79 let gap_trimmed = gap.trim();
80
81 let is_connectable = gap_trimmed.is_empty()
83 || gap_trimmed == ","
84 || gap_trimmed == ", den"
85 || gap_trimmed == ",den"
86 || gap_trimmed == "den"
87 || gap_trimmed == "、"
88 || gap_trimmed == ","
89 || gap_trimmed == "の";
90
91 if is_connectable {
92 let current_has_weekday = current.start.get(Component::Weekday).is_some();
93 let next_has_weekday = next.start.get(Component::Weekday).is_some();
94 let current_has_date = Self::has_explicit_date(current);
95 let next_has_date = Self::has_explicit_date(next);
96
97 if current_has_weekday && next_has_date && !next_has_weekday {
98 let merged_result =
99 Self::merge_results(context, current, next, current, next);
100 merged.push(merged_result);
101 i += 2;
102 continue;
103 }
104
105 if current_has_date && !current_has_weekday && next_has_weekday {
106 let merged_result =
107 Self::merge_results(context, current, next, next, current);
108 merged.push(merged_result);
109 i += 2;
110 continue;
111 }
112 }
113 }
114 }
115
116 merged.push(results[i].clone());
117 i += 1;
118 }
119
120 merged
121 }
122}