#![crate_name = "tz"]
#![crate_type = "rlib"]
#![crate_type = "dylib"]
extern crate byteorder;
use std::sync::Arc;
pub mod internals;
pub use internals::Result;
#[derive(PartialEq, Eq, Debug, Clone)]
pub struct TZData {
pub transitions: Vec<Transition>,
pub leap_seconds: Vec<LeapSecond>,
}
#[derive(Debug, PartialEq, Eq, Clone)]
pub enum TransitionType {
Standard,
Wall,
UTC,
}
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct Transition {
pub timestamp: i32,
pub local_time_type: Arc<LocalTimeType>,
}
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct LeapSecond {
pub timestamp: i32,
pub leap_second_count: u32,
}
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct LocalTimeType {
pub name: String,
pub offset: i32,
pub is_dst: bool,
pub transition_type: TransitionType,
}
pub fn parse(input: Vec<u8>) -> Result<TZData> {
let tz = try!(internals::parse(input, internals::Limits::sensible()));
cook(tz)
}
pub fn cook(tz: internals::TZData) -> Result<TZData> {
let mut transitions = Vec::with_capacity(tz.header.num_transitions as usize);
let mut local_time_types = Vec::with_capacity(tz.header.num_local_time_types as usize);
for i in 0 .. tz.header.num_local_time_types as usize {
let ref data = tz.time_info[i];
let name_bytes = tz.strings.iter()
.cloned()
.skip(data.name_offset as usize)
.take_while(|&c| c != 0)
.collect();
let info = LocalTimeType {
name: try!(String::from_utf8(name_bytes)),
offset: data.offset,
is_dst: data.is_dst != 0,
transition_type: flags_to_transition_type(tz.standard_flags[i] != 0,
tz.gmt_flags[i] != 0),
};
local_time_types.push(Arc::new(info));
}
for i in 0 .. tz.header.num_transitions as usize {
let ref t = tz.transitions[i];
let transition = Transition {
timestamp: t.timestamp,
local_time_type: local_time_types[t.local_time_type_index as usize].clone(),
};
transitions.push(transition);
}
let mut leap_seconds = Vec::new();
for ls in tz.leap_seconds.iter() {
let leap_second = LeapSecond {
timestamp: ls.timestamp,
leap_second_count: ls.leap_second_count,
};
leap_seconds.push(leap_second);
}
Ok(TZData {
transitions: transitions,
leap_seconds: leap_seconds,
})
}
fn flags_to_transition_type(standard: bool, gmt: bool) -> TransitionType {
match (standard, gmt) {
(_, true) => TransitionType::UTC,
(true, _) => TransitionType::Standard,
(false, false) => TransitionType::Wall,
}
}