use std::cmp;
use std::fmt;
#[derive(Debug, PartialEq, Eq, Clone, Hash)]
pub struct Time(pub u8, pub u8, pub u8);
impl Time {
pub fn midnight() -> Self {
Self(0, 0, 0)
}
pub fn new_h(hour: u8) -> Self {
Self(hour, 0, 0)
}
pub fn new_hm(hour: u8, minute: u8) -> Self {
Self(hour, minute, 0)
}
pub fn new_hms(hour: u8, minute: u8, second: u8) -> Self {
Self(hour, minute, second)
}
pub fn as_minutes(&self) -> u16 {
(self.0 as u16) * 60 + (self.1 as u16)
}
pub fn from_minutes(minutes: u16) -> Self {
Self::new_hm(((minutes / 60) % 24) as u8, (minutes % 60) as u8)
}
pub fn as_seconds(&self) -> u32 {
((self.0 as u32) * 60 + (self.1 as u32)) * 60 + (self.2 as u32)
}
pub fn from_seconds(seconds: u32) -> Self {
let minutes = seconds / 60;
Self::new_hms(
((minutes / 60) % 24) as u8,
(minutes % 60) as u8,
(seconds % 60) as u8,
)
}
}
impl cmp::PartialOrd for Time {
fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
Some(self.cmp(other))
}
}
impl cmp::Ord for Time {
fn cmp(&self, other: &Self) -> cmp::Ordering {
self.as_seconds().cmp(&other.as_seconds())
}
}
impl fmt::Display for Time {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let mut print_mins = true;
let mut print_secs = self.2 != 0;
if let Some(precision) = f.precision() {
if precision == 1 {
print_mins = false;
print_secs = false;
} else if precision == 2 {
print_secs = false;
} else if precision >= 3 {
print_secs = true;
}
}
if f.alternate() {
if self.0 % 12 == 0 {
write!(f, "12")?;
} else {
write!(f, "{:02}", self.0 % 12)?;
}
} else {
write!(f, "{:02}", self.0 % 24)?;
}
if print_mins {
write!(f, ":{:02}", self.1 % 60)?;
if print_secs {
write!(f, ":{:02}", self.2 % 60)?;
}
}
if f.alternate() {
if self.0 < 12 {
write!(f, " AM")?;
} else {
write!(f, " PM")?;
}
}
Ok(())
}
}
pub struct Clock {
hour: u8,
minute: u8,
second: u8,
hour_inc: u8,
minute_inc: u8,
second_inc: u8,
}
impl Clock {
pub fn seconds() -> Self {
Self {
hour: 0,
minute: 0,
second: 0,
hour_inc: 0,
minute_inc: 0,
second_inc: 1,
}
}
pub fn minutes() -> Self {
Self {
hour: 0,
minute: 0,
second: 0,
hour_inc: 0,
minute_inc: 1,
second_inc: 0,
}
}
pub fn hours() -> Self {
Self {
hour: 0,
minute: 0,
second: 0,
hour_inc: 1,
minute_inc: 0,
second_inc: 0,
}
}
pub fn every(hours: u8, minutes: u8, seconds: u8) -> Self {
Self {
hour: 0,
minute: 0,
second: 0,
hour_inc: hours,
minute_inc: minutes,
second_inc: seconds,
}
}
pub fn start_h(self, hour: u8) -> Self {
Self {
hour: hour % 24,
minute: 0,
second: 0,
..self
}
}
pub fn start_hm(self, hour: u8, minute: u8) -> Self {
Self {
hour: hour % 24,
minute: minute % 60,
second: 0,
..self
}
}
pub fn start_hms(self, hour: u8, minute: u8, second: u8) -> Self {
Self {
hour: hour % 24,
minute: minute % 60,
second: second % 60,
..self
}
}
}
impl Iterator for Clock {
type Item = Time;
fn next(&mut self) -> Option<Self::Item> {
if self.hour >= 24 {
None
} else {
let r = Time::new_hms(self.hour, self.minute, self.second);
self.hour += self.hour_inc;
self.minute += self.minute_inc;
self.second += self.second_inc;
if self.second >= 60 {
self.minute += self.second / 60;
self.second %= 60;
}
if self.minute >= 60 {
self.hour += self.minute / 60;
self.minute %= 60;
}
Some(r)
}
}
}