mirror of
https://github.com/bspeice/dtparse
synced 2025-07-03 14:54:57 -04:00
Weekday support
This commit is contained in:
132
src/weekday.rs
Normal file
132
src/weekday.rs
Normal file
@ -0,0 +1,132 @@
|
||||
use std::cmp::max;
|
||||
|
||||
use ParseResult;
|
||||
use ParseError;
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum DayOfWeek {
|
||||
Sunday,
|
||||
Monday,
|
||||
Tuesday,
|
||||
Wednesday,
|
||||
Thursday,
|
||||
Friday,
|
||||
Saturday
|
||||
}
|
||||
|
||||
impl DayOfWeek {
|
||||
|
||||
pub fn to_numeral(&self) -> u32 {
|
||||
match self {
|
||||
DayOfWeek::Sunday => 0,
|
||||
DayOfWeek::Monday => 1,
|
||||
DayOfWeek::Tuesday => 2,
|
||||
DayOfWeek::Wednesday => 3,
|
||||
DayOfWeek::Thursday => 4,
|
||||
DayOfWeek::Friday => 5,
|
||||
DayOfWeek::Saturday => 6,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_numeral(num: u32) -> DayOfWeek {
|
||||
match num % 7 {
|
||||
0 => DayOfWeek::Sunday,
|
||||
1 => DayOfWeek::Monday,
|
||||
2 => DayOfWeek::Tuesday,
|
||||
3 => DayOfWeek::Wednesday,
|
||||
4 => DayOfWeek::Thursday,
|
||||
5 => DayOfWeek::Friday,
|
||||
6 => DayOfWeek::Saturday,
|
||||
_ => panic!("Unreachable.")
|
||||
}
|
||||
}
|
||||
|
||||
/// Given the current day of the week, how many days until the next day?
|
||||
pub fn difference(&self, other: DayOfWeek) -> u32 {
|
||||
// Have to use i32 because of wraparound issues
|
||||
let s_num = self.to_numeral() as i32;
|
||||
let o_num = other.to_numeral() as i32;
|
||||
|
||||
if o_num - s_num >= 0 {
|
||||
(o_num - s_num) as u32
|
||||
} else {
|
||||
(7 + o_num - s_num) as u32
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn day_of_week(year: u32, month: u32, day: u32) -> ParseResult<DayOfWeek> {
|
||||
// From https://en.wikipedia.org/wiki/Determination_of_the_day_of_the_week#Schwerdtfeger's_method
|
||||
let (c, g) = match month {
|
||||
3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 => {
|
||||
let c = year / 100;
|
||||
(c, year - 100 * c)
|
||||
},
|
||||
1 | 2 => {
|
||||
let c = (year - 1) / 100;
|
||||
(c, year - 1 - 100 * c)
|
||||
},
|
||||
_ => return Err(ParseError::InvalidMonth)
|
||||
};
|
||||
|
||||
let e = match month {
|
||||
1 | 5 => 0,
|
||||
2 | 6 => 3,
|
||||
3 | 11 => 2,
|
||||
4 | 7 => 5,
|
||||
8 => 1,
|
||||
9 | 12 => 4,
|
||||
10 => 6,
|
||||
_ => panic!("Unreachable.")
|
||||
};
|
||||
|
||||
// This implementation is Gregorian-only.
|
||||
let f = match c % 4 {
|
||||
0 => 0,
|
||||
1 => 5,
|
||||
2 => 3,
|
||||
3 => 1,
|
||||
_ => panic!("Unreachable.")
|
||||
};
|
||||
|
||||
match (day + e + f + g + g / 4) % 7 {
|
||||
0 => Ok(DayOfWeek::Sunday),
|
||||
1 => Ok(DayOfWeek::Monday),
|
||||
2 => Ok(DayOfWeek::Tuesday),
|
||||
3 => Ok(DayOfWeek::Wednesday),
|
||||
4 => Ok(DayOfWeek::Thursday),
|
||||
5 => Ok(DayOfWeek::Friday),
|
||||
6 => Ok(DayOfWeek::Saturday),
|
||||
_ => panic!("Unreachable.")
|
||||
}
|
||||
}
|
||||
|
||||
mod test {
|
||||
|
||||
use weekday::day_of_week;
|
||||
use weekday::DayOfWeek;
|
||||
|
||||
#[test]
|
||||
fn day_of_week_examples() {
|
||||
assert_eq!(day_of_week(2018, 6, 24).unwrap(), DayOfWeek::Sunday);
|
||||
assert_eq!(day_of_week(2003, 9, 25).unwrap(), DayOfWeek::Thursday);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn weekday_difference() {
|
||||
|
||||
assert_eq!(DayOfWeek::Sunday.difference(DayOfWeek::Sunday), 0);
|
||||
assert_eq!(DayOfWeek::Sunday.difference(DayOfWeek::Monday), 1);
|
||||
assert_eq!(DayOfWeek::Sunday.difference(DayOfWeek::Tuesday), 2);
|
||||
assert_eq!(DayOfWeek::Sunday.difference(DayOfWeek::Wednesday), 3);
|
||||
assert_eq!(DayOfWeek::Sunday.difference(DayOfWeek::Thursday), 4);
|
||||
assert_eq!(DayOfWeek::Sunday.difference(DayOfWeek::Friday), 5);
|
||||
assert_eq!(DayOfWeek::Sunday.difference(DayOfWeek::Saturday), 6);
|
||||
assert_eq!(DayOfWeek::Monday.difference(DayOfWeek::Sunday), 6);
|
||||
assert_eq!(DayOfWeek::Tuesday.difference(DayOfWeek::Sunday), 5);
|
||||
assert_eq!(DayOfWeek::Wednesday.difference(DayOfWeek::Sunday), 4);
|
||||
assert_eq!(DayOfWeek::Thursday.difference(DayOfWeek::Sunday), 3);
|
||||
assert_eq!(DayOfWeek::Friday.difference(DayOfWeek::Sunday), 2);
|
||||
assert_eq!(DayOfWeek::Saturday.difference(DayOfWeek::Sunday), 1);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user