Skip to content

Commit 6fd0444

Browse files
authored
Merge pull request #1164 from allan2/jiff
Add Jiff support
2 parents 2e6b7df + bc9102c commit 6fd0444

File tree

11 files changed

+344
-0
lines changed

11 files changed

+344
-0
lines changed

postgres-types/CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22

33
## Unreleased
44

5+
### Added
6+
7+
* Added support for `jiff` 0.1 via the `with-jiff-01` feature.
8+
59
## v0.2.7 - 2024-07-21
610

711
### Added

postgres-types/Cargo.toml

+2
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ with-eui48-0_4 = ["eui48-04"]
2121
with-eui48-1 = ["eui48-1"]
2222
with-geo-types-0_6 = ["geo-types-06"]
2323
with-geo-types-0_7 = ["geo-types-0_7"]
24+
with-jiff-0_1 = ["jiff-01"]
2425
with-serde_json-1 = ["serde-1", "serde_json-1"]
2526
with-smol_str-01 = ["smol_str-01"]
2627
with-uuid-0_8 = ["uuid-08"]
@@ -46,6 +47,7 @@ eui48-04 = { version = "0.4", package = "eui48", optional = true }
4647
eui48-1 = { version = "1.0", package = "eui48", optional = true, default-features = false }
4748
geo-types-06 = { version = "0.6", package = "geo-types", optional = true }
4849
geo-types-0_7 = { version = "0.7", package = "geo-types", optional = true }
50+
jiff-01 = { version = "0.1", package = "jiff", optional = true }
4951
serde-1 = { version = "1.0", package = "serde", optional = true }
5052
serde_json-1 = { version = "1.0", package = "serde_json", optional = true }
5153
uuid-08 = { version = "0.8", package = "uuid", optional = true }

postgres-types/src/jiff_01.rs

