time_tz/interface.rs
1// Copyright (c) 2022, Yuri6037
2//
3// All rights reserved.
4//
5// Redistribution and use in source and binary forms, with or without modification,
6// are permitted provided that the following conditions are met:
7//
8// * Redistributions of source code must retain the above copyright notice,
9// this list of conditions and the following disclaimer.
10// * Redistributions in binary form must reproduce the above copyright notice,
11// this list of conditions and the following disclaimer in the documentation
12// and/or other materials provided with the distribution.
13// * Neither the name of time-tz nor the names of its contributors
14// may be used to endorse or promote products derived from this software
15// without specific prior written permission.
16//
17// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
21// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
29use time::{OffsetDateTime, UtcOffset};
30
31/// This trait represents a particular timezone offset.
32pub trait Offset {
33 /// Converts this timezone offset to a [UtcOffset](time::UtcOffset).
34 fn to_utc(&self) -> UtcOffset;
35
36 /// Returns the name of this offset.
37 fn name(&self) -> &str;
38
39 /// Returns true if this offset is DST in the corresponding timezone, false otherwise.
40 fn is_dst(&self) -> bool;
41}
42
43/// This trait represents a timezone provider.
44pub trait TimeZone {
45 /// The type of offset.
46 type Offset: Offset;
47
48 /// Search for the given date time offset (assuming it is UTC) in this timezone.
49 fn get_offset_utc(&self, date_time: &OffsetDateTime) -> Self::Offset;
50
51 /// Search for the given date time offset (assuming it is already local) in this timezone.
52 fn get_offset_local(&self, date_time: &OffsetDateTime) -> OffsetResult<Self::Offset>;
53
54 /// Gets the main/default offset in this timezone.
55 fn get_offset_primary(&self) -> Self::Offset;
56
57 /// Returns the name of this timezone.
58 fn name(&self) -> &str;
59}
60
61/// This represents the possible types of errors when trying to find a local offset.
62#[derive(Clone, Copy, Debug)]
63pub enum OffsetResult<T> {
64 /// The date time is not ambiguous (exactly 1 is possible).
65 Some(T),
66
67 /// The date time is ambiguous (2 are possible).
68 Ambiguous(T, T),
69
70 /// The date time is invalid.
71 None,
72}
73
74impl<T> OffsetResult<T> {
75 /// Unwraps this OffsetResult assuming ambiguity is an error.
76 pub fn unwrap(self) -> T {
77 match self {
78 OffsetResult::Some(v) => v,
79 OffsetResult::Ambiguous(_, _) => panic!("Attempt to unwrap an ambiguous offset"),
80 OffsetResult::None => panic!("Attempt to unwrap an invalid offset"),
81 }
82 }
83
84 /// Unwraps this OffsetResult resolving ambiguity by taking the first result.
85 pub fn unwrap_first(self) -> T {
86 match self {
87 OffsetResult::Some(v) => v,
88 OffsetResult::Ambiguous(v, _) => v,
89 OffsetResult::None => panic!("Attempt to unwrap an invalid offset"),
90 }
91 }
92
93 /// Unwraps this OffsetResult resolving ambiguity by taking the second result.
94 pub fn unwrap_second(self) -> T {
95 match self {
96 OffsetResult::Some(v) => v,
97 OffsetResult::Ambiguous(_, v) => v,
98 OffsetResult::None => panic!("Attempt to unwrap an invalid offset"),
99 }
100 }
101
102 /// Turns this OffsetResult into an Option assuming ambiguity is an error.
103 pub fn take(self) -> Option<T> {
104 match self {
105 OffsetResult::Some(v) => Some(v),
106 OffsetResult::Ambiguous(_, _) => None,
107 OffsetResult::None => None,
108 }
109 }
110
111 /// Turns this OffsetResult into an Option resolving ambiguity by taking the first result.
112 pub fn take_first(self) -> Option<T> {
113 match self {
114 OffsetResult::Some(v) => Some(v),
115 OffsetResult::Ambiguous(v, _) => Some(v),
116 OffsetResult::None => None,
117 }
118 }
119
120 /// Turns this OffsetResult into an Option resolving ambiguity by taking the second result.
121 pub fn take_second(self) -> Option<T> {
122 match self {
123 OffsetResult::Some(v) => Some(v),
124 OffsetResult::Ambiguous(_, v) => Some(v),
125 OffsetResult::None => None,
126 }
127 }
128
129 /// Returns true if this OffsetResult is None.
130 pub fn is_none(&self) -> bool {
131 match self {
132 OffsetResult::Some(_) => false,
133 OffsetResult::Ambiguous(_, _) => false,
134 OffsetResult::None => true,
135 }
136 }
137
138 /// Returns true if this OffsetResult is ambiguous.
139 pub fn is_ambiguous(&self) -> bool {
140 match self {
141 OffsetResult::Some(_) => false,
142 OffsetResult::Ambiguous(_, _) => true,
143 OffsetResult::None => false,
144 }
145 }
146}