smartcalc_tauri/tokinizer/regex_tokinizer/
time.rs

1/*
2 * smartcalc v1.0.8
3 * Copyright (c) Erhan BARIS (Ruslan Ognyanov Asenov)
4 * Licensed under the GNU General Public License v2.0.
5 */
6
7use 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