smartcalc_tauri/tokinizer/regex_tokinizer/
time.rs1use alloc::string::ToString;
8use alloc::borrow::ToOwned;
9use regex::Regex;
10use crate::config::SmartCalcConfig;
11use crate::tokinizer::Tokinizer;
12use crate::types::{TokenType, TimeOffset};
13use crate::token::ui_token::{UiTokenType};
14use chrono::{Utc, FixedOffset, Datelike};
15
16use chrono::{TimeZone};
17
18pub fn time_regex_parser(config: &SmartCalcConfig, tokinizer: &mut Tokinizer, group_item: &[Regex]) {
19 for re in group_item.iter() {
20 for capture in re.captures_iter(&tokinizer.data.to_owned()) {
21 let mut end_position = 0;
22 let mut hour = capture.name("hour").unwrap().as_str().parse::<i32>().unwrap();
23 let minute = match capture.name("minute") {
24 Some(minute) => {
25 end_position = minute.end();
26 minute.as_str().parse::<i32>().unwrap()
27 },
28 _ => 0
29 };
30
31 let second = match capture.name("second") {
32 Some(second) => {
33 end_position = second.end();
34 second.as_str().parse::<i32>().unwrap()
35 },
36 _ => 0
37 };
38
39 if let Some(meridiem) = capture.name("meridiem") {
40 if meridiem.as_str().to_lowercase() == "pm" && hour < 12 && hour >= 0 {
41 hour += 12;
42 }
43 end_position = meridiem.end();
44 }
45
46 let time_offset = TimeOffset {
47 name: config.timezone.to_string(),
48 offset: config.timezone_offset
49 };
50
51 let date = Utc::today().naive_utc();
52 let datetime = FixedOffset::east(time_offset.offset * 60).ymd(date.year(), date.month(), date.day()).and_hms(hour as u32, minute as u32, second as u32);
53 let date_as_utc = Utc.from_utc_datetime(&datetime.naive_utc()).naive_utc();
54
55 if tokinizer.add_token_location(capture.get(0).unwrap().start(), end_position, Some(TokenType::Time(date_as_utc, time_offset)), capture.get(0).unwrap().as_str().to_string()) {
56 tokinizer.add_uitoken_from_match(capture.get(0), UiTokenType::DateTime);
57 }
58 }
59 }
60}
61
62#[cfg(test)]
63#[test]
64fn time_test() {
65 use core::ops::Deref;
66 use chrono::NaiveTime;
67
68 use crate::tokinizer::regex_tokinizer;
69 use crate::tokinizer::test::setup_tokinizer;
70 use crate::config::SmartCalcConfig;
71 use crate::session::Session;
72 let mut session = Session::new();
73 let config = SmartCalcConfig::default();
74 let mut tokinizer_mut = setup_tokinizer("11:30 12:00 AM 1:20 3:30 PM 9:01 1pm 1am 0pm 0am 1am GMT+10:00 12:34 pm".to_string(), &mut session, &config);
75
76 regex_tokinizer(&mut tokinizer_mut);
77 let tokens = &tokinizer_mut.token_infos;
78
79 assert_eq!(tokens.len(), 12);
80 assert_eq!(tokens[0].start, 0);
81 assert_eq!(tokens[0].end, 5);
82 assert_eq!(tokens[0].token_type.borrow().deref(), &Some(TokenType::Time(chrono::Utc::today().and_hms(11, 30, 0).naive_utc(), config.get_time_offset())));
83
84 assert_eq!(tokens[1].start, 6);
85 assert_eq!(tokens[1].end, 14);
86 assert_eq!(tokens[1].token_type.borrow().deref(), &Some(TokenType::Time(chrono::Utc::today().and_hms(12, 00, 0).naive_utc(), config.get_time_offset())));
87
88 assert_eq!(tokens[2].start, 15);
89 assert_eq!(tokens[2].end, 19);
90 assert_eq!(tokens[2].token_type.borrow().deref(), &Some(TokenType::Time(chrono::Utc::today().and_hms(1, 20, 0).naive_utc(), config.get_time_offset())));
91
92 assert_eq!(tokens[3].start, 20);
93 assert_eq!(tokens[3].end, 27);
94 assert_eq!(tokens[3].token_type.borrow().deref(), &Some(TokenType::Time(chrono::Utc::today().and_hms(15, 30, 0).naive_utc(), config.get_time_offset())));
95
96 assert_eq!(tokens[4].start, 28);
97 assert_eq!(tokens[4].end, 32);
98 assert_eq!(tokens[4].token_type.borrow().deref(), &Some(TokenType::Time(chrono::Utc::today().and_hms(9, 1, 0).naive_utc(), config.get_time_offset())));
99
100 assert_eq!(tokens[5].start, 33);
101 assert_eq!(tokens[5].end, 36);
102 assert_eq!(tokens[5].token_type.borrow().deref(), &Some(TokenType::Time(chrono::Utc::today().and_hms(13, 0, 0).naive_utc(), config.get_time_offset())));
103
104 assert_eq!(tokens[6].start, 37);
105 assert_eq!(tokens[6].end, 40);
106 assert_eq!(tokens[6].token_type.borrow().deref(), &Some(TokenType::Time(chrono::Utc::today().and_hms(1, 0, 0).naive_utc(), config.get_time_offset())));
107
108 assert_eq!(tokens[7].start, 41);
109 assert_eq!(tokens[7].end, 44);
110 assert_eq!(tokens[7].token_type.borrow().deref(), &Some(TokenType::Time(chrono::Utc::today().and_hms(12, 0, 0).naive_utc(), config.get_time_offset())));
111
112 assert_eq!(tokens[8].start, 45);
113 assert_eq!(tokens[8].end, 48);
114 assert_eq!(tokens[8].token_type.borrow().deref(), &Some(TokenType::Time(chrono::Utc::today().and_hms(0, 0, 0).naive_utc(), config.get_time_offset())));
115
116 assert_eq!(tokens[9].start, 49);
117 assert_eq!(tokens[9].end, 52);
118
119 let time = tokens[9].token_type.borrow().deref().clone();
120
121 if let Some(TokenType::Time(time, timezone)) = time {
122 assert_eq!(time.time(), NaiveTime::from_hms(1, 0, 0));
123 assert_eq!(timezone, TimeOffset {
124 name: "UTC".to_string(),
125 offset: 0
126 });
127 } else {
128 assert_eq!(false, true);
129 }
130
131 assert_eq!(tokens[10].start, 53);
132 assert_eq!(tokens[10].end, 62);
133 assert_eq!(tokens[10].token_type.borrow().deref(), &Some(TokenType::Timezone("GMT+10:00".to_string(), 600)));
134
135 assert_eq!(tokens[11].start, 63);
136 assert_eq!(tokens[11].end, 71);
137 assert_eq!(tokens[11].token_type.borrow().deref(), &Some(TokenType::Time(chrono::Utc::today().and_hms(12, 34, 0).naive_utc(), config.get_time_offset())));
138}
139