Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a TimeConfigBuilder to avoid further breaking changes #46

Merged
merged 5 commits into from
Jul 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
name = "speedate"
authors = ["Samuel Colvin <s@muelcolvin.com>"]
version = "0.11.0"
version = "0.12.0"
edition = "2021"
description = "Fast and simple datetime, date, time and duration parsing"
readme = "README.md"
Expand Down
31 changes: 31 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,37 @@ fn main() {
}
```

To control the specifics of time parsing you can use provide a `TimeConfig`:

```rust
use speedate::{DateTime, Date, Time, TimeConfig};

fn main() {
let dt = DateTime::parse_bytes_with_config(
"1689102037.5586429".as_bytes(),
&TimeConfig::builder().unix_timestamp_offset(Some(0)).build(),
).unwrap();
assert_eq!(
dt,
DateTime {
date: Date {
year: 2023,
month: 7,
day: 11,
},
time: Time {
hour: 19,
minute: 0,
second: 37,
microsecond: 558643,
tz_offset: Some(0),
},
}
);
assert_eq!(dt.to_string(), "2023-07-11T19:00:37.558643Z");
}
```

## Performance

**speedate** is significantly faster than
Expand Down
23 changes: 12 additions & 11 deletions src/datetime.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::numbers::{float_parse_bytes, IntFloat};
use crate::{Date, ParseError, Time, TimeConfig};
use crate::TimeConfigBuilder;
use crate::{time::TimeConfig, Date, ParseError, Time};
use std::cmp::Ordering;
use std::fmt;
use std::time::SystemTime;
Expand Down Expand Up @@ -236,7 +237,7 @@ impl DateTime {
/// assert_eq!(dt.to_string(), "2022-01-01T12:13:14Z");
/// ```
pub fn parse_bytes_rfc3339(bytes: &[u8]) -> Result<Self, ParseError> {
DateTime::parse_bytes_rfc3339_with_config(bytes, &TimeConfig::default())
DateTime::parse_bytes_rfc3339_with_config(bytes, &TimeConfigBuilder::new().build())
}

