Skip to content

Commit cc5029c

Browse files
authored
Merge pull request #211 from yuankunzhang/replace-chrono-with-jiff-4
(jiff series #4) refactor: optimize offset type sizes and add conversion from `Offset` to `jifff::tz::Offset`
2 parents b5439d8 + 1b96dd5 commit cc5029c

File tree

1 file changed

+33
-21
lines changed

1 file changed

+33
-21
lines changed

src/items/timezone.rs

Lines changed: 33 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -46,13 +46,13 @@ use super::{
4646
#[derive(PartialEq, Debug, Clone, Default)]
4747
pub(crate) struct Offset {
4848
pub(crate) negative: bool,
49-
pub(crate) hours: u32,
50-
pub(crate) minutes: u32,
49+
pub(crate) hours: u8,
50+
pub(crate) minutes: u8,
5151
}
5252

5353
impl Offset {
5454
fn merge(self, offset: Offset) -> Offset {
55-
fn combine(a: u32, neg_a: bool, b: u32, neg_b: bool) -> (u32, bool) {
55+
fn combine(a: u16, neg_a: bool, b: u16, neg_b: bool) -> (u16, bool) {
5656
if neg_a == neg_b {
5757
(a + b, neg_a)
5858
} else if a > b {
@@ -61,14 +61,14 @@ impl Offset {
6161
(b - a, neg_b)
6262
}
6363
}
64-
let (hours_minutes, negative) = combine(
65-
self.hours * 60 + self.minutes,
64+
let (total_minutes, negative) = combine(
65+
(self.hours as u16) * 60 + (self.minutes as u16),
6666
self.negative,
67-
offset.hours * 60 + offset.minutes,
67+
(offset.hours as u16) * 60 + (offset.minutes as u16),
6868
offset.negative,
6969
);
70-
let hours = hours_minutes / 60;
71-
let minutes = hours_minutes % 60;
70+
let hours = (total_minutes / 60) as u8;
71+
let minutes = (total_minutes % 60) as u8;
7272

7373
Offset {
7474
negative,
@@ -88,26 +88,38 @@ impl TryFrom<Offset> for chrono::FixedOffset {
8888
minutes,
8989
}: Offset,
9090
) -> Result<Self, Self::Error> {
91-
let secs = hours * 3600 + minutes * 60;
91+
let secs = (hours as i32) * 3600 + (minutes as i32) * 60;
9292

9393
let offset = if negative {
94-
FixedOffset::west_opt(
95-
secs.try_into()
96-
.map_err(|_| ParseDateTimeError::InvalidInput)?,
97-
)
98-
.ok_or(ParseDateTimeError::InvalidInput)?
94+
FixedOffset::west_opt(secs).ok_or(ParseDateTimeError::InvalidInput)?
9995
} else {
100-
FixedOffset::east_opt(
101-
secs.try_into()
102-
.map_err(|_| ParseDateTimeError::InvalidInput)?,
103-
)
104-
.ok_or(ParseDateTimeError::InvalidInput)?
96+
FixedOffset::east_opt(secs).ok_or(ParseDateTimeError::InvalidInput)?
10597
};
10698

10799
Ok(offset)
108100
}
109101
}
110102

103+
impl TryFrom<Offset> for jiff::tz::Offset {
104+
type Error = ParseDateTimeError;
105+
106+
fn try_from(
107+
Offset {
108+
negative,
109+
hours,
110+
minutes,
111+
}: Offset,
112+
) -> Result<Self, Self::Error> {
113+
let secs = (hours as i32) * 3600 + (minutes as i32) * 60;
114+
let secs = if negative { -secs } else { secs };
115+
116+
let offset =
117+
jiff::tz::Offset::from_seconds(secs).map_err(|_| ParseDateTimeError::InvalidInput)?;
118+
119+
Ok(offset)
120+
}
121+
}
122+
111123
impl Display for Offset {
112124
fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
113125
write!(
@@ -159,7 +171,7 @@ pub(super) fn timezone_num(input: &mut &str) -> ModalResult<Offset> {
159171
}
160172

161173
/// Parse a timezone offset with a colon separating hours and minutes
162-
fn timezone_colon(input: &mut &str) -> ModalResult<(u32, u32)> {
174+
fn timezone_colon(input: &mut &str) -> ModalResult<(u8, u8)> {
163175
seq!(
164176
s(take_while(1..=2, AsChar::is_dec_digit)).try_map(|x: &str| x.parse()),
165177
_: colon,
@@ -169,7 +181,7 @@ fn timezone_colon(input: &mut &str) -> ModalResult<(u32, u32)> {
169181
}
170182

171183
/// Parse a timezone offset without colon
172-
fn timezone_colonless(input: &mut &str) -> ModalResult<(u32, u32)> {
184+
fn timezone_colonless(input: &mut &str) -> ModalResult<(u8, u8)> {
173185
s(take_while(0.., AsChar::is_dec_digit))
174186
.verify_map(|s: &str| {
175187
// GNU date supports number strings with leading zeroes, e.g.,

0 commit comments

Comments
 (0)