+141
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
use bytes::BytesMut;
2+
use jiff_01::{
3+
civil::{Date, DateTime, Time},
4+
Span, SpanRound, Timestamp, Unit,
5+
};
6+
use postgres_protocol::types;
7+
use std::error::Error;
8+
9+
use crate::{FromSql, IsNull, ToSql, Type};
10+
11+
const fn base() -> DateTime {
12+
DateTime::constant(2000, 1, 1, 0, 0, 0, 0)
13+
}
14+
15+
/// The number of seconds from the Unix epoch to 2000-01-01 00:00:00 UTC.
16+
const PG_EPOCH: i64 = 946684800;
17+
18+
fn base_ts() -> Timestamp {
19+
Timestamp::new(PG_EPOCH, 0).unwrap()
20+
}
21+
22+
fn round_us<'a>() -> SpanRound<'a> {
23+
SpanRound::new().largest(Unit::Microsecond)
24+
}
25+
26+
fn decode_err<E>(_e: E) -> Box<dyn Error + Sync + Send>
27+
where
28+
E: Error,
29+
{
30+
"value too large to decode".into()
31+
}
32+
33+
fn transmit_err<E>(_e: E) -> Box<dyn Error + Sync + Send>
34+
where
35+
E: Error,
36+
{
37+
"value too large to transmit".into()
38+
}
39+
40+
impl<'a> FromSql<'a> for DateTime {
41+
fn from_sql(_: &Type, raw: &[u8]) -> Result<DateTime, Box<dyn Error + Sync + Send>> {
42+
let v = types::timestamp_from_sql(raw)?;
43+
Span::new()
44+
.try_microseconds(v)
45+
.and_then(|s| base().checked_add(s))
46+
.map_err(decode_err)
47+
}
48+
49+
accepts!(TIMESTAMP);
50+
}
51+
52+
impl ToSql for DateTime {
53+
fn to_sql(&self, _: &Type, w: &mut BytesMut) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
54+
let v = self
55+
.since(base())
56+
.and_then(|s| s.round(round_us()))
57+
.map_err(transmit_err)?
58+
.get_microseconds();
59+
types::timestamp_to_sql(v, w);
60+
Ok(IsNull::No)
61+
}
62+
63+
accepts!(TIMESTAMP);
64+
to_sql_checked!();
65+
}
66+
67+
impl<'a> FromSql<'a> for Timestamp {
68+
fn from_sql(_: &Type, raw: &[u8]) -> Result<Timestamp, Box<dyn Error + Sync + Send>> {
69+
let v = types::timestamp_from_sql(raw)?;
70+
Span::new()
71+
.try_microseconds(v)
72+
.and_then(|s| base_ts().checked_add(s))
73+
.map_err(decode_err)
74+
}
75+
76+
accepts!(TIMESTAMPTZ);
77+
}
78+
79+
impl ToSql for Timestamp {
80+
fn to_sql(&self, _: &Type, w: &mut BytesMut) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
81+
let v = self
82+
.since(base_ts())
83+
.and_then(|s| s.round(round_us()))
84+
.map_err(transmit_err)?
85+
.get_microseconds();
86+
types::timestamp_to_sql(v, w);
87+
Ok(IsNull::No)
88+
}
89+
90+
accepts!(TIMESTAMPTZ);
91+
to_sql_checked!();
92+
}
93+
94+
impl<'a> FromSql<'a> for Date {
95+
fn from_sql(_: &Type, raw: &[u8]) -> Result<Date, Box<dyn Error + Sync + Send>> {
96+
let v = types::date_from_sql(raw)?;
97+
Span::new()
98+
.try_days(v)
99+
.and_then(|s| base().date().checked_add(s))
100+
.map_err(decode_err)
101+
}
102+
accepts!(DATE);
103+
}
104+
105+
impl ToSql for Date {
106+
fn to_sql(&self, _: &Type, w: &mut BytesMut) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
107+
let v = self.since(base().date()).map_err(transmit_err)?.get_days();
108+
types::date_to_sql(v, w);
109+
Ok(IsNull::No)
110+
}
111+
112+
accepts!(DATE);
113+
to_sql_checked!();
114+
}
115+
116+
impl<'a> FromSql<'a> for Time {
117+
fn from_sql(_: &Type, raw: &[u8]) -> Result<Time, Box<dyn Error + Sync + Send>> {
118+
let v = types::time_from_sql(raw)?;
119+
Span::new()
120+
.try_microseconds(v)
121+
.and_then(|s| Time::midnight().checked_add(s))
122+
.map_err(decode_err)
123+
}
124+
125+
accepts!(TIME);
126+
}
127+
128+
impl ToSql for Time {
129+
fn to_sql(&self, _: &Type, w: &mut BytesMut) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
130+
let v = self
131+
.since(Time::midnight())
132+
.and_then(|s| s.round(round_us()))
133+
.map_err(transmit_err)?
134+
.get_microseconds();
135+
types::time_to_sql(v, w);
136+
Ok(IsNull::No)
137+
}
138+
139+
accepts!(TIME);
140+
to_sql_checked!();
141+
}

postgres-types/src/lib.rs

