Compare commits
No commits in common. "f73aeb7769cc8e8c16db5680223338ff02288c61" and "c0def257fbddb39cf43881582e60bb8f2973da7a" have entirely different histories.
f73aeb7769
...
c0def257fb
10 changed files with 44 additions and 166 deletions
24
Cargo.lock
generated
24
Cargo.lock
generated
|
@ -11,36 +11,36 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.92"
|
||||
version = "1.0.78"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0"
|
||||
checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.37"
|
||||
version = "1.0.35"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af"
|
||||
checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.216"
|
||||
version = "1.0.196"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b9781016e935a97e8beecf0c933758c97a5520d32930e460142b4cd80c6338e"
|
||||
checksum = "870026e60fa08c69f064aa766c10f10b1d62db9ccd4d0abb206472bee0ce3b32"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.216"
|
||||
version = "1.0.196"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "46f859dbbf73865c6627ed570e78961cd3ac92407a2d117204c49232485da55e"
|
||||
checksum = "33c85360c95e7d137454dc81d9a4ed2b8efd8fbe19cee57357b32b9771fccb67"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
@ -49,9 +49,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.90"
|
||||
version = "2.0.48"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "919d3b74a5dd0ccd15aeb8f93e7006bd9e14c295087c9896a110f490752bcf31"
|
||||
checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
@ -60,6 +60,6 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.14"
|
||||
version = "1.0.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83"
|
||||
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
|
||||
|
|
|
@ -4,8 +4,6 @@ version = "0.1.0"
|
|||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
[features]
|
||||
serde = ["dep:serde"]
|
||||
|
||||
[dependencies]
|
||||
serde = { version = "1.0", features = ["derive"], optional = true }
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
|
|
19
README.md
19
README.md
|
@ -1,19 +0,0 @@
|
|||
Contents
|
||||
========
|
||||
- [Summary](#summary)
|
||||
- [Usage](#usage)
|
||||
|
||||
## Summary
|
||||
Epoch is a small library for converting Unix timestamps to human readable datetime
|
||||
and vice versa. It includes functionality for displaying a DateTime as a human
|
||||
readable string, parsing from string, and comparison for equality or ordering.
|
||||
|
||||
This crate is ideal when you want a lighter and simpler date/time library than the
|
||||
excellent and very complete [chrono](https://crates.io/crates/chrono), which is
|
||||
likely overkill for many use cases.
|
||||
|
||||
## Usage
|
||||
Add epoch to your Cargo.toml
|
||||
```Toml
|
||||
epoch = { git = "http://git.hitchhiker-linux.org/jeang3nie/epoch-rs.git" }
|
||||
```
|
124
src/datetime.rs
124
src/datetime.rs
|
@ -1,47 +1,13 @@
|
|||
#[cfg(feature = "serde")]
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use {
|
||||
crate::{
|
||||
month::Month, weekday::Weekday, year::Year, zone::TimeZone, SECONDS_PER_DAY,
|
||||
SECONDS_PER_HOUR, SECONDS_PER_MINUTE,
|
||||
},
|
||||
std::{
|
||||
cmp, fmt,
|
||||
num::TryFromIntError,
|
||||
time::{SystemTime, SystemTimeError, UNIX_EPOCH},
|
||||
},
|
||||
serde::{Deserialize, Serialize},
|
||||
std::{cmp, fmt},
|
||||
};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Error {
|
||||
System(SystemTimeError),
|
||||
RangeError,
|
||||
}
|
||||
|
||||
impl fmt::Display for Error {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
Self::System(e) => write!(f, "{e}"),
|
||||
Self::RangeError => write!(f, "self:?"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<SystemTimeError> for Error {
|
||||
fn from(value: SystemTimeError) -> Self {
|
||||
Self::System(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<TryFromIntError> for Error {
|
||||
fn from(_value: TryFromIntError) -> Self {
|
||||
Self::RangeError
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
|
||||
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
|
||||
pub struct DateTime {
|
||||
pub year: Year,
|
||||
pub month: Month,
|
||||
|
@ -93,40 +59,39 @@ impl DateTime {
|
|||
seconds
|
||||
}
|
||||
|
||||
#[allow(clippy::missing_panics_doc)]
|
||||
/// Converts a Unix timestamp to a `DateTime` struct
|
||||
pub fn from_timestamp(ts: i64) -> Self {
|
||||
if ts < 0 {
|
||||
let mut seconds: i64 = ts;
|
||||
let mut year = Year::new(1969);
|
||||
while seconds < -year.seconds() {
|
||||
seconds += year.seconds();
|
||||
let mut seconds: i64 = 0;
|
||||
let mut year = Year::new(-1);
|
||||
while seconds > -year.seconds() {
|
||||
seconds -= year.seconds();
|
||||
year = year.previous();
|
||||
}
|
||||
let mut month = Some(Month::December);
|
||||
while month.is_some() {
|
||||
let m = month.unwrap();
|
||||
if -seconds < m.seconds(year) {
|
||||
if seconds > m.seconds(year) {
|
||||
break;
|
||||
}
|
||||
seconds += m.seconds(year);
|
||||
seconds -= m.seconds(year);
|
||||
month = m.previous();
|
||||
}
|
||||
let month = month.unwrap();
|
||||
let mut day = month.days(year);
|
||||
while day > 0 && seconds < -SECONDS_PER_DAY {
|
||||
seconds += SECONDS_PER_DAY;
|
||||
seconds -= SECONDS_PER_HOUR;
|
||||
day -= 1;
|
||||
}
|
||||
let mut hour: i8 = 23;
|
||||
while hour > 0 && seconds < -SECONDS_PER_HOUR {
|
||||
seconds += SECONDS_PER_HOUR;
|
||||
while hour >= 0 && seconds < -SECONDS_PER_HOUR {
|
||||
seconds -= SECONDS_PER_HOUR;
|
||||
hour -= 1;
|
||||
}
|
||||
let hour = hour.try_into().unwrap();
|
||||
let mut minute: i8 = 59;
|
||||
while minute > 0 && seconds < -60 {
|
||||
seconds += 60;
|
||||
let mut minute: i8 = 60;
|
||||
while minute >= 0 && seconds < -60 {
|
||||
seconds -= 60;
|
||||
minute -= 1;
|
||||
}
|
||||
let minute = minute.try_into().unwrap();
|
||||
|
@ -180,30 +145,13 @@ impl DateTime {
|
|||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::missing_panics_doc)]
|
||||
/// Creates a `DateTime` from the system time
|
||||
pub fn now() -> Result<Self, Error> {
|
||||
let now = SystemTime::now().duration_since(UNIX_EPOCH)?;
|
||||
Ok(Self::from_timestamp(i64::try_from(now.as_secs())?))
|
||||
}
|
||||
|
||||
#[allow(clippy::missing_panics_doc)]
|
||||
/// Gets the day of the week for this `DateTime`
|
||||
pub fn weekday(&self) -> Weekday {
|
||||
let ts = self.timestamp_naive();
|
||||
let mut days = ts / SECONDS_PER_DAY;
|
||||
// For negative timestamps this number is actually the following day
|
||||
if ts < 0 {
|
||||
days -= 1;
|
||||
}
|
||||
// Rusts `%` operator is modulo, not modulus. We have to use the
|
||||
// operation which will gove the correct answer for either positive
|
||||
// or negative remainders
|
||||
let rem = days.rem_euclid(7);
|
||||
let days = ts / SECONDS_PER_DAY;
|
||||
let rem = days % 7;
|
||||
rem.try_into().unwrap()
|
||||
}
|
||||
|
||||
/// Returns a string representing this date and time in human readable format
|
||||
pub fn display(&self) -> String {
|
||||
format!(
|
||||
"{} {} {} {:0>2}:{:0>2}:{:0>2} {} {}",
|
||||
|
@ -279,28 +227,6 @@ mod tests {
|
|||
},
|
||||
};
|
||||
assert_eq!(dt.weekday(), Weekday::Saturday);
|
||||
dt = DateTime {
|
||||
year: Year::new(1965),
|
||||
month: Month::February,
|
||||
day: 9,
|
||||
hour: 4,
|
||||
minute: 4,
|
||||
second: 37,
|
||||
zone: TimeZone::Utc,
|
||||
};
|
||||
assert_eq!(dt.weekday(), Weekday::Tuesday);
|
||||
dt.day -= 1;
|
||||
assert_eq!(dt.weekday(), Weekday::Monday);
|
||||
dt.day -= 1;
|
||||
assert_eq!(dt.weekday(), Weekday::Sunday);
|
||||
dt.day -= 1;
|
||||
assert_eq!(dt.weekday(), Weekday::Saturday);
|
||||
dt.day -= 1;
|
||||
assert_eq!(dt.weekday(), Weekday::Friday);
|
||||
dt.day -= 1;
|
||||
assert_eq!(dt.weekday(), Weekday::Thursday);
|
||||
dt.day -= 1;
|
||||
assert_eq!(dt.weekday(), Weekday::Wednesday);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -342,22 +268,6 @@ mod tests {
|
|||
assert_eq!(dt, DateTime::from_timestamp(ts));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ts_negative() {
|
||||
let ts: i64 = -154382123;
|
||||
let dt = DateTime {
|
||||
year: Year::new(1965),
|
||||
month: Month::February,
|
||||
day: 9,
|
||||
hour: 4,
|
||||
minute: 4,
|
||||
second: 37,
|
||||
zone: TimeZone::Utc,
|
||||
};
|
||||
assert_eq!(dt.timestamp(), ts);
|
||||
assert_eq!(dt, DateTime::from_timestamp(ts));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn fmt() {
|
||||
let mut dt = DateTime::from_timestamp(1706571482);
|
||||
|
|
|
@ -8,8 +8,6 @@ pub(crate) mod year;
|
|||
pub(crate) mod zone;
|
||||
|
||||
pub mod prelude;
|
||||
pub use datetime::DateTime;
|
||||
pub use datetime::Error as DateTimeError;
|
||||
|
||||
pub static SECONDS_PER_MINUTE: i64 = 60;
|
||||
pub static SECONDS_PER_HOUR: i64 = 60 * 60;
|
||||
|
|
11
src/month.rs
11
src/month.rs
|
@ -1,13 +1,12 @@
|
|||
#[cfg(feature = "serde")]
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::str::FromStr;
|
||||
|
||||
use {
|
||||
crate::{year::Year, SECONDS_PER_DAY},
|
||||
std::{cmp, error, fmt, str},
|
||||
serde::{Deserialize, Serialize},
|
||||
std::{cmp, error, fmt},
|
||||
};
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Serialize, PartialEq, Eq)]
|
||||
#[repr(u8)]
|
||||
pub enum Month {
|
||||
Janurary = 1,
|
||||
|
@ -139,7 +138,7 @@ impl fmt::Display for Month {
|
|||
}
|
||||
}
|
||||
|
||||
impl str::FromStr for Month {
|
||||
impl FromStr for Month {
|
||||
type Err = Error;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
pub use crate::{
|
||||
datetime::DateTime,
|
||||
month::{Error as MonthError, Month},
|
||||
weekday::Weekday,
|
||||
year::Year,
|
||||
|
|
|
@ -1,10 +1,8 @@
|
|||
#[cfg(feature = "serde")]
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use std::fmt;
|
||||
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
|
||||
#[repr(u8)]
|
||||
pub enum Weekday {
|
||||
Thursday,
|
||||
|
|
|
@ -1,13 +1,10 @@
|
|||
#[cfg(feature = "serde")]
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use {
|
||||
crate::SECONDS_PER_DAY,
|
||||
serde::{Deserialize, Serialize},
|
||||
std::{cmp, fmt, num::ParseIntError, str::FromStr},
|
||||
};
|
||||
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
|
||||
pub enum Year {
|
||||
Normal(i32),
|
||||
Leap(i32),
|
||||
|
|
10
src/zone.rs
10
src/zone.rs
|
@ -1,13 +1,10 @@
|
|||
#[cfg(feature = "serde")]
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use {
|
||||
crate::SECONDS_PER_HOUR,
|
||||
serde::{Deserialize, Serialize},
|
||||
std::{error, fmt, str::FromStr},
|
||||
};
|
||||
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
|
||||
pub enum Sign {
|
||||
Positive,
|
||||
Negative,
|
||||
|
@ -26,8 +23,7 @@ impl fmt::Display for Sign {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
|
||||
pub enum TimeZone {
|
||||
Offset { sign: Sign, hours: u8, minutes: u8 },
|
||||
Utc,
|
||||
|
|
Loading…
Add table
Reference in a new issue