1#![crate_name = "tz"]
2#![crate_type = "rlib"]
3#![crate_type = "dylib"]
4
5extern crate byteorder;
26use std::sync::Arc;
27
28pub mod internals;
29pub use internals::Result;
30
31
32#[derive(PartialEq, Eq, Debug, Clone)]
34pub struct TZData {
35
36 pub transitions: Vec<Transition>,
38
39 pub leap_seconds: Vec<LeapSecond>,
41}
42
43#[derive(Debug, PartialEq, Eq, Clone)]
45pub enum TransitionType {
46
47 Standard,
49
50 Wall,
52
53 UTC,
55}
56
57#[derive(Debug, PartialEq, Eq, Clone)]
59pub struct Transition {
60
61 pub timestamp: i32,
63
64 pub local_time_type: Arc<LocalTimeType>,
66}
67
68#[derive(Debug, PartialEq, Eq, Clone)]
70pub struct LeapSecond {
71
72 pub timestamp: i32,
74
75 pub leap_second_count: u32,
77}
78
79#[derive(Debug, PartialEq, Eq, Clone)]
82pub struct LocalTimeType {
83
84 pub name: String,
86
87 pub offset: i32,
89
90 pub is_dst: bool,
92
93 pub transition_type: TransitionType,
95}
96
97pub fn parse(input: Vec<u8>) -> Result<TZData> {
99 let tz = try!(internals::parse(input, internals::Limits::sensible()));
100 cook(tz)
101}
102
103pub fn cook(tz: internals::TZData) -> Result<TZData> {
105 let mut transitions = Vec::with_capacity(tz.header.num_transitions as usize);
106 let mut local_time_types = Vec::with_capacity(tz.header.num_local_time_types as usize);
107
108 for i in 0 .. tz.header.num_local_time_types as usize {
110 let ref data = tz.time_info[i];
111
112 let name_bytes = tz.strings.iter()
115 .cloned()
116 .skip(data.name_offset as usize)
117 .take_while(|&c| c != 0)
118 .collect();
119
120 let info = LocalTimeType {
121 name: try!(String::from_utf8(name_bytes)),
122 offset: data.offset,
123 is_dst: data.is_dst != 0,
124 transition_type: flags_to_transition_type(tz.standard_flags[i] != 0,
125 tz.gmt_flags[i] != 0),
126 };
127
128 local_time_types.push(Arc::new(info));
129 }
130
131 for i in 0 .. tz.header.num_transitions as usize {
133 let ref t = tz.transitions[i];
134
135 let transition = Transition {
136 timestamp: t.timestamp,
137 local_time_type: local_time_types[t.local_time_type_index as usize].clone(),
138 };
139
140 transitions.push(transition);
141 }
142
143 let mut leap_seconds = Vec::new();
144 for ls in tz.leap_seconds.iter() {
145 let leap_second = LeapSecond {
146 timestamp: ls.timestamp,
147 leap_second_count: ls.leap_second_count,
148 };
149
150 leap_seconds.push(leap_second);
151 }
152
153 Ok(TZData {
154 transitions: transitions,
155 leap_seconds: leap_seconds,
156 })
157}
158
159fn flags_to_transition_type(standard: bool, gmt: bool) -> TransitionType {
165 match (standard, gmt) {
166 (_, true) => TransitionType::UTC,
167 (true, _) => TransitionType::Standard,
168 (false, false) => TransitionType::Wall,
169 }
170}