Skip to main content

whichtime_sys/
results.rs

1//! Parsing results
2
3use crate::components::FastComponents;
4use chrono::{DateTime, Local};
5
6/// Reference date/time with timezone information.
7///
8/// Relative expressions are resolved against this instant and optional
9/// timezone offset.
10#[derive(Debug, Clone)]
11pub struct ReferenceWithTimezone {
12    /// The reference instant used as the base for relative parsing.
13    pub instant: DateTime<Local>,
14    /// Explicit timezone offset in minutes.
15    ///
16    /// `None` means the system timezone of `instant` should be used.
17    pub timezone_offset: Option<i32>,
18}
19
20impl ReferenceWithTimezone {
21    /// Create a new reference value from an instant and optional offset.
22    pub fn new(instant: DateTime<Local>, timezone_offset: Option<i32>) -> Self {
23        Self {
24            instant,
25            timezone_offset,
26        }
27    }
28
29    /// Create a reference value using the current local time.
30    pub fn now() -> Self {
31        Self {
32            instant: Local::now(),
33            timezone_offset: None,
34        }
35    }
36
37    /// Return the effective timezone offset in minutes.
38    pub fn get_timezone_offset(&self) -> i32 {
39        self.timezone_offset
40            .unwrap_or_else(|| -self.instant.offset().utc_minus_local() / 60)
41    }
42
43    /// Compute the adjustment between the current system offset and a target offset.
44    pub fn get_system_timezone_adjustment(
45        &self,
46        date: Option<DateTime<Local>>,
47        override_offset: Option<i32>,
48    ) -> i32 {
49        let date = date.unwrap_or_else(Local::now);
50        let current_offset = -date.offset().utc_minus_local() / 60;
51        let target_offset = override_offset.unwrap_or_else(|| self.get_timezone_offset());
52        current_offset - target_offset
53    }
54}
55
56/// A parsed result representing a matched date/time expression.
57#[derive(Debug, Clone)]
58pub struct ParsedResult {
59    /// Reference date used while resolving this result.
60    pub ref_date: DateTime<Local>,
61    /// Start byte index of the matched text.
62    pub index: usize,
63    /// End byte index of the matched text.
64    pub end_index: usize,
65    /// Original text slice that produced this result.
66    pub text: String,
67    /// Parsed components for the start of the match.
68    pub start: FastComponents,
69    /// Parsed components for the end of the match, when the result is a range.
70    pub end: Option<FastComponents>,
71}
72
73impl ParsedResult {
74    /// Create a parsed result from a matched slice and component set.
75    pub fn new(
76        reference: &ReferenceWithTimezone,
77        index: usize,
78        text: impl Into<String>,
79        start: FastComponents,
80        end: Option<FastComponents>,
81    ) -> Self {
82        let text = text.into();
83        let end_index = index + text.len();
84        Self {
85            ref_date: reference.instant,
86            index,
87            end_index,
88            text,
89            start,
90            end,
91        }
92    }
93
94    /// Resolve the start components to a concrete local datetime.
95    pub fn date(&self, reference: &ReferenceWithTimezone) -> Option<DateTime<Local>> {
96        self.start.to_datetime(reference)
97    }
98}