+6
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,8 @@ mod eui48_1;
276276
mod geo_types_06;
277277
#[cfg(feature = "with-geo-types-0_7")]
278278
mod geo_types_07;
279+
#[cfg(feature = "with-jiff-0_1")]
280+
mod jiff_01;
279281
#[cfg(feature = "with-serde_json-1")]
280282
mod serde_json_1;
281283
#[cfg(feature = "with-smol_str-01")]
@@ -491,6 +493,10 @@ impl WrongType {
491493
/// | `time::OffsetDateTime` | TIMESTAMP WITH TIME ZONE |
492494
/// | `time::Date` | DATE |
493495
/// | `time::Time` | TIME |
496+
/// | `jiff::civil::Date` | DATE |
497+
/// | `jiff::civil::DateTime` | TIMESTAMP |
498+
/// | `jiff::civil::Time` | TIME |
499+
/// | `jiff::Timestamp` | TIMESTAMP WITH TIME ZONE |
494500
/// | `eui48::MacAddress` | MACADDR |
495501
/// | `geo_types::Point<f64>` | POINT |
496502
/// | `geo_types::Rect<f64>` | BOX |

postgres/CHANGELOG.md

+6
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# Change Log
22

3+
## Unreleased
4+
5+
### Added
6+
7+
* Added support for `jiff` 0.1 via the `with-jiff-01` feature.
8+
39
## v0.19.8 - 2024-07-21
410

511
### Added

postgres/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ with-eui48-0_4 = ["tokio-postgres/with-eui48-0_4"]
2828
with-eui48-1 = ["tokio-postgres/with-eui48-1"]
2929
with-geo-types-0_6 = ["tokio-postgres/with-geo-types-0_6"]
3030
with-geo-types-0_7 = ["tokio-postgres/with-geo-types-0_7"]
31+
with-jiff-0_1 = ["tokio-postgres/with-jiff-0_1"]
3132
with-serde_json-1 = ["tokio-postgres/with-serde_json-1"]
3233
with-smol_str-01 = ["tokio-postgres/with-smol_str-01"]
3334
with-uuid-0_8 = ["tokio-postgres/with-uuid-0_8"]

tokio-postgres/CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22

33
## Unreleased
44

5+
### Added
6+
7+
* Added support for `jiff` 0.1 via the `with-jiff-01` feature.
8+
59
## v0.7.11 - 2024-07-21
610

711
### Fixed

tokio-postgres/Cargo.toml

+2
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ with-eui48-0_4 = ["postgres-types/with-eui48-0_4"]
3434
with-eui48-1 = ["postgres-types/with-eui48-1"]
3535
with-geo-types-0_6 = ["postgres-types/with-geo-types-0_6"]
3636
with-geo-types-0_7 = ["postgres-types/with-geo-types-0_7"]
37+
with-jiff-0_1 = ["postgres-types/with-jiff-0_1"]
3738
with-serde_json-1 = ["postgres-types/with-serde_json-1"]
3839
with-smol_str-01 = ["postgres-types/with-smol_str-01"]
3940
with-uuid-0_8 = ["postgres-types/with-uuid-0_8"]
@@ -81,6 +82,7 @@ chrono-04 = { version = "0.4", package = "chrono", default-features = false }
8182
eui48-1 = { version = "1.0", package = "eui48", default-features = false }
8283
geo-types-06 = { version = "0.6", package = "geo-types" }
8384
geo-types-07 = { version = "0.7", package = "geo-types" }
85+
jiff-01 = { version = "0.1", package = "jiff" }
8486
serde-1 = { version = "1.0", package = "serde" }
8587
serde_json-1 = { version = "1.0", package = "serde_json" }
8688
smol_str-01 = { version = "0.1", package = "smol_str" }

tokio-postgres/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@
111111
//! | `with-eui48-1` | Enable support for the 1.0 version of the `eui48` crate. | [eui48](https://crates.io/crates/eui48) 1.0 | no |
112112
//! | `with-geo-types-0_6` | Enable support for the 0.6 version of the `geo-types` crate. | [geo-types](https://crates.io/crates/geo-types/0.6.0) 0.6 | no |
113113
//! | `with-geo-types-0_7` | Enable support for the 0.7 version of the `geo-types` crate. | [geo-types](https://crates.io/crates/geo-types/0.7.0) 0.7 | no |
114+
//! | `with-jiff-0_1` | Enable support for the 0.1 version of the `jiff` crate. | [jiff](https://crates.io/crates/jiff/0.1.0) 0.1 | no |
114115
//! | `with-serde_json-1` | Enable support for the `serde_json` crate. | [serde_json](https://crates.io/crates/serde_json) 1.0 | no |
115116
//! | `with-uuid-0_8` | Enable support for the `uuid` crate. | [uuid](https://crates.io/crates/uuid) 0.8 | no |
116117
//! | `with-uuid-1` | Enable support for the `uuid` crate. | [uuid](https://crates.io/crates/uuid) 1.0 | no |

0 commit comments

Comments
 (0)