1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
use time::{OffsetDateTime, PrimitiveDateTime, UtcOffset};
pub trait Offset {
fn to_utc(&self) -> UtcOffset;
fn name(&self) -> &str;
}
pub trait TimeZone {
type Offset: Offset;
fn get_offset_utc(&self, date_time: &OffsetDateTime) -> Self::Offset;
fn name(&self) -> &str;
}
pub trait OffsetDateTimeExt {
fn to_timezone<T: TimeZone>(&self, tz: &T) -> OffsetDateTime;
}
pub trait PrimitiveDateTimeExt {
fn assume_timezone<T: TimeZone>(&self, tz: &T) -> OffsetDateTime;
}
impl PrimitiveDateTimeExt for PrimitiveDateTime {
fn assume_timezone<T: TimeZone>(&self, tz: &T) -> OffsetDateTime {
let offset = tz.get_offset_utc(&self.assume_utc());
self.assume_offset(offset.to_utc())
}
}
impl OffsetDateTimeExt for OffsetDateTime {
fn to_timezone<T: TimeZone>(&self, tz: &T) -> OffsetDateTime {
let offset = tz.get_offset_utc(self);
self.to_offset(offset.to_utc())
}
}
mod binary_search;
mod timezone_impl;
pub mod timezones;
#[cfg(feature = "system")]
pub mod system;
pub use timezone_impl::Tz;
#[cfg(test)]
mod tests {
use crate::timezones;
use crate::Offset;
use crate::OffsetDateTimeExt;
use crate::PrimitiveDateTimeExt;
use crate::TimeZone;
use time::macros::{datetime, offset};
use time::OffsetDateTime;
#[test]
fn names() {
let shanghai = timezones::get_by_name("Asia/Shanghai");
let china = timezones::get_by_name("China Standard Time");
assert!(shanghai.is_some());
assert!(china.is_some());
assert_eq!(shanghai, china);
}
#[test]
fn find() {
let zones_iana = timezones::find_by_name("Asia");
assert!(zones_iana.len() > 1);
}
#[test]
fn offsets_and_name() {
let tz = timezones::db::europe::LONDON;
assert_eq!(tz.name(), "Europe/London");
let offset = tz.get_offset_utc(&OffsetDateTime::now_utc());
assert!(!offset.name().is_empty());
}
#[test]
fn london_to_berlin() {
let dt = datetime!(2016-10-8 17:0:0).assume_timezone(timezones::db::europe::LONDON);
let converted = dt.to_timezone(timezones::db::europe::BERLIN);
let expected = datetime!(2016-10-8 18:0:0).assume_timezone(timezones::db::europe::BERLIN);
assert_eq!(converted, expected);
}
#[test]
fn dst() {
let london = timezones::db::europe::LONDON;
let odt1 = datetime!(2021-01-01 12:0:0 UTC);
assert_eq!(odt1.to_timezone(london), datetime!(2021-01-01 12:0:0 +0));
let odt2 = datetime!(2021-07-01 12:0:0 UTC);
assert_eq!(
odt2.to_timezone(london),
datetime!(2021-07-01 12:0:0 UTC).to_offset(offset!(+1))
);
}
}