use alloc::collections::BTreeSet;
use alloc::string::String;
#[cfg(feature = "unstable")]
use crate::tzif::TzifBlockV2;
use crate::{
posix::PosixTimeZone,
types::{QualifiedTimeKind, Time},
zone::ZoneRecord,
ZoneInfoData,
};
use hashbrown::HashMap;
#[derive(Debug, Clone, PartialEq)]
pub struct LocalTimeRecord {
pub offset: i64,
pub saving: Time,
pub letter: Option<String>,
pub designation: String, }
#[derive(Debug, Clone, PartialEq, Eq)]
#[non_exhaustive]
pub struct Transition {
pub at_time: i64,
pub time_type: QualifiedTimeKind,
pub offset: i64,
pub dst: bool,
pub savings: Time,
pub letter: Option<String>,
pub format: String,
}
impl Ord for Transition {
fn cmp(&self, other: &Self) -> core::cmp::Ordering {
self.at_time.cmp(&other.at_time)
}
}
impl PartialOrd for Transition {
fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
Some(self.cmp(other))
}
}
#[non_exhaustive]
#[derive(Debug, PartialEq)]
pub struct CompiledTransitions {
pub initial_record: LocalTimeRecord,
pub transitions: BTreeSet<Transition>,
pub posix_time_zone: PosixTimeZone,
}
#[cfg(feature = "unstable")]
impl CompiledTransitions {
pub fn to_v2_data_block(&self) -> TzifBlockV2 {
TzifBlockV2::from_transition_data(self)
}
}
#[derive(Debug, Default)]
pub struct CompiledTransitionsMap {
pub data: HashMap<String, CompiledTransitions>,
}
pub struct ZoneInfoCompiler {
data: ZoneInfoData,
}
impl ZoneInfoCompiler {
pub fn new(data: ZoneInfoData) -> Self {
Self { data }
}
pub fn build_zone(&mut self, target: &str) -> CompiledTransitions {
if let Some(zone) = self.data.zones.get_mut(target) {
zone.associate_rules(&self.data.rules);
}
self.build_zone_internal(target)
}
pub fn build(&mut self) -> CompiledTransitionsMap {
self.associate();
let mut zoneinfo = CompiledTransitionsMap::default();
for identifier in self.data.zones.keys() {
let transition_data = self.build_zone_internal(identifier);
let _ = zoneinfo.data.insert(identifier.clone(), transition_data);
}
zoneinfo
}
pub(crate) fn build_zone_internal(&self, target: &str) -> CompiledTransitions {
let zone_table = self
.data
.zones
.get(target)
.expect("Invalid identifier provided.");
zone_table.compile()
}
pub fn get_posix_time_zone(&mut self, target: &str) -> Option<PosixTimeZone> {
self.associate();
self.data
.zones
.get(target)
.map(ZoneRecord::get_posix_time_zone)
}
pub fn associate(&mut self) {
for zones in self.data.zones.values_mut() {
zones.associate_rules(&self.data.rules);
}
}
}