mod date;
pub(crate) mod month;
#[macro_use]
mod macros;
mod time;
mod utc;
pub mod zone;
use std::fmt;
use std::num::ParseIntError;
use std::str::FromStr;
use crate::{
Point,
Span,
Frame,
real::Scale
};
use zone::Unsteady;
pub struct Utc;
pub struct Calendar<Z>(
pub Z
);
#[derive(Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub struct DateTime (pub Date, pub Time);
#[derive(Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub struct Date {
pub y: i64,
pub m: u8,
pub d: u8
}
#[derive(Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub struct Time {
pub h: u8,
pub m: u8,
pub s: u8
}
#[allow(missing_docs)]
#[derive(Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub enum Weekday {
Monday,
Tuesday,
Wednesday,
Thursday,
Friday,
Saturday,
Sunday
}
pub struct Frames<'c, Z> {
calendar: &'c Calendar<Z>,
scale: Scale,
previous: Point,
state: State
}
pub struct FramesRev<'c, Z>(pub Frames<'c, Z>);
enum State {
Date(Date),
Utc(Point),
Seconds
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ParseError {
ParseInt(ParseIntError),
Empty,
Format,
Invalid
}
impl fmt::Display for DateTime {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let Self (date, time) = self;
write!(f, "{date} {time}")
}
}
impl fmt::Debug for DateTime {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(self, f)
}
}
impl FromStr for DateTime {
type Err = ParseError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
if s.is_empty() {return Err(ParseError::Empty)}
let mut split = s.splitn(2, [' ', 'T']);
let date = split.next()
.ok_or(ParseError::Format)?
.parse()?;
let time = split.next()
.ok_or(ParseError::Format)?
.parse()?;
Ok(Self (date, time))
}
}
impl fmt::Display for Weekday {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let day = match self {
Weekday::Monday => "Monday",
Weekday::Tuesday => "Tuesday",
Weekday::Wednesday => "Wednesday",
Weekday::Thursday => "Thursday",
Weekday::Friday => "Friday",
Weekday::Saturday => "Saturday",
Weekday::Sunday => "Sunday",
};
f.write_str(day)
}
}
impl fmt::Debug for Weekday {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(self, f)
}
}
impl State {
fn forward<Z: Unsteady>(
&mut self,
calendar: &Calendar<Z>,
scale: Scale,
previous: Point)
-> Point
{
match self {
Self::Date(ref mut date) if scale == Scale::Years => {
date.y += 1;
calendar.resolve_earliest_midnight(*date)
},
Self::Date(ref mut date) if scale == Scale::Months => {
match date.m == 12 {
true => {
date.y += 1;
date.m = 1;
},
false => date.m += 1
};
calendar.resolve_earliest_midnight(*date)
},
Self::Date(_) => unreachable!(),
Self::Utc(ref mut utc_point) => {
*utc_point = *utc_point + Span::from(scale);
calendar.0.revert_to_earliest(*utc_point)
},
Self::Seconds => previous + Span::SECOND
}
}
fn backward<Z: Unsteady>(
&mut self,
calendar: &Calendar<Z>,
scale: Scale,
previous: Point)
-> Point
{
match self {
Self::Date(ref mut date) if scale == Scale::Years => {
date.y -= 1;
calendar.resolve_earliest_midnight(*date)
},
Self::Date(ref mut date) if scale == Scale::Months => {
match date.m == 1 {
true => {
date.y -= 1;
date.m = 12;
},
false => date.m -= 1
};
calendar.resolve_earliest_midnight(*date)
},
Self::Date(_) => unreachable!(),
Self::Utc(ref mut utc_point) => {
*utc_point = *utc_point - Span::from(scale);
calendar.0.revert_to_earliest(*utc_point)
},
Self::Seconds => previous - Span::SECOND
}
}
}
impl<'c, Z: Unsteady> Iterator for Frames<'c, Z> {
type Item = Frame;
fn next(&mut self) -> Option<Self::Item> {
loop {
let start = self.previous;
let stop = self.state.forward(
self.calendar,
self.scale,
self.previous
);
self.previous = stop;
if start != stop {
break Some(Frame {start, stop});
}
else {continue}
}
}
}
impl<'c, Z> Frames<'c, Z> {
pub fn rev(self) -> FramesRev<'c, Z> {FramesRev(self)}
}
impl<'c, Z: Unsteady> Frames<'c, Z> {
pub fn prev(&mut self) -> Frame {
loop {
let stop = self.previous;
let start = self.state.backward(
self.calendar,
self.scale,
self.previous
);
self.previous = start;
if start != stop {
break Frame {start, stop};
}
else {continue}
}
}
}
impl<'c, Z: Unsteady> Iterator for FramesRev<'c, Z> {
type Item = Frame;
fn next(&mut self) -> Option<Self::Item> {Some(self.0.prev())}
}
impl<'c, Z: Unsteady> FramesRev<'c, Z> {
pub fn prev(&mut self) -> Frame {self.0.next().unwrap()}
}
impl fmt::Display for ParseError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::ParseInt(e) => fmt::Display::fmt(e, f),
Self::Empty => f.write_str("invalid empty date/time"),
Self::Format => f.write_str("invalid date/time format"),
Self::Invalid => f.write_str("invalid date/time")
}
}
}
impl From<ParseIntError> for ParseError {
fn from(e: ParseIntError) -> Self {Self::ParseInt(e)}
}