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]]
|
[[package]]
|
||||||
name = "proc-macro2"
|
name = "proc-macro2"
|
||||||
version = "1.0.92"
|
version = "1.0.78"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0"
|
checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "quote"
|
name = "quote"
|
||||||
version = "1.0.37"
|
version = "1.0.35"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af"
|
checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
version = "1.0.216"
|
version = "1.0.196"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0b9781016e935a97e8beecf0c933758c97a5520d32930e460142b4cd80c6338e"
|
checksum = "870026e60fa08c69f064aa766c10f10b1d62db9ccd4d0abb206472bee0ce3b32"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde_derive",
|
"serde_derive",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_derive"
|
name = "serde_derive"
|
||||||
version = "1.0.216"
|
version = "1.0.196"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "46f859dbbf73865c6627ed570e78961cd3ac92407a2d117204c49232485da55e"
|
checksum = "33c85360c95e7d137454dc81d9a4ed2b8efd8fbe19cee57357b32b9771fccb67"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
@ -49,9 +49,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "2.0.90"
|
version = "2.0.48"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "919d3b74a5dd0ccd15aeb8f93e7006bd9e14c295087c9896a110f490752bcf31"
|
checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
@ -60,6 +60,6 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-ident"
|
name = "unicode-ident"
|
||||||
version = "1.0.14"
|
version = "1.0.12"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83"
|
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
|
||||||
|
|
|
@ -4,8 +4,6 @@ version = "0.1.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
[features]
|
|
||||||
serde = ["dep:serde"]
|
|
||||||
|
|
||||||
[dependencies]
|
[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 {
|
use {
|
||||||
crate::{
|
crate::{
|
||||||
month::Month, weekday::Weekday, year::Year, zone::TimeZone, SECONDS_PER_DAY,
|
month::Month, weekday::Weekday, year::Year, zone::TimeZone, SECONDS_PER_DAY,
|
||||||
SECONDS_PER_HOUR, SECONDS_PER_MINUTE,
|
SECONDS_PER_HOUR, SECONDS_PER_MINUTE,
|
||||||
},
|
},
|
||||||
std::{
|
serde::{Deserialize, Serialize},
|
||||||
cmp, fmt,
|
std::{cmp, fmt},
|
||||||
num::TryFromIntError,
|
|
||||||
time::{SystemTime, SystemTimeError, UNIX_EPOCH},
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
|
||||||
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))]
|
|
||||||
pub struct DateTime {
|
pub struct DateTime {
|
||||||
pub year: Year,
|
pub year: Year,
|
||||||
pub month: Month,
|
pub month: Month,
|
||||||
|
@ -93,40 +59,39 @@ impl DateTime {
|
||||||
seconds
|
seconds
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::missing_panics_doc)]
|
|
||||||
/// Converts a Unix timestamp to a `DateTime` struct
|
/// Converts a Unix timestamp to a `DateTime` struct
|
||||||
pub fn from_timestamp(ts: i64) -> Self {
|
pub fn from_timestamp(ts: i64) -> Self {
|
||||||
if ts < 0 {
|
if ts < 0 {
|
||||||
let mut seconds: i64 = ts;
|
let mut seconds: i64 = 0;
|
||||||
let mut year = Year::new(1969);
|
let mut year = Year::new(-1);
|
||||||
while seconds < -year.seconds() {
|
while seconds > -year.seconds() {
|
||||||
seconds += year.seconds();
|
seconds -= year.seconds();
|
||||||
year = year.previous();
|
year = year.previous();
|
||||||
}
|
}
|
||||||
let mut month = Some(Month::December);
|
let mut month = Some(Month::December);
|
||||||
while month.is_some() {
|
while month.is_some() {
|
||||||
let m = month.unwrap();
|
let m = month.unwrap();
|
||||||
if -seconds < m.seconds(year) {
|
if seconds > m.seconds(year) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
seconds += m.seconds(year);
|
seconds -= m.seconds(year);
|
||||||
month = m.previous();
|
month = m.previous();
|
||||||
}
|
}
|
||||||
let month = month.unwrap();
|
let month = month.unwrap();
|
||||||
let mut day = month.days(year);
|
let mut day = month.days(year);
|
||||||
while day > 0 && seconds < -SECONDS_PER_DAY {
|
while day > 0 && seconds < -SECONDS_PER_DAY {
|
||||||
seconds += SECONDS_PER_DAY;
|
seconds -= SECONDS_PER_HOUR;
|
||||||
day -= 1;
|
day -= 1;
|
||||||
}
|
}
|
||||||
let mut hour: i8 = 23;
|
let mut hour: i8 = 23;
|
||||||
while hour > 0 && seconds < -SECONDS_PER_HOUR {
|
while hour >= 0 && seconds < -SECONDS_PER_HOUR {
|
||||||
seconds += SECONDS_PER_HOUR;
|
seconds -= SECONDS_PER_HOUR;
|
||||||
hour -= 1;
|
hour -= 1;
|
||||||
}
|
}
|
||||||
let hour = hour.try_into().unwrap();
|
let hour = hour.try_into().unwrap();
|
||||||
let mut minute: i8 = 59;
|
let mut minute: i8 = 60;
|
||||||
while minute > 0 && seconds < -60 {
|
while minute >= 0 && seconds < -60 {
|
||||||
seconds += 60;
|
seconds -= 60;
|
||||||
minute -= 1;
|
minute -= 1;
|
||||||
}
|
}
|
||||||
let minute = minute.try_into().unwrap();
|
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 {
|
pub fn weekday(&self) -> Weekday {
|
||||||
let ts = self.timestamp_naive();
|
let ts = self.timestamp_naive();
|
||||||
let mut days = ts / SECONDS_PER_DAY;
|
let days = ts / SECONDS_PER_DAY;
|
||||||
// For negative timestamps this number is actually the following day
|
let rem = days % 7;
|
||||||
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);
|
|
||||||
rem.try_into().unwrap()
|
rem.try_into().unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a string representing this date and time in human readable format
|
|
||||||
pub fn display(&self) -> String {
|
pub fn display(&self) -> String {
|
||||||
format!(
|
format!(
|
||||||
"{} {} {} {:0>2}:{:0>2}:{:0>2} {} {}",
|
"{} {} {} {:0>2}:{:0>2}:{:0>2} {} {}",
|
||||||
|
@ -279,28 +227,6 @@ mod tests {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
assert_eq!(dt.weekday(), Weekday::Saturday);
|
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]
|
#[test]
|
||||||
|
@ -342,22 +268,6 @@ mod tests {
|
||||||
assert_eq!(dt, DateTime::from_timestamp(ts));
|
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]
|
#[test]
|
||||||
fn fmt() {
|
fn fmt() {
|
||||||
let mut dt = DateTime::from_timestamp(1706571482);
|
let mut dt = DateTime::from_timestamp(1706571482);
|
||||||
|
|
|
@ -8,8 +8,6 @@ pub(crate) mod year;
|
||||||
pub(crate) mod zone;
|
pub(crate) mod zone;
|
||||||
|
|
||||||
pub mod prelude;
|
pub mod prelude;
|
||||||
pub use datetime::DateTime;
|
|
||||||
pub use datetime::Error as DateTimeError;
|
|
||||||
|
|
||||||
pub static SECONDS_PER_MINUTE: i64 = 60;
|
pub static SECONDS_PER_MINUTE: i64 = 60;
|
||||||
pub static SECONDS_PER_HOUR: i64 = 60 * 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 std::str::FromStr;
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
|
|
||||||
use {
|
use {
|
||||||
crate::{year::Year, SECONDS_PER_DAY},
|
crate::{year::Year, SECONDS_PER_DAY},
|
||||||
std::{cmp, error, fmt, str},
|
serde::{Deserialize, Serialize},
|
||||||
|
std::{cmp, error, fmt},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
#[derive(Clone, Copy, Debug, Deserialize, Serialize, PartialEq, Eq)]
|
||||||
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
|
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
pub enum Month {
|
pub enum Month {
|
||||||
Janurary = 1,
|
Janurary = 1,
|
||||||
|
@ -139,7 +138,7 @@ impl fmt::Display for Month {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl str::FromStr for Month {
|
impl FromStr for Month {
|
||||||
type Err = Error;
|
type Err = Error;
|
||||||
|
|
||||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
pub use crate::{
|
pub use crate::{
|
||||||
|
datetime::DateTime,
|
||||||
month::{Error as MonthError, Month},
|
month::{Error as MonthError, Month},
|
||||||
weekday::Weekday,
|
weekday::Weekday,
|
||||||
year::Year,
|
year::Year,
|
||||||
|
|
|
@ -1,10 +1,8 @@
|
||||||
#[cfg(feature = "serde")]
|
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
|
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
use serde::{Deserialize, Serialize};
|
||||||
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
|
|
||||||
|
#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
pub enum Weekday {
|
pub enum Weekday {
|
||||||
Thursday,
|
Thursday,
|
||||||
|
|
|
@ -1,13 +1,10 @@
|
||||||
#[cfg(feature = "serde")]
|
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
|
|
||||||
use {
|
use {
|
||||||
crate::SECONDS_PER_DAY,
|
crate::SECONDS_PER_DAY,
|
||||||
|
serde::{Deserialize, Serialize},
|
||||||
std::{cmp, fmt, num::ParseIntError, str::FromStr},
|
std::{cmp, fmt, num::ParseIntError, str::FromStr},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
|
||||||
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
|
|
||||||
pub enum Year {
|
pub enum Year {
|
||||||
Normal(i32),
|
Normal(i32),
|
||||||
Leap(i32),
|
Leap(i32),
|
||||||
|
|
10
src/zone.rs
10
src/zone.rs
|
@ -1,13 +1,10 @@
|
||||||
#[cfg(feature = "serde")]
|
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
|
|
||||||
use {
|
use {
|
||||||
crate::SECONDS_PER_HOUR,
|
crate::SECONDS_PER_HOUR,
|
||||||
|
serde::{Deserialize, Serialize},
|
||||||
std::{error, fmt, str::FromStr},
|
std::{error, fmt, str::FromStr},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
|
||||||
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
|
|
||||||
pub enum Sign {
|
pub enum Sign {
|
||||||
Positive,
|
Positive,
|
||||||
Negative,
|
Negative,
|
||||||
|
@ -26,8 +23,7 @@ impl fmt::Display for Sign {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
|
||||||
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
|
|
||||||
pub enum TimeZone {
|
pub enum TimeZone {
|
||||||
Offset { sign: Sign, hours: u8, minutes: u8 },
|
Offset { sign: Sign, hours: u8, minutes: u8 },
|
||||||
Utc,
|
Utc,
|
||||||
|
|
Loading…
Add table
Reference in a new issue