chrono_node/calculation/
merging.rs1use crate::core::components::{meridiem, Component, ParsingComponents};
4use crate::core::js_date::JsDate;
5use crate::core::result::ParsingResult;
6use crate::core::utils::dates::{assign_similar_date, imply_similar_date};
7
8pub fn merge_date_time_result(date_result: &ParsingResult, time_result: &ParsingResult) -> ParsingResult {
10 let mut result = date_result.js_clone();
11 result.start = merge_date_time_component(&date_result.start, &time_result.start);
12
13 if date_result.end.is_some() || time_result.end.is_some() {
14 let end_date = date_result.end.as_ref().unwrap_or(&date_result.start);
15 let end_time = time_result.end.as_ref().unwrap_or(&time_result.start);
16 let mut end_date_time = merge_date_time_component(end_date, end_time);
17
18 let earlier = matches!(
19 (end_date_time.date().get_time(), result.start.date().get_time()),
20 (Some(e), Some(s)) if e < s
21 );
22 if date_result.end.is_none() && earlier {
23 let mut next_day = JsDate::from_millis(end_date_time.date().get_time().unwrap_or(0));
25 next_day.set_date(next_day.get_date() + 1);
26 if end_date_time.is_certain(Component::Day) {
27 assign_similar_date(&mut end_date_time, next_day);
28 } else {
29 imply_similar_date(&mut end_date_time, next_day);
30 }
31 }
32 result.end = Some(end_date_time);
33 }
34 result
35}
36
37pub fn merge_date_time_component(date: &ParsingComponents, time: &ParsingComponents) -> ParsingComponents {
39 let mut dt = date.js_clone();
40 let t = |c| time.get_or_zero(c);
42 if time.is_certain(Component::Hour) {
43 dt.assign(Component::Hour, t(Component::Hour));
44 dt.assign(Component::Minute, t(Component::Minute));
45 if time.is_certain(Component::Second) {
46 dt.assign(Component::Second, t(Component::Second));
47 if time.is_certain(Component::Millisecond) {
48 dt.assign(Component::Millisecond, t(Component::Millisecond));
49 } else {
50 dt.imply(Component::Millisecond, t(Component::Millisecond));
51 }
52 } else {
53 dt.imply(Component::Second, t(Component::Second));
54 dt.imply(Component::Millisecond, t(Component::Millisecond));
55 }
56 } else {
57 dt.imply(Component::Hour, t(Component::Hour));
58 dt.imply(Component::Minute, t(Component::Minute));
59 dt.imply(Component::Second, t(Component::Second));
60 dt.imply(Component::Millisecond, t(Component::Millisecond));
61 }
62
63 if time.is_certain(Component::TimezoneOffset) {
64 dt.assign(Component::TimezoneOffset, t(Component::TimezoneOffset));
65 }
66
67 let date_has_meaningful_meridiem = date.get(Component::Meridiem).is_some()
68 && (date.is_certain(Component::Meridiem) || date.tags().iter().any(|t| t.starts_with("casualReference/")));
69
70 if time.is_certain(Component::Meridiem) {
71 dt.assign(Component::Meridiem, t(Component::Meridiem));
72 } else if let Some(m) = time.get(Component::Meridiem) {
73 if !date_has_meaningful_meridiem {
74 dt.imply(Component::Meridiem, m);
76 }
77 }
78
79 if dt.get(Component::Meridiem) == Some(meridiem::PM) && dt.get_or_zero(Component::Hour) < 12 {
81 let hour = dt.get_or_zero(Component::Hour) + 12;
82 if time.is_certain(Component::Hour) {
83 dt.assign(Component::Hour, hour);
84 } else {
85 dt.imply(Component::Hour, hour);
86 }
87 }
88
89 let date_tags: Vec<String> = date.tags().to_vec();
90 let time_tags: Vec<String> = time.tags().to_vec();
91 dt.add_tags(date_tags.iter().map(String::as_str));
92 dt.add_tags(time_tags.iter().map(String::as_str));
93 dt
94}