///|
/// A day of the week.
///
/// The variant order below has no calendar meaning by itself; use
/// `number_from_monday`, `number_from_sunday`, `num_days_from_monday`, or
/// `num_days_from_sunday` to get a day-of-week number in a specific
/// counting convention.
pub(all) enum Weekday {
Mon
Tue
Wed
Thu
Fri
Sat
Sun
} derive(Eq, Hash, @debug.Debug)
///|
pub extend Weekday with Eq::{equal}
///|
pub extend Weekday with Eq::{not_equal}
///|
pub extend Weekday with Hash::{hash, hash_combine}
///|
pub extend Weekday with @debug.Debug::{to_repr}
///|
/// The English name of the weekday.
pub fn Weekday::name(self : Weekday) -> String {
match self {
Mon => "Monday"
Tue => "Tuesday"
Wed => "Wednesday"
Thu => "Thursday"
Fri => "Friday"
Sat => "Saturday"
Sun => "Sunday"
}
}
///|
pub impl Show for Weekday with fn output(self, logger) {
logger.write_string(self.name())
}
///|
pub extend Weekday with Show::{to_string, output}
///|
fn Weekday::index(self : Weekday) -> Int {
match self {
Mon => 0
Tue => 1
Wed => 2
Thu => 3
Fri => 4
Sat => 5
Sun => 6
}
}
///|
/// The weekday `n` days after `self` (before it, for a negative `n`),
/// wrapping around the week in either direction.
pub fn Weekday::add_days(self : Weekday, n : Int) -> Weekday {
let index = (self.index() + n % 7 + 7) % 7
Weekday::from_num_days_from_monday(index).unwrap()
}
///|
/// The next day, wrapping from `Sun` back to `Mon`.
pub fn Weekday::succ(self : Weekday) -> Weekday {
match self {
Mon => Tue
Tue => Wed
Wed => Thu
Thu => Fri
Fri => Sat
Sat => Sun
Sun => Mon
}
}
///|
/// The previous day, wrapping from `Mon` back to `Sun`.
pub fn Weekday::pred(self : Weekday) -> Weekday {
match self {
Mon => Sun
Tue => Mon
Wed => Tue
Thu => Wed
Fri => Thu
Sat => Fri
Sun => Sat
}
}
///|
/// Day-of-week number counting from `Mon = 0`.
pub fn Weekday::num_days_from_monday(self : Weekday) -> Int {
self.index()
}
///|
/// Day-of-week number counting from `Sun = 0`.
pub fn Weekday::num_days_from_sunday(self : Weekday) -> Int {
(self.index() + 1) % 7
}
///|
/// ISO 8601 day-of-week number, counting from `Mon = 1`.
pub fn Weekday::number_from_monday(self : Weekday) -> Int {
self.num_days_from_monday() + 1
}
///|
/// Day-of-week number counting from `Sun = 1`.
pub fn Weekday::number_from_sunday(self : Weekday) -> Int {
self.num_days_from_sunday() + 1
}
///|
/// The `Weekday` whose `number_from_monday()` is `n` (ISO 8601 numbering:
/// `1` = `Mon`, `7` = `Sun`), or `None` if `n` is outside `1..=7`.
pub fn Weekday::from_number_from_monday(n : Int) -> Weekday? {
Weekday::from_num_days_from_monday(n - 1)
}
///|
/// The `Weekday` whose `number_from_sunday()` is `n` (`1` = `Sun`,
/// `7` = `Sat`), or `None` if `n` is outside `1..=7`.
pub fn Weekday::from_number_from_sunday(n : Int) -> Weekday? {
Weekday::from_num_days_from_sunday(n - 1)
}
///|
/// The `Weekday` whose `num_days_from_monday()` is `n` (`0` = `Mon`), or
/// `None` if `n` is outside `0..=6`.
pub fn Weekday::from_num_days_from_monday(n : Int) -> Weekday? {
match n {
0 => Some(Mon)
1 => Some(Tue)
2 => Some(Wed)
3 => Some(Thu)
4 => Some(Fri)
5 => Some(Sat)
6 => Some(Sun)
_ => None
}
}
///|
/// The `Weekday` whose `num_days_from_sunday()` is `n` (`0` = `Sun`), or
/// `None` if `n` is outside `0..=6`.
pub fn Weekday::from_num_days_from_sunday(n : Int) -> Weekday? {
match n {
0 => Some(Sun)
1..=6 => Weekday::from_num_days_from_monday(n - 1)
_ => None
}
}
///|
/// The weekday named by `name`: its full English name (`"Monday"`) or its
/// three-letter abbreviation (`"Mon"`), ignoring ASCII letter case, or
/// `None` for anything else (including a prefix, an abbreviation of another
/// length such as `"Tues"`, surrounding whitespace, or non-ASCII text).
pub fn Weekday::from_name(name : String) -> Weekday? {
let key = ascii_lower(name)
for number in 1..<=7 {
let day = Weekday::from_number_from_monday(number).unwrap()
if key == ascii_lower(day.name()) || key == ascii_lower(day.short_name()) {
return Some(day)
}
}
None
}
///|
/// The number of days elapsed since `other`, wrapping forward through the
/// week (always in `0..=6`).
pub fn Weekday::days_since(self : Weekday, other : Weekday) -> Int {
(self.index() - other.index() + 7) % 7
}
///|
fn weekday_from_days64(days : Int64) -> Weekday {
weekday_from_days(floor_mod64(days, 7L).to_int())
}
///|
/// The weekday of the given day count relative to the Unix epoch
/// (`1970-01-01`, day `0`, was a `Thu`).
fn weekday_from_days(days : Int) -> Weekday {
match floor_mod(days + 3, 7) {
0 => Mon
1 => Tue
2 => Wed
3 => Thu
4 => Fri
5 => Sat
_ => Sun
}
}