1 #![deny(missing_docs)]
2 #![allow(dead_code)]
3 #![warn(unreachable_pub)]
4 
5 use std::num::ParseIntError;
6 use std::str::Utf8Error;
7 use std::time::SystemTimeError;
8 use std::{error, fmt, io};
9 
10 mod timezone;
11 pub(crate) use timezone::TimeZone;
12 
13 mod parser;
14 mod rule;
15 
16 /// Unified error type for everything in the crate
17 #[derive(Debug)]
18 pub(crate) enum Error {
19     /// Date time error
20     DateTime(&'static str),
21     /// Local time type search error
22     FindLocalTimeType(&'static str),
23     /// Local time type error
24     LocalTimeType(&'static str),
25     /// Invalid slice for integer conversion
26     InvalidSlice(&'static str),
27     /// Invalid Tzif file
28     InvalidTzFile(&'static str),
29     /// Invalid TZ string
30     InvalidTzString(&'static str),
31     /// I/O error
32     Io(io::Error),
33     /// Out of range error
34     OutOfRange(&'static str),
35     /// Integer parsing error
36     ParseInt(ParseIntError),
37     /// Date time projection error
38     ProjectDateTime(&'static str),
39     /// System time error
40     SystemTime(SystemTimeError),
41     /// Time zone error
42     TimeZone(&'static str),
43     /// Transition rule error
44     TransitionRule(&'static str),
45     /// Unsupported Tzif file
46     UnsupportedTzFile(&'static str),
47     /// Unsupported TZ string
48     UnsupportedTzString(&'static str),
49     /// UTF-8 error
50     Utf8(Utf8Error),
51 }
52 
53 impl fmt::Display for Error {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result54     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
55         use Error::*;
56         match self {
57             DateTime(error) => write!(f, "invalid date time: {}", error),
58             FindLocalTimeType(error) => error.fmt(f),
59             LocalTimeType(error) => write!(f, "invalid local time type: {}", error),
60             InvalidSlice(error) => error.fmt(f),
61             InvalidTzString(error) => write!(f, "invalid TZ string: {}", error),
62             InvalidTzFile(error) => error.fmt(f),
63             Io(error) => error.fmt(f),
64             OutOfRange(error) => error.fmt(f),
65             ParseInt(error) => error.fmt(f),
66             ProjectDateTime(error) => error.fmt(f),
67             SystemTime(error) => error.fmt(f),
68             TransitionRule(error) => write!(f, "invalid transition rule: {}", error),
69             TimeZone(error) => write!(f, "invalid time zone: {}", error),
70             UnsupportedTzFile(error) => error.fmt(f),
71             UnsupportedTzString(error) => write!(f, "unsupported TZ string: {}", error),
72             Utf8(error) => error.fmt(f),
73         }
74     }
75 }
76 
77 impl error::Error for Error {}
78 
79 impl From<io::Error> for Error {
from(error: io::Error) -> Self80     fn from(error: io::Error) -> Self {
81         Error::Io(error)
82     }
83 }
84 
85 impl From<ParseIntError> for Error {
from(error: ParseIntError) -> Self86     fn from(error: ParseIntError) -> Self {
87         Error::ParseInt(error)
88     }
89 }
90 
91 impl From<SystemTimeError> for Error {
from(error: SystemTimeError) -> Self92     fn from(error: SystemTimeError) -> Self {
93         Error::SystemTime(error)
94     }
95 }
96 
97 impl From<Utf8Error> for Error {
from(error: Utf8Error) -> Self98     fn from(error: Utf8Error) -> Self {
99         Error::Utf8(error)
100     }
101 }
102 
103 /// Number of hours in one day
104 const HOURS_PER_DAY: i64 = 24;
105 /// Number of seconds in one hour
106 const SECONDS_PER_HOUR: i64 = 3600;
107 /// Number of seconds in one day
108 const SECONDS_PER_DAY: i64 = SECONDS_PER_HOUR * HOURS_PER_DAY;
109 /// Number of days in one week
110 const DAYS_PER_WEEK: i64 = 7;
111 
112 /// Month days in a normal year
113 const DAY_IN_MONTHS_NORMAL_YEAR: [i64; 12] = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
114 /// Cumulated month days in a normal year
115 const CUMUL_DAY_IN_MONTHS_NORMAL_YEAR: [i64; 12] =
116     [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334];
117