/// Same as `parse_bytes_rfc3339` with with a `TimeConfig` parameter.
Expand All @@ -249,9 +250,9 @@ impl DateTime {
/// # Examples
///
/// ```
/// use speedate::{DateTime, Date, Time, TimeConfig};
/// use speedate::{DateTime, Date, Time, TimeConfigBuilder};
///
/// let dt = DateTime::parse_bytes_rfc3339_with_config(b"2022-01-01T12:13:14Z", &TimeConfig::default()).unwrap();
/// let dt = DateTime::parse_bytes_rfc3339_with_config(b"2022-01-01T12:13:14Z", &TimeConfigBuilder::new().build()).unwrap();
/// assert_eq!(
/// dt,
/// DateTime {
Expand Down Expand Up @@ -305,7 +306,7 @@ impl DateTime {
/// assert_eq!(dt.to_string(), "2022-01-01T12:13:14");
/// ```
pub fn parse_bytes(bytes: &[u8]) -> Result<Self, ParseError> {
DateTime::parse_bytes_with_config(bytes, &TimeConfig::default())
DateTime::parse_bytes_with_config(bytes, &TimeConfigBuilder::new().build())
}

/// Same as `DateTime::parse_bytes` but supporting TimeConfig
Expand All @@ -318,9 +319,9 @@ impl DateTime {
/// # Examples
///
/// ```
/// use speedate::{DateTime, Date, Time, TimeConfig};
/// use speedate::{DateTime, Date, Time, TimeConfigBuilder};
///
/// let dt = DateTime::parse_bytes_with_config(b"2022-01-01T12:13:14Z", &TimeConfig::default()).unwrap();
/// let dt = DateTime::parse_bytes_with_config(b"2022-01-01T12:13:14Z", &TimeConfigBuilder::new().build()).unwrap();
/// assert_eq!(dt.to_string(), "2022-01-01T12:13:14Z");
/// ```
pub fn parse_bytes_with_config(bytes: &[u8], config: &TimeConfig) -> Result<Self, ParseError> {
Expand Down Expand Up @@ -364,12 +365,12 @@ impl DateTime {
/// # Examples
///
/// ```
/// use speedate::{DateTime, TimeConfig};
/// use speedate::{DateTime, TimeConfigBuilder};
///
/// let d = DateTime::from_timestamp_with_config(1_654_619_320, 123, &TimeConfig::default()).unwrap();
/// let d = DateTime::from_timestamp_with_config(1_654_619_320, 123, &TimeConfigBuilder::new().build()).unwrap();
/// assert_eq!(d.to_string(), "2022-06-07T16:28:40.000123");
///
/// let d = DateTime::from_timestamp_with_config(1_654_619_320_123, 123_000, &TimeConfig::default()).unwrap();
/// let d = DateTime::from_timestamp_with_config(1_654_619_320_123, 123_000, &TimeConfigBuilder::new().build()).unwrap();
/// assert_eq!(d.to_string(), "2022-06-07T16:28:40.246");
/// ```
pub fn from_timestamp_with_config(
Expand Down Expand Up @@ -431,7 +432,7 @@ impl DateTime {
/// assert_eq!(d.to_string(), "2022-06-07T16:28:40.246");
/// ```
pub fn from_timestamp(timestamp: i64, timestamp_microsecond: u32) -> Result<Self, ParseError> {
Self::from_timestamp_with_config(timestamp, timestamp_microsecond, &TimeConfig::default())
Self::from_timestamp_with_config(timestamp, timestamp_microsecond, &TimeConfigBuilder::new().build())
}

/// Create a datetime from the system time. This method uses [std::time::SystemTime] to get
Expand Down
10 changes: 5 additions & 5 deletions src/duration.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::cmp::Ordering;
use std::fmt;

use crate::{ParseError, Time, TimeConfig};
use crate::{time::TimeConfig, ParseError, Time, TimeConfigBuilder};

/// A Duration
///
Expand Down Expand Up @@ -231,7 +231,7 @@ impl Duration {
/// ```
#[inline]
pub fn parse_bytes(bytes: &[u8]) -> Result<Self, ParseError> {
Duration::parse_bytes_with_config(bytes, &TimeConfig::default())
Duration::parse_bytes_with_config(bytes, &TimeConfigBuilder::new().build())
}

/// Same as `Duration::parse_bytes` but with a TimeConfig component.
Expand All @@ -244,9 +244,9 @@ impl Duration {
/// # Examples
///
/// ```
/// use speedate::{Duration, TimeConfig};
/// use speedate::{Duration, TimeConfigBuilder};
///
/// let d = Duration::parse_bytes_with_config(b"P1Y", &TimeConfig::default()).unwrap();
/// let d = Duration::parse_bytes_with_config(b"P1Y", &TimeConfigBuilder::new().build()).unwrap();
/// assert_eq!(
/// d,
/// Duration {
Expand Down Expand Up @@ -454,7 +454,7 @@ impl Duration {

match bytes.get(position).copied() {
Some(_) => {
let t = Time::parse_bytes_offset(bytes, position, &TimeConfig::default())?;
let t = Time::parse_bytes_offset(bytes, position, &TimeConfigBuilder::new().build())?;

Ok(Self {
positive: false, // is set above
Expand Down
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ mod time;
pub use date::Date;
pub use datetime::DateTime;
pub use duration::Duration;
pub use time::{MicrosecondsPrecisionOverflowBehavior, Time, TimeConfig};
pub use time::{MicrosecondsPrecisionOverflowBehavior, Time, TimeConfig, TimeConfigBuilder};

pub use numbers::{float_parse_bytes, float_parse_str, int_parse_bytes, int_parse_str, IntFloat};

Expand Down
55 changes: 47 additions & 8 deletions src/time.rs
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ impl Time {
/// ```
#[inline]
pub fn parse_bytes(bytes: &[u8]) -> Result<Self, ParseError> {
Self::parse_bytes_offset(bytes, 0, &TimeConfig::default())
Self::parse_bytes_offset(bytes, 0, &TimeConfigBuilder::new().build())
}

/// Same as `Time::parse_bytes` but with a `TimeConfig`.
Expand All @@ -199,9 +199,9 @@ impl Time {
/// # Examples
///
/// ```
/// use speedate::{Time, TimeConfig};
/// use speedate::{Time, TimeConfigBuilder};
///
/// let d = Time::parse_bytes_with_config(b"12:13:14.123456", &TimeConfig::default()).unwrap();
/// let d = Time::parse_bytes_with_config(b"12:13:14.123456", &TimeConfigBuilder::new().build()).unwrap();
/// assert_eq!(
/// d,
/// Time {
Expand Down Expand Up @@ -237,7 +237,11 @@ impl Time {
/// assert_eq!(d.to_string(), "01:02:20.000123");
/// ```
pub fn from_timestamp(timestamp_second: u32, timestamp_microsecond: u32) -> Result<Self, ParseError> {
Time::from_timestamp_with_config(timestamp_second, timestamp_microsecond, &TimeConfig::default())
Time::from_timestamp_with_config(
timestamp_second,
timestamp_microsecond,
&TimeConfigBuilder::new().build(),
)
}

/// Like `from_timestamp` but with a `TimeConfig`
Expand All @@ -253,9 +257,9 @@ impl Time {
/// # Examples
///
/// ```
/// use speedate::{Time, TimeConfig};
/// use speedate::{Time, TimeConfigBuilder};
///
/// let d = Time::from_timestamp_with_config(3740, 123, &TimeConfig::default()).unwrap();
/// let d = Time::from_timestamp_with_config(3740, 123, &TimeConfigBuilder::new().build()).unwrap();
/// assert_eq!(d.to_string(), "01:02:20.000123");
/// ```
pub fn from_timestamp_with_config(
Expand Down Expand Up @@ -555,7 +559,7 @@ impl PureTime {
}
}

#[derive(Debug, Clone, Default, Copy)]
#[derive(Debug, Clone, Default, Copy, PartialEq)]
pub enum MicrosecondsPrecisionOverflowBehavior {
Truncate,
#[default]
Expand All @@ -573,8 +577,43 @@ impl TryFrom<&str> for MicrosecondsPrecisionOverflowBehavior {
}
}

#[derive(Debug, Clone, Default)]
#[derive(Debug, Clone, Default, PartialEq)]
pub struct TimeConfig {
pub microseconds_precision_overflow_behavior: MicrosecondsPrecisionOverflowBehavior,
pub unix_timestamp_offset: Option<i32>,
}

impl TimeConfig {
pub fn builder() -> TimeConfigBuilder {
TimeConfigBuilder::new()
}
}

#[derive(Debug, Clone, Default)]
pub struct TimeConfigBuilder {
microseconds_precision_overflow_behavior: Option<MicrosecondsPrecisionOverflowBehavior>,
unix_timestamp_offset: Option<i32>,
}

impl TimeConfigBuilder {
pub fn new() -> Self {
Self::default()
}
pub fn microseconds_precision_overflow_behavior(
mut self,
microseconds_precision_overflow_behavior: MicrosecondsPrecisionOverflowBehavior,
) -> Self {
self.microseconds_precision_overflow_behavior = Some(microseconds_precision_overflow_behavior);
self
}
pub fn unix_timestamp_offset(mut self, unix_timestamp_offset: Option<i32>) -> Self {
self.unix_timestamp_offset = unix_timestamp_offset;
self
}
pub fn build(self) -> TimeConfig {
TimeConfig {
microseconds_precision_overflow_behavior: self.microseconds_precision_overflow_behavior.unwrap_or_default(),
unix_timestamp_offset: self.unix_timestamp_offset,
}
}
}
Loading