Skip to main content

diesel/sqlite/types/date_and_time/
time.rs

1//! This module makes it possible to map `time` date and time values to sqlite `NUMERIC`
2//! fields. It is enabled with the `time` feature.
3
4extern crate time;
5
6use self::time::{
7    Date as NaiveDate, OffsetDateTime, PrimitiveDateTime, Time as NaiveTime, UtcOffset,
8    error::ComponentRange, macros::format_description,
9};
10// the non-deprecated variant does not exist in our minimal supported version
11#[allow(deprecated)]
12use self::time::format_description::FormatItem;
13
14use crate::backend::Backend;
15use crate::deserialize::{self, FromSql};
16use crate::serialize::{self, IsNull, Output, ToSql};
17use crate::sql_types::{Date, Time, Timestamp, TimestamptzSqlite};
18use crate::sqlite::Sqlite;
19
20/// Warning to future editors:
21/// Changes in the following formats need to be kept in sync
22/// with the formats of the ["chrono"](super::chrono) module.
23/// We need a distinction between whole second and subsecond
24/// since there is no format option to forgo the dot.
25/// We always print as many subsecond as his given to us,
26/// this means the subsecond part can be between 1 and 9 digits.
27// the non-deprecated variant does not exist in our minimal supported version
28#[allow(deprecated)]
29const DATE_FORMAT: &[FormatItem<'_>] = const {
        use ::time::format_description::{*, modifier::*};
        &[BorrowedFormatItem::Component {
                            0: Component::Year(Year::default()),
                        }, BorrowedFormatItem::Literal(b"-"),
                        BorrowedFormatItem::Component {
                            0: Component::Month(Month::default()),
                        }, BorrowedFormatItem::Literal(b"-"),
                        BorrowedFormatItem::Component {
                            0: Component::Day(Day::default()),
                        }] as StaticFormatDescription
    }format_description!("[year]-[month]-[day]");
30
31// the non-deprecated variant does not exist in our minimal supported version
32#[allow(deprecated)]
33const ENCODE_TIME_FORMAT_WHOLE_SECOND: &[FormatItem<'_>] =
34    const {
        use ::time::format_description::{*, modifier::*};
        &[BorrowedFormatItem::Component {
                            0: Component::Hour(Hour::default()),
                        }, BorrowedFormatItem::Literal(b":"),
                        BorrowedFormatItem::Component {
                            0: Component::Minute(Minute::default()),
                        }, BorrowedFormatItem::Literal(b":"),
                        BorrowedFormatItem::Component {
                            0: Component::Second(Second::default()),
                        }] as StaticFormatDescription
    }format_description!("[hour]:[minute]:[second]");
35
36// the non-deprecated variant does not exist in our minimal supported version
37#[allow(deprecated)]
38const ENCODE_TIME_FORMAT_SUBSECOND: &[FormatItem<'_>] =
39    const {
        use ::time::format_description::{*, modifier::*};
        &[BorrowedFormatItem::Component {
                            0: Component::Hour(Hour::default()),
                        }, BorrowedFormatItem::Literal(b":"),
                        BorrowedFormatItem::Component {
                            0: Component::Minute(Minute::default()),
                        }, BorrowedFormatItem::Literal(b":"),
                        BorrowedFormatItem::Component {
                            0: Component::Second(Second::default()),
                        }, BorrowedFormatItem::Literal(b"."),
                        BorrowedFormatItem::Component {
                            0: Component::Subsecond(Subsecond::default()),
                        }] as StaticFormatDescription
    }format_description!("[hour]:[minute]:[second].[subsecond]");
40
41// the non-deprecated variant does not exist in our minimal supported version
42#[allow(deprecated)]
43const TIME_FORMATS: [&[FormatItem<'_>]; 9] = [
44    // Most likely formats
45    const {
        use ::time::format_description::{*, modifier::*};
        &[BorrowedFormatItem::Component {
                            0: Component::Hour(Hour::default()),
                        }, BorrowedFormatItem::Literal(b":"),
                        BorrowedFormatItem::Component {
                            0: Component::Minute(Minute::default()),
                        }, BorrowedFormatItem::Literal(b":"),
                        BorrowedFormatItem::Component {
                            0: Component::Second(Second::default()),
                        }, BorrowedFormatItem::Literal(b"."),
                        BorrowedFormatItem::Component {
                            0: Component::Subsecond(Subsecond::default()),
                        }] as StaticFormatDescription
    }format_description!("[hour]:[minute]:[second].[subsecond]"),
46    const {
        use ::time::format_description::{*, modifier::*};
        &[BorrowedFormatItem::Component {
                            0: Component::Hour(Hour::default()),
                        }, BorrowedFormatItem::Literal(b":"),
                        BorrowedFormatItem::Component {
                            0: Component::Minute(Minute::default()),
                        }, BorrowedFormatItem::Literal(b":"),
                        BorrowedFormatItem::Component {
                            0: Component::Second(Second::default()),
                        }] as StaticFormatDescription
    }format_description!("[hour]:[minute]:[second]"),
47    // All other valid formats in order of increasing specificity
48    const {
        use ::time::format_description::{*, modifier::*};
        &[BorrowedFormatItem::Component {
                            0: Component::Hour(Hour::default()),
                        }, BorrowedFormatItem::Literal(b":"),
                        BorrowedFormatItem::Component {
                            0: Component::Minute(Minute::default()),
                        }] as StaticFormatDescription
    }format_description!("[hour]:[minute]"),
49    const {
        use ::time::format_description::{*, modifier::*};
        &[BorrowedFormatItem::Component {
                            0: Component::Hour(Hour::default()),
                        }, BorrowedFormatItem::Literal(b":"),
                        BorrowedFormatItem::Component {
                            0: Component::Minute(Minute::default()),
                        }, BorrowedFormatItem::Literal(b"Z")] as
            StaticFormatDescription
    }format_description!("[hour]:[minute]Z"),
50    const {
        use ::time::format_description::{*, modifier::*};
        &[BorrowedFormatItem::Component {
                            0: Component::Hour(Hour::default()),
                        }, BorrowedFormatItem::Literal(b":"),
                        BorrowedFormatItem::Component {
                            0: Component::Minute(Minute::default()),
                        },
                        BorrowedFormatItem::Component {
                            0: Component::OffsetHour({
                                    OffsetHour::default().with_sign_is_mandatory(true)
                                }),
                        }, BorrowedFormatItem::Literal(b":"),
                        BorrowedFormatItem::Component {
                            0: Component::OffsetMinute(OffsetMinute::default()),
                        }] as StaticFormatDescription
    }format_description!("[hour]:[minute][offset_hour sign:mandatory]:[offset_minute]"),
51    const {
        use ::time::format_description::{*, modifier::*};
        &[BorrowedFormatItem::Component {
                            0: Component::Hour(Hour::default()),
                        }, BorrowedFormatItem::Literal(b":"),
                        BorrowedFormatItem::Component {
                            0: Component::Minute(Minute::default()),
                        }, BorrowedFormatItem::Literal(b":"),
                        BorrowedFormatItem::Component {
                            0: Component::Second(Second::default()),
                        }, BorrowedFormatItem::Literal(b"Z")] as
            StaticFormatDescription
    }format_description!("[hour]:[minute]:[second]Z"),
52    const {
        use ::time::format_description::{*, modifier::*};
        &[BorrowedFormatItem::Component {
                            0: Component::Hour(Hour::default()),
                        }, BorrowedFormatItem::Literal(b":"),
                        BorrowedFormatItem::Component {
                            0: Component::Minute(Minute::default()),
                        }, BorrowedFormatItem::Literal(b":"),
                        BorrowedFormatItem::Component {
                            0: Component::Second(Second::default()),
                        },
                        BorrowedFormatItem::Component {
                            0: Component::OffsetHour({
                                    OffsetHour::default().with_sign_is_mandatory(true)
                                }),
                        }, BorrowedFormatItem::Literal(b":"),
                        BorrowedFormatItem::Component {
                            0: Component::OffsetMinute(OffsetMinute::default()),
                        }] as StaticFormatDescription
    }format_description!("[hour]:[minute]:[second][offset_hour sign:mandatory]:[offset_minute]"),
53    const {
        use ::time::format_description::{*, modifier::*};
        &[BorrowedFormatItem::Component {
                            0: Component::Hour(Hour::default()),
                        }, BorrowedFormatItem::Literal(b":"),
                        BorrowedFormatItem::Component {
                            0: Component::Minute(Minute::default()),
                        }, BorrowedFormatItem::Literal(b":"),
                        BorrowedFormatItem::Component {
                            0: Component::Second(Second::default()),
                        }, BorrowedFormatItem::Literal(b"."),
                        BorrowedFormatItem::Component {
                            0: Component::Subsecond(Subsecond::default()),
                        }, BorrowedFormatItem::Literal(b"Z")] as
            StaticFormatDescription
    }format_description!("[hour]:[minute]:[second].[subsecond]Z"),
54    const {
        use ::time::format_description::{*, modifier::*};
        &[BorrowedFormatItem::Component {
                            0: Component::Hour(Hour::default()),
                        }, BorrowedFormatItem::Literal(b":"),
                        BorrowedFormatItem::Component {
                            0: Component::Minute(Minute::default()),
                        }, BorrowedFormatItem::Literal(b":"),
                        BorrowedFormatItem::Component {
                            0: Component::Second(Second::default()),
                        }, BorrowedFormatItem::Literal(b"."),
                        BorrowedFormatItem::Component {
                            0: Component::Subsecond(Subsecond::default()),
                        },
                        BorrowedFormatItem::Component {
                            0: Component::OffsetHour({
                                    OffsetHour::default().with_sign_is_mandatory(true)
                                }),
                        }, BorrowedFormatItem::Literal(b":"),
                        BorrowedFormatItem::Component {
                            0: Component::OffsetMinute(OffsetMinute::default()),
                        }] as StaticFormatDescription
    }format_description!(
55        "[hour]:[minute]:[second].[subsecond][offset_hour sign:mandatory]:[offset_minute]"
56    ),
57];
58
59// the non-deprecated variant does not exist in our minimal supported version
60#[allow(deprecated)]
61const ENCODE_PRIMITIVE_DATETIME_FORMAT_WHOLE_SECOND: &[FormatItem<'_>] =
62    const {
        use ::time::format_description::{*, modifier::*};
        &[BorrowedFormatItem::Component {
                            0: Component::Year(Year::default()),
                        }, BorrowedFormatItem::Literal(b"-"),
                        BorrowedFormatItem::Component {
                            0: Component::Month(Month::default()),
                        }, BorrowedFormatItem::Literal(b"-"),
                        BorrowedFormatItem::Component {
                            0: Component::Day(Day::default()),
                        }, BorrowedFormatItem::Literal(b" "),
                        BorrowedFormatItem::Component {
                            0: Component::Hour(Hour::default()),
                        }, BorrowedFormatItem::Literal(b":"),
                        BorrowedFormatItem::Component {
                            0: Component::Minute(Minute::default()),
                        }, BorrowedFormatItem::Literal(b":"),
                        BorrowedFormatItem::Component {
                            0: Component::Second(Second::default()),
                        }] as StaticFormatDescription
    }format_description!("[year]-[month]-[day] [hour]:[minute]:[second]");
63
64// the non-deprecated variant does not exist in our minimal supported version
65#[allow(deprecated)]
66const ENCODE_PRIMITIVE_DATETIME_FORMAT_SUBSECOND: &[FormatItem<'_>] =
67    const {
        use ::time::format_description::{*, modifier::*};
        &[BorrowedFormatItem::Component {
                            0: Component::Year(Year::default()),
                        }, BorrowedFormatItem::Literal(b"-"),
                        BorrowedFormatItem::Component {
                            0: Component::Month(Month::default()),
                        }, BorrowedFormatItem::Literal(b"-"),
                        BorrowedFormatItem::Component {
                            0: Component::Day(Day::default()),
                        }, BorrowedFormatItem::Literal(b" "),
                        BorrowedFormatItem::Component {
                            0: Component::Hour(Hour::default()),
                        }, BorrowedFormatItem::Literal(b":"),
                        BorrowedFormatItem::Component {
                            0: Component::Minute(Minute::default()),
                        }, BorrowedFormatItem::Literal(b":"),
                        BorrowedFormatItem::Component {
                            0: Component::Second(Second::default()),
                        }, BorrowedFormatItem::Literal(b"."),
                        BorrowedFormatItem::Component {
                            0: Component::Subsecond(Subsecond::default()),
                        }] as StaticFormatDescription
    }format_description!("[year]-[month]-[day] [hour]:[minute]:[second].[subsecond]");
68
69// the non-deprecated variant does not exist in our minimal supported version
70#[allow(deprecated)]
71const ENCODE_DATETIME_FORMAT_WHOLE_SECOND: &[FormatItem<'_>] = const {
        use ::time::format_description::{*, modifier::*};
        &[BorrowedFormatItem::Component {
                            0: Component::Year(Year::default()),
                        }, BorrowedFormatItem::Literal(b"-"),
                        BorrowedFormatItem::Component {
                            0: Component::Month(Month::default()),
                        }, BorrowedFormatItem::Literal(b"-"),
                        BorrowedFormatItem::Component {
                            0: Component::Day(Day::default()),
                        }, BorrowedFormatItem::Literal(b" "),
                        BorrowedFormatItem::Component {
                            0: Component::Hour(Hour::default()),
                        }, BorrowedFormatItem::Literal(b":"),
                        BorrowedFormatItem::Component {
                            0: Component::Minute(Minute::default()),
                        }, BorrowedFormatItem::Literal(b":"),
                        BorrowedFormatItem::Component {
                            0: Component::Second(Second::default()),
                        },
                        BorrowedFormatItem::Component {
                            0: Component::OffsetHour({
                                    OffsetHour::default().with_sign_is_mandatory(true)
                                }),
                        }, BorrowedFormatItem::Literal(b":"),
                        BorrowedFormatItem::Component {
                            0: Component::OffsetMinute(OffsetMinute::default()),
                        }] as StaticFormatDescription
    }format_description!(
72    "[year]-[month]-[day] [hour]:[minute]:[second][offset_hour sign:mandatory]:[offset_minute]"
73);
74
75// the non-deprecated variant does not exist in our minimal supported version
76#[allow(deprecated)]
77const ENCODE_DATETIME_FORMAT_SUBSECOND: &[FormatItem<'_>] = const {
        use ::time::format_description::{*, modifier::*};
        &[BorrowedFormatItem::Component {
                            0: Component::Year(Year::default()),
                        }, BorrowedFormatItem::Literal(b"-"),
                        BorrowedFormatItem::Component {
                            0: Component::Month(Month::default()),
                        }, BorrowedFormatItem::Literal(b"-"),
                        BorrowedFormatItem::Component {
                            0: Component::Day(Day::default()),
                        }, BorrowedFormatItem::Literal(b" "),
                        BorrowedFormatItem::Component {
                            0: Component::Hour(Hour::default()),
                        }, BorrowedFormatItem::Literal(b":"),
                        BorrowedFormatItem::Component {
                            0: Component::Minute(Minute::default()),
                        }, BorrowedFormatItem::Literal(b":"),
                        BorrowedFormatItem::Component {
                            0: Component::Second(Second::default()),
                        }, BorrowedFormatItem::Literal(b"."),
                        BorrowedFormatItem::Component {
                            0: Component::Subsecond(Subsecond::default()),
                        },
                        BorrowedFormatItem::Component {
                            0: Component::OffsetHour({
                                    OffsetHour::default().with_sign_is_mandatory(true)
                                }),
                        }, BorrowedFormatItem::Literal(b":"),
                        BorrowedFormatItem::Component {
                            0: Component::OffsetMinute(OffsetMinute::default()),
                        }] as StaticFormatDescription
    }format_description!(
78    "[year]-[month]-[day] [hour]:[minute]:[second].[subsecond][offset_hour sign:mandatory]:[offset_minute]"
79);
80
81// the non-deprecated variant does not exist in our minimal supported version
82#[allow(deprecated)]
83const PRIMITIVE_DATETIME_FORMATS: [&[FormatItem<'_>]; 18] = [
84    // Most likely formats
85    const {
        use ::time::format_description::{*, modifier::*};
        &[BorrowedFormatItem::Component {
                            0: Component::Year(Year::default()),
                        }, BorrowedFormatItem::Literal(b"-"),
                        BorrowedFormatItem::Component {
                            0: Component::Month(Month::default()),
                        }, BorrowedFormatItem::Literal(b"-"),
                        BorrowedFormatItem::Component {
                            0: Component::Day(Day::default()),
                        }, BorrowedFormatItem::Literal(b" "),
                        BorrowedFormatItem::Component {
                            0: Component::Hour(Hour::default()),
                        }, BorrowedFormatItem::Literal(b":"),
                        BorrowedFormatItem::Component {
                            0: Component::Minute(Minute::default()),
                        }, BorrowedFormatItem::Literal(b":"),
                        BorrowedFormatItem::Component {
                            0: Component::Second(Second::default()),
                        }, BorrowedFormatItem::Literal(b"."),
                        BorrowedFormatItem::Component {
                            0: Component::Subsecond(Subsecond::default()),
                        }] as StaticFormatDescription
    }format_description!("[year]-[month]-[day] [hour]:[minute]:[second].[subsecond]"),
86    const {
        use ::time::format_description::{*, modifier::*};
        &[BorrowedFormatItem::Component {
                            0: Component::Year(Year::default()),
                        }, BorrowedFormatItem::Literal(b"-"),
                        BorrowedFormatItem::Component {
                            0: Component::Month(Month::default()),
                        }, BorrowedFormatItem::Literal(b"-"),
                        BorrowedFormatItem::Component {
                            0: Component::Day(Day::default()),
                        }, BorrowedFormatItem::Literal(b" "),
                        BorrowedFormatItem::Component {
                            0: Component::Hour(Hour::default()),
                        }, BorrowedFormatItem::Literal(b":"),
                        BorrowedFormatItem::Component {
                            0: Component::Minute(Minute::default()),
                        }, BorrowedFormatItem::Literal(b":"),
                        BorrowedFormatItem::Component {
                            0: Component::Second(Second::default()),
                        }, BorrowedFormatItem::Literal(b"."),
                        BorrowedFormatItem::Component {
                            0: Component::Subsecond(Subsecond::default()),
                        },
                        BorrowedFormatItem::Component {
                            0: Component::OffsetHour({
                                    OffsetHour::default().with_sign_is_mandatory(true)
                                }),
                        }, BorrowedFormatItem::Literal(b":"),
                        BorrowedFormatItem::Component {
                            0: Component::OffsetMinute(OffsetMinute::default()),
                        }] as StaticFormatDescription
    }format_description!(
87        "[year]-[month]-[day] [hour]:[minute]:[second].[subsecond][offset_hour sign:mandatory]:[offset_minute]"
88    ),
89    const {
        use ::time::format_description::{*, modifier::*};
        &[BorrowedFormatItem::Component {
                            0: Component::Year(Year::default()),
                        }, BorrowedFormatItem::Literal(b"-"),
                        BorrowedFormatItem::Component {
                            0: Component::Month(Month::default()),
                        }, BorrowedFormatItem::Literal(b"-"),
                        BorrowedFormatItem::Component {
                            0: Component::Day(Day::default()),
                        }, BorrowedFormatItem::Literal(b" "),
                        BorrowedFormatItem::Component {
                            0: Component::Hour(Hour::default()),
                        }, BorrowedFormatItem::Literal(b":"),
                        BorrowedFormatItem::Component {
                            0: Component::Minute(Minute::default()),
                        }, BorrowedFormatItem::Literal(b":"),
                        BorrowedFormatItem::Component {
                            0: Component::Second(Second::default()),
                        }] as StaticFormatDescription
    }format_description!("[year]-[month]-[day] [hour]:[minute]:[second]"),
90    const {
        use ::time::format_description::{*, modifier::*};
        &[BorrowedFormatItem::Component {
                            0: Component::Year(Year::default()),
                        }, BorrowedFormatItem::Literal(b"-"),
                        BorrowedFormatItem::Component {
                            0: Component::Month(Month::default()),
                        }, BorrowedFormatItem::Literal(b"-"),
                        BorrowedFormatItem::Component {
                            0: Component::Day(Day::default()),
                        }, BorrowedFormatItem::Literal(b" "),
                        BorrowedFormatItem::Component {
                            0: Component::Hour(Hour::default()),
                        }, BorrowedFormatItem::Literal(b":"),
                        BorrowedFormatItem::Component {
                            0: Component::Minute(Minute::default()),
                        }, BorrowedFormatItem::Literal(b":"),
                        BorrowedFormatItem::Component {
                            0: Component::Second(Second::default()),
                        },
                        BorrowedFormatItem::Component {
                            0: Component::OffsetHour({
                                    OffsetHour::default().with_sign_is_mandatory(true)
                                }),
                        }, BorrowedFormatItem::Literal(b":"),
                        BorrowedFormatItem::Component {
                            0: Component::OffsetMinute(OffsetMinute::default()),
                        }] as StaticFormatDescription
    }format_description!(
91        "[year]-[month]-[day] [hour]:[minute]:[second][offset_hour sign:mandatory]:[offset_minute]"
92    ),
93    // All other formats in order of increasing specificity
94    const {
        use ::time::format_description::{*, modifier::*};
        &[BorrowedFormatItem::Component {
                            0: Component::Year(Year::default()),
                        }, BorrowedFormatItem::Literal(b"-"),
                        BorrowedFormatItem::Component {
                            0: Component::Month(Month::default()),
                        }, BorrowedFormatItem::Literal(b"-"),
                        BorrowedFormatItem::Component {
                            0: Component::Day(Day::default()),
                        }, BorrowedFormatItem::Literal(b" "),
                        BorrowedFormatItem::Component {
                            0: Component::Hour(Hour::default()),
                        }, BorrowedFormatItem::Literal(b":"),
                        BorrowedFormatItem::Component {
                            0: Component::Minute(Minute::default()),
                        }] as StaticFormatDescription
    }format_description!("[year]-[month]-[day] [hour]:[minute]"),
95    const {
        use ::time::format_description::{*, modifier::*};
        &[BorrowedFormatItem::Component {
                            0: Component::Year(Year::default()),
                        }, BorrowedFormatItem::Literal(b"-"),
                        BorrowedFormatItem::Component {
                            0: Component::Month(Month::default()),
                        }, BorrowedFormatItem::Literal(b"-"),
                        BorrowedFormatItem::Component {
                            0: Component::Day(Day::default()),
                        }, BorrowedFormatItem::Literal(b" "),
                        BorrowedFormatItem::Component {
                            0: Component::Hour(Hour::default()),
                        }, BorrowedFormatItem::Literal(b":"),
                        BorrowedFormatItem::Component {
                            0: Component::Minute(Minute::default()),
                        }, BorrowedFormatItem::Literal(b"Z")] as
            StaticFormatDescription
    }format_description!("[year]-[month]-[day] [hour]:[minute]Z"),
96    const {
        use ::time::format_description::{*, modifier::*};
        &[BorrowedFormatItem::Component {
                            0: Component::Year(Year::default()),
                        }, BorrowedFormatItem::Literal(b"-"),
                        BorrowedFormatItem::Component {
                            0: Component::Month(Month::default()),
                        }, BorrowedFormatItem::Literal(b"-"),
                        BorrowedFormatItem::Component {
                            0: Component::Day(Day::default()),
                        }, BorrowedFormatItem::Literal(b" "),
                        BorrowedFormatItem::Component {
                            0: Component::Hour(Hour::default()),
                        }, BorrowedFormatItem::Literal(b":"),
                        BorrowedFormatItem::Component {
                            0: Component::Minute(Minute::default()),
                        },
                        BorrowedFormatItem::Component {
                            0: Component::OffsetHour({
                                    OffsetHour::default().with_sign_is_mandatory(true)
                                }),
                        }, BorrowedFormatItem::Literal(b":"),
                        BorrowedFormatItem::Component {
                            0: Component::OffsetMinute(OffsetMinute::default()),
                        }] as StaticFormatDescription
    }format_description!(
97        "[year]-[month]-[day] [hour]:[minute][offset_hour sign:mandatory]:[offset_minute]"
98    ),
99    const {
        use ::time::format_description::{*, modifier::*};
        &[BorrowedFormatItem::Component {
                            0: Component::Year(Year::default()),
                        }, BorrowedFormatItem::Literal(b"-"),
                        BorrowedFormatItem::Component {
                            0: Component::Month(Month::default()),
                        }, BorrowedFormatItem::Literal(b"-"),
                        BorrowedFormatItem::Component {
                            0: Component::Day(Day::default()),
                        }, BorrowedFormatItem::Literal(b" "),
                        BorrowedFormatItem::Component {
                            0: Component::Hour(Hour::default()),
                        }, BorrowedFormatItem::Literal(b":"),
                        BorrowedFormatItem::Component {
                            0: Component::Minute(Minute::default()),
                        }, BorrowedFormatItem::Literal(b":"),
                        BorrowedFormatItem::Component {
                            0: Component::Second(Second::default()),
                        }, BorrowedFormatItem::Literal(b"Z")] as
            StaticFormatDescription
    }format_description!("[year]-[month]-[day] [hour]:[minute]:[second]Z"),
100    const {
        use ::time::format_description::{*, modifier::*};
        &[BorrowedFormatItem::Component {
                            0: Component::Year(Year::default()),
                        }, BorrowedFormatItem::Literal(b"-"),
                        BorrowedFormatItem::Component {
                            0: Component::Month(Month::default()),
                        }, BorrowedFormatItem::Literal(b"-"),
                        BorrowedFormatItem::Component {
                            0: Component::Day(Day::default()),
                        }, BorrowedFormatItem::Literal(b" "),
                        BorrowedFormatItem::Component {
                            0: Component::Hour(Hour::default()),
                        }, BorrowedFormatItem::Literal(b":"),
                        BorrowedFormatItem::Component {
                            0: Component::Minute(Minute::default()),
                        }, BorrowedFormatItem::Literal(b":"),
                        BorrowedFormatItem::Component {
                            0: Component::Second(Second::default()),
                        }, BorrowedFormatItem::Literal(b"."),
                        BorrowedFormatItem::Component {
                            0: Component::Subsecond(Subsecond::default()),
                        }, BorrowedFormatItem::Literal(b"Z")] as
            StaticFormatDescription
    }format_description!("[year]-[month]-[day] [hour]:[minute]:[second].[subsecond]Z"),
101    const {
        use ::time::format_description::{*, modifier::*};
        &[BorrowedFormatItem::Component {
                            0: Component::Year(Year::default()),
                        }, BorrowedFormatItem::Literal(b"-"),
                        BorrowedFormatItem::Component {
                            0: Component::Month(Month::default()),
                        }, BorrowedFormatItem::Literal(b"-"),
                        BorrowedFormatItem::Component {
                            0: Component::Day(Day::default()),
                        }, BorrowedFormatItem::Literal(b"T"),
                        BorrowedFormatItem::Component {
                            0: Component::Hour(Hour::default()),
                        }, BorrowedFormatItem::Literal(b":"),
                        BorrowedFormatItem::Component {
                            0: Component::Minute(Minute::default()),
                        }] as StaticFormatDescription
    }format_description!("[year]-[month]-[day]T[hour]:[minute]"),
102    const {
        use ::time::format_description::{*, modifier::*};
        &[BorrowedFormatItem::Component {
                            0: Component::Year(Year::default()),
                        }, BorrowedFormatItem::Literal(b"-"),
                        BorrowedFormatItem::Component {
                            0: Component::Month(Month::default()),
                        }, BorrowedFormatItem::Literal(b"-"),
                        BorrowedFormatItem::Component {
                            0: Component::Day(Day::default()),
                        }, BorrowedFormatItem::Literal(b"T"),
                        BorrowedFormatItem::Component {
                            0: Component::Hour(Hour::default()),
                        }, BorrowedFormatItem::Literal(b":"),
                        BorrowedFormatItem::Component {
                            0: Component::Minute(Minute::default()),
                        }, BorrowedFormatItem::Literal(b"Z")] as
            StaticFormatDescription
    }format_description!("[year]-[month]-[day]T[hour]:[minute]Z"),
103    const {
        use ::time::format_description::{*, modifier::*};
        &[BorrowedFormatItem::Component {
                            0: Component::Year(Year::default()),
                        }, BorrowedFormatItem::Literal(b"-"),
                        BorrowedFormatItem::Component {
                            0: Component::Month(Month::default()),
                        }, BorrowedFormatItem::Literal(b"-"),
                        BorrowedFormatItem::Component {
                            0: Component::Day(Day::default()),
                        }, BorrowedFormatItem::Literal(b"T"),
                        BorrowedFormatItem::Component {
                            0: Component::Hour(Hour::default()),
                        }, BorrowedFormatItem::Literal(b":"),
                        BorrowedFormatItem::Component {
                            0: Component::Minute(Minute::default()),
                        },
                        BorrowedFormatItem::Component {
                            0: Component::OffsetHour({
                                    OffsetHour::default().with_sign_is_mandatory(true)
                                }),
                        }, BorrowedFormatItem::Literal(b":"),
                        BorrowedFormatItem::Component {
                            0: Component::OffsetMinute(OffsetMinute::default()),
                        }] as StaticFormatDescription
    }format_description!(
104        "[year]-[month]-[day]T[hour]:[minute][offset_hour sign:mandatory]:[offset_minute]"
105    ),
106    const {
        use ::time::format_description::{*, modifier::*};
        &[BorrowedFormatItem::Component {
                            0: Component::Year(Year::default()),
                        }, BorrowedFormatItem::Literal(b"-"),
                        BorrowedFormatItem::Component {
                            0: Component::Month(Month::default()),
                        }, BorrowedFormatItem::Literal(b"-"),
                        BorrowedFormatItem::Component {
                            0: Component::Day(Day::default()),
                        }, BorrowedFormatItem::Literal(b"T"),
                        BorrowedFormatItem::Component {
                            0: Component::Hour(Hour::default()),
                        }, BorrowedFormatItem::Literal(b":"),
                        BorrowedFormatItem::Component {
                            0: Component::Minute(Minute::default()),
                        }, BorrowedFormatItem::Literal(b":"),
                        BorrowedFormatItem::Component {
                            0: Component::Second(Second::default()),
                        }] as StaticFormatDescription
    }format_description!("[year]-[month]-[day]T[hour]:[minute]:[second]"),
107    const {
        use ::time::format_description::{*, modifier::*};
        &[BorrowedFormatItem::Component {
                            0: Component::Year(Year::default()),
                        }, BorrowedFormatItem::Literal(b"-"),
                        BorrowedFormatItem::Component {
                            0: Component::Month(Month::default()),
                        }, BorrowedFormatItem::Literal(b"-"),
                        BorrowedFormatItem::Component {
                            0: Component::Day(Day::default()),
                        }, BorrowedFormatItem::Literal(b"T"),
                        BorrowedFormatItem::Component {
                            0: Component::Hour(Hour::default()),
                        }, BorrowedFormatItem::Literal(b":"),
                        BorrowedFormatItem::Component {
                            0: Component::Minute(Minute::default()),
                        }, BorrowedFormatItem::Literal(b":"),
                        BorrowedFormatItem::Component {
                            0: Component::Second(Second::default()),
                        }, BorrowedFormatItem::Literal(b"Z")] as
            StaticFormatDescription
    }format_description!("[year]-[month]-[day]T[hour]:[minute]:[second]Z"),
108    const {
        use ::time::format_description::{*, modifier::*};
        &[BorrowedFormatItem::Component {
                            0: Component::Year(Year::default()),
                        }, BorrowedFormatItem::Literal(b"-"),
                        BorrowedFormatItem::Component {
                            0: Component::Month(Month::default()),
                        }, BorrowedFormatItem::Literal(b"-"),
                        BorrowedFormatItem::Component {
                            0: Component::Day(Day::default()),
                        }, BorrowedFormatItem::Literal(b"T"),
                        BorrowedFormatItem::Component {
                            0: Component::Hour(Hour::default()),
                        }, BorrowedFormatItem::Literal(b":"),
                        BorrowedFormatItem::Component {
                            0: Component::Minute(Minute::default()),
                        }, BorrowedFormatItem::Literal(b":"),
                        BorrowedFormatItem::Component {
                            0: Component::Second(Second::default()),
                        },
                        BorrowedFormatItem::Component {
                            0: Component::OffsetHour({
                                    OffsetHour::default().with_sign_is_mandatory(true)
                                }),
                        }, BorrowedFormatItem::Literal(b":"),
                        BorrowedFormatItem::Component {
                            0: Component::OffsetMinute(OffsetMinute::default()),
                        }] as StaticFormatDescription
    }format_description!(
109        "[year]-[month]-[day]T[hour]:[minute]:[second][offset_hour sign:mandatory]:[offset_minute]"
110    ),
111    const {
        use ::time::format_description::{*, modifier::*};
        &[BorrowedFormatItem::Component {
                            0: Component::Year(Year::default()),
                        }, BorrowedFormatItem::Literal(b"-"),
                        BorrowedFormatItem::Component {
                            0: Component::Month(Month::default()),
                        }, BorrowedFormatItem::Literal(b"-"),
                        BorrowedFormatItem::Component {
                            0: Component::Day(Day::default()),
                        }, BorrowedFormatItem::Literal(b"T"),
                        BorrowedFormatItem::Component {
                            0: Component::Hour(Hour::default()),
                        }, BorrowedFormatItem::Literal(b":"),
                        BorrowedFormatItem::Component {
                            0: Component::Minute(Minute::default()),
                        }, BorrowedFormatItem::Literal(b":"),
                        BorrowedFormatItem::Component {
                            0: Component::Second(Second::default()),
                        }, BorrowedFormatItem::Literal(b"."),
                        BorrowedFormatItem::Component {
                            0: Component::Subsecond(Subsecond::default()),
                        }] as StaticFormatDescription
    }format_description!("[year]-[month]-[day]T[hour]:[minute]:[second].[subsecond]"),
112    const {
        use ::time::format_description::{*, modifier::*};
        &[BorrowedFormatItem::Component {
                            0: Component::Year(Year::default()),
                        }, BorrowedFormatItem::Literal(b"-"),
                        BorrowedFormatItem::Component {
                            0: Component::Month(Month::default()),
                        }, BorrowedFormatItem::Literal(b"-"),
                        BorrowedFormatItem::Component {
                            0: Component::Day(Day::default()),
                        }, BorrowedFormatItem::Literal(b"T"),
                        BorrowedFormatItem::Component {
                            0: Component::Hour(Hour::default()),
                        }, BorrowedFormatItem::Literal(b":"),
                        BorrowedFormatItem::Component {
                            0: Component::Minute(Minute::default()),
                        }, BorrowedFormatItem::Literal(b":"),
                        BorrowedFormatItem::Component {
                            0: Component::Second(Second::default()),
                        }, BorrowedFormatItem::Literal(b"."),
                        BorrowedFormatItem::Component {
                            0: Component::Subsecond(Subsecond::default()),
                        }, BorrowedFormatItem::Literal(b"Z")] as
            StaticFormatDescription
    }format_description!("[year]-[month]-[day]T[hour]:[minute]:[second].[subsecond]Z"),
113    const {
        use ::time::format_description::{*, modifier::*};
        &[BorrowedFormatItem::Component {
                            0: Component::Year(Year::default()),
                        }, BorrowedFormatItem::Literal(b"-"),
                        BorrowedFormatItem::Component {
                            0: Component::Month(Month::default()),
                        }, BorrowedFormatItem::Literal(b"-"),
                        BorrowedFormatItem::Component {
                            0: Component::Day(Day::default()),
                        }, BorrowedFormatItem::Literal(b"T"),
                        BorrowedFormatItem::Component {
                            0: Component::Hour(Hour::default()),
                        }, BorrowedFormatItem::Literal(b":"),
                        BorrowedFormatItem::Component {
                            0: Component::Minute(Minute::default()),
                        }, BorrowedFormatItem::Literal(b":"),
                        BorrowedFormatItem::Component {
                            0: Component::Second(Second::default()),
                        }, BorrowedFormatItem::Literal(b"."),
                        BorrowedFormatItem::Component {
                            0: Component::Subsecond(Subsecond::default()),
                        },
                        BorrowedFormatItem::Component {
                            0: Component::OffsetHour({
                                    OffsetHour::default().with_sign_is_mandatory(true)
                                }),
                        }, BorrowedFormatItem::Literal(b":"),
                        BorrowedFormatItem::Component {
                            0: Component::OffsetMinute(OffsetMinute::default()),
                        }] as StaticFormatDescription
    }format_description!(
114        "[year]-[month]-[day]T[hour]:[minute]:[second].[subsecond][offset_hour sign:mandatory]:[offset_minute]"
115    ),
116];
117
118// the non-deprecated variant does not exist in our minimal supported version
119#[allow(deprecated)]
120const DATETIME_FORMATS: [&[FormatItem<'_>]; 12] = [
121    // Most likely formats
122    const {
        use ::time::format_description::{*, modifier::*};
        &[BorrowedFormatItem::Component {
                            0: Component::Year(Year::default()),
                        }, BorrowedFormatItem::Literal(b"-"),
                        BorrowedFormatItem::Component {
                            0: Component::Month(Month::default()),
                        }, BorrowedFormatItem::Literal(b"-"),
                        BorrowedFormatItem::Component {
                            0: Component::Day(Day::default()),
                        }, BorrowedFormatItem::Literal(b" "),
                        BorrowedFormatItem::Component {
                            0: Component::Hour(Hour::default()),
                        }, BorrowedFormatItem::Literal(b":"),
                        BorrowedFormatItem::Component {
                            0: Component::Minute(Minute::default()),
                        }, BorrowedFormatItem::Literal(b":"),
                        BorrowedFormatItem::Component {
                            0: Component::Second(Second::default()),
                        }, BorrowedFormatItem::Literal(b"."),
                        BorrowedFormatItem::Component {
                            0: Component::Subsecond(Subsecond::default()),
                        },
                        BorrowedFormatItem::Component {
                            0: Component::OffsetHour({
                                    OffsetHour::default().with_sign_is_mandatory(true)
                                }),
                        }, BorrowedFormatItem::Literal(b":"),
                        BorrowedFormatItem::Component {
                            0: Component::OffsetMinute(OffsetMinute::default()),
                        }] as StaticFormatDescription
    }format_description!(
123        "[year]-[month]-[day] [hour]:[minute]:[second].[subsecond][offset_hour sign:mandatory]:[offset_minute]"
124    ),
125    const {
        use ::time::format_description::{*, modifier::*};
        &[BorrowedFormatItem::Component {
                            0: Component::Year(Year::default()),
                        }, BorrowedFormatItem::Literal(b"-"),
                        BorrowedFormatItem::Component {
                            0: Component::Month(Month::default()),
                        }, BorrowedFormatItem::Literal(b"-"),
                        BorrowedFormatItem::Component {
                            0: Component::Day(Day::default()),
                        }, BorrowedFormatItem::Literal(b" "),
                        BorrowedFormatItem::Component {
                            0: Component::Hour(Hour::default()),
                        }, BorrowedFormatItem::Literal(b":"),
                        BorrowedFormatItem::Component {
                            0: Component::Minute(Minute::default()),
                        }, BorrowedFormatItem::Literal(b":"),
                        BorrowedFormatItem::Component {
                            0: Component::Second(Second::default()),
                        },
                        BorrowedFormatItem::Component {
                            0: Component::OffsetHour({
                                    OffsetHour::default().with_sign_is_mandatory(true)
                                }),
                        }, BorrowedFormatItem::Literal(b":"),
                        BorrowedFormatItem::Component {
                            0: Component::OffsetMinute(OffsetMinute::default()),
                        }] as StaticFormatDescription
    }format_description!(
126        "[year]-[month]-[day] [hour]:[minute]:[second][offset_hour sign:mandatory]:[offset_minute]"
127    ),
128    // All other formats in order of increasing specificity
129    const {
        use ::time::format_description::{*, modifier::*};
        &[BorrowedFormatItem::Component {
                            0: Component::Year(Year::default()),
                        }, BorrowedFormatItem::Literal(b"-"),
                        BorrowedFormatItem::Component {
                            0: Component::Month(Month::default()),
                        }, BorrowedFormatItem::Literal(b"-"),
                        BorrowedFormatItem::Component {
                            0: Component::Day(Day::default()),
                        }, BorrowedFormatItem::Literal(b" "),
                        BorrowedFormatItem::Component {
                            0: Component::Hour(Hour::default()),
                        }, BorrowedFormatItem::Literal(b":"),
                        BorrowedFormatItem::Component {
                            0: Component::Minute(Minute::default()),
                        }, BorrowedFormatItem::Literal(b"Z")] as
            StaticFormatDescription
    }format_description!("[year]-[month]-[day] [hour]:[minute]Z"),
130    const {
        use ::time::format_description::{*, modifier::*};
        &[BorrowedFormatItem::Component {
                            0: Component::Year(Year::default()),
                        }, BorrowedFormatItem::Literal(b"-"),
                        BorrowedFormatItem::Component {
                            0: Component::Month(Month::default()),
                        }, BorrowedFormatItem::Literal(b"-"),
                        BorrowedFormatItem::Component {
                            0: Component::Day(Day::default()),
                        }, BorrowedFormatItem::Literal(b" "),
                        BorrowedFormatItem::Component {
                            0: Component::Hour(Hour::default()),
                        }, BorrowedFormatItem::Literal(b":"),
                        BorrowedFormatItem::Component {
                            0: Component::Minute(Minute::default()),
                        },
                        BorrowedFormatItem::Component {
                            0: Component::OffsetHour({
                                    OffsetHour::default().with_sign_is_mandatory(true)
                                }),
                        }, BorrowedFormatItem::Literal(b":"),
                        BorrowedFormatItem::Component {
                            0: Component::OffsetMinute(OffsetMinute::default()),
                        }] as StaticFormatDescription
    }format_description!(
131        "[year]-[month]-[day] [hour]:[minute][offset_hour sign:mandatory]:[offset_minute]"
132    ),
133    const {
        use ::time::format_description::{*, modifier::*};
        &[BorrowedFormatItem::Component {
                            0: Component::Year(Year::default()),
                        }, BorrowedFormatItem::Literal(b"-"),
                        BorrowedFormatItem::Component {
                            0: Component::Month(Month::default()),
                        }, BorrowedFormatItem::Literal(b"-"),
                        BorrowedFormatItem::Component {
                            0: Component::Day(Day::default()),
                        }, BorrowedFormatItem::Literal(b" "),
                        BorrowedFormatItem::Component {
                            0: Component::Hour(Hour::default()),
                        }, BorrowedFormatItem::Literal(b":"),
                        BorrowedFormatItem::Component {
                            0: Component::Minute(Minute::default()),
                        }, BorrowedFormatItem::Literal(b":"),
                        BorrowedFormatItem::Component {
                            0: Component::Second(Second::default()),
                        }, BorrowedFormatItem::Literal(b"Z")] as
            StaticFormatDescription
    }format_description!("[year]-[month]-[day] [hour]:[minute]:[second]Z"),
134    const {
        use ::time::format_description::{*, modifier::*};
        &[BorrowedFormatItem::Component {
                            0: Component::Year(Year::default()),
                        }, BorrowedFormatItem::Literal(b"-"),
                        BorrowedFormatItem::Component {
                            0: Component::Month(Month::default()),
                        }, BorrowedFormatItem::Literal(b"-"),
                        BorrowedFormatItem::Component {
                            0: Component::Day(Day::default()),
                        }, BorrowedFormatItem::Literal(b" "),
                        BorrowedFormatItem::Component {
                            0: Component::Hour(Hour::default()),
                        }, BorrowedFormatItem::Literal(b":"),
                        BorrowedFormatItem::Component {
                            0: Component::Minute(Minute::default()),
                        }, BorrowedFormatItem::Literal(b":"),
                        BorrowedFormatItem::Component {
                            0: Component::Second(Second::default()),
                        }, BorrowedFormatItem::Literal(b"."),
                        BorrowedFormatItem::Component {
                            0: Component::Subsecond(Subsecond::default()),
                        }, BorrowedFormatItem::Literal(b"Z")] as
            StaticFormatDescription
    }format_description!("[year]-[month]-[day] [hour]:[minute]:[second].[subsecond]Z"),
135    const {
        use ::time::format_description::{*, modifier::*};
        &[BorrowedFormatItem::Component {
                            0: Component::Year(Year::default()),
                        }, BorrowedFormatItem::Literal(b"-"),
                        BorrowedFormatItem::Component {
                            0: Component::Month(Month::default()),
                        }, BorrowedFormatItem::Literal(b"-"),
                        BorrowedFormatItem::Component {
                            0: Component::Day(Day::default()),
                        }, BorrowedFormatItem::Literal(b"T"),
                        BorrowedFormatItem::Component {
                            0: Component::Hour(Hour::default()),
                        }, BorrowedFormatItem::Literal(b":"),
                        BorrowedFormatItem::Component {
                            0: Component::Minute(Minute::default()),
                        }, BorrowedFormatItem::Literal(b"Z")] as
            StaticFormatDescription
    }format_description!("[year]-[month]-[day]T[hour]:[minute]Z"),
136    const {
        use ::time::format_description::{*, modifier::*};
        &[BorrowedFormatItem::Component {
                            0: Component::Year(Year::default()),
                        }, BorrowedFormatItem::Literal(b"-"),
                        BorrowedFormatItem::Component {
                            0: Component::Month(Month::default()),
                        }, BorrowedFormatItem::Literal(b"-"),
                        BorrowedFormatItem::Component {
                            0: Component::Day(Day::default()),
                        }, BorrowedFormatItem::Literal(b"T"),
                        BorrowedFormatItem::Component {
                            0: Component::Hour(Hour::default()),
                        }, BorrowedFormatItem::Literal(b":"),
                        BorrowedFormatItem::Component {
                            0: Component::Minute(Minute::default()),
                        },
                        BorrowedFormatItem::Component {
                            0: Component::OffsetHour({
                                    OffsetHour::default().with_sign_is_mandatory(true)
                                }),
                        }, BorrowedFormatItem::Literal(b":"),
                        BorrowedFormatItem::Component {
                            0: Component::OffsetMinute(OffsetMinute::default()),
                        }] as StaticFormatDescription
    }format_description!(
137        "[year]-[month]-[day]T[hour]:[minute][offset_hour sign:mandatory]:[offset_minute]"
138    ),
139    const {
        use ::time::format_description::{*, modifier::*};
        &[BorrowedFormatItem::Component {
                            0: Component::Year(Year::default()),
                        }, BorrowedFormatItem::Literal(b"-"),
                        BorrowedFormatItem::Component {
                            0: Component::Month(Month::default()),
                        }, BorrowedFormatItem::Literal(b"-"),
                        BorrowedFormatItem::Component {
                            0: Component::Day(Day::default()),
                        }, BorrowedFormatItem::Literal(b"T"),
                        BorrowedFormatItem::Component {
                            0: Component::Hour(Hour::default()),
                        }, BorrowedFormatItem::Literal(b":"),
                        BorrowedFormatItem::Component {
                            0: Component::Minute(Minute::default()),
                        }, BorrowedFormatItem::Literal(b":"),
                        BorrowedFormatItem::Component {
                            0: Component::Second(Second::default()),
                        }, BorrowedFormatItem::Literal(b"Z")] as
            StaticFormatDescription
    }format_description!("[year]-[month]-[day]T[hour]:[minute]:[second]Z"),
140    const {
        use ::time::format_description::{*, modifier::*};
        &[BorrowedFormatItem::Component {
                            0: Component::Year(Year::default()),
                        }, BorrowedFormatItem::Literal(b"-"),
                        BorrowedFormatItem::Component {
                            0: Component::Month(Month::default()),
                        }, BorrowedFormatItem::Literal(b"-"),
                        BorrowedFormatItem::Component {
                            0: Component::Day(Day::default()),
                        }, BorrowedFormatItem::Literal(b"T"),
                        BorrowedFormatItem::Component {
                            0: Component::Hour(Hour::default()),
                        }, BorrowedFormatItem::Literal(b":"),
                        BorrowedFormatItem::Component {
                            0: Component::Minute(Minute::default()),
                        }, BorrowedFormatItem::Literal(b":"),
                        BorrowedFormatItem::Component {
                            0: Component::Second(Second::default()),
                        },
                        BorrowedFormatItem::Component {
                            0: Component::OffsetHour({
                                    OffsetHour::default().with_sign_is_mandatory(true)
                                }),
                        }, BorrowedFormatItem::Literal(b":"),
                        BorrowedFormatItem::Component {
                            0: Component::OffsetMinute(OffsetMinute::default()),
                        }] as StaticFormatDescription
    }format_description!(
141        "[year]-[month]-[day]T[hour]:[minute]:[second][offset_hour sign:mandatory]:[offset_minute]"
142    ),
143    const {
        use ::time::format_description::{*, modifier::*};
        &[BorrowedFormatItem::Component {
                            0: Component::Year(Year::default()),
                        }, BorrowedFormatItem::Literal(b"-"),
                        BorrowedFormatItem::Component {
                            0: Component::Month(Month::default()),
                        }, BorrowedFormatItem::Literal(b"-"),
                        BorrowedFormatItem::Component {
                            0: Component::Day(Day::default()),
                        }, BorrowedFormatItem::Literal(b"T"),
                        BorrowedFormatItem::Component {
                            0: Component::Hour(Hour::default()),
                        }, BorrowedFormatItem::Literal(b":"),
                        BorrowedFormatItem::Component {
                            0: Component::Minute(Minute::default()),
                        }, BorrowedFormatItem::Literal(b":"),
                        BorrowedFormatItem::Component {
                            0: Component::Second(Second::default()),
                        }, BorrowedFormatItem::Literal(b"."),
                        BorrowedFormatItem::Component {
                            0: Component::Subsecond(Subsecond::default()),
                        }, BorrowedFormatItem::Literal(b"Z")] as
            StaticFormatDescription
    }format_description!("[year]-[month]-[day]T[hour]:[minute]:[second].[subsecond]Z"),
144    const {
        use ::time::format_description::{*, modifier::*};
        &[BorrowedFormatItem::Component {
                            0: Component::Year(Year::default()),
                        }, BorrowedFormatItem::Literal(b"-"),
                        BorrowedFormatItem::Component {
                            0: Component::Month(Month::default()),
                        }, BorrowedFormatItem::Literal(b"-"),
                        BorrowedFormatItem::Component {
                            0: Component::Day(Day::default()),
                        }, BorrowedFormatItem::Literal(b"T"),
                        BorrowedFormatItem::Component {
                            0: Component::Hour(Hour::default()),
                        }, BorrowedFormatItem::Literal(b":"),
                        BorrowedFormatItem::Component {
                            0: Component::Minute(Minute::default()),
                        }, BorrowedFormatItem::Literal(b":"),
                        BorrowedFormatItem::Component {
                            0: Component::Second(Second::default()),
                        }, BorrowedFormatItem::Literal(b"."),
                        BorrowedFormatItem::Component {
                            0: Component::Subsecond(Subsecond::default()),
                        },
                        BorrowedFormatItem::Component {
                            0: Component::OffsetHour({
                                    OffsetHour::default().with_sign_is_mandatory(true)
                                }),
                        }, BorrowedFormatItem::Literal(b":"),
                        BorrowedFormatItem::Component {
                            0: Component::OffsetMinute(OffsetMinute::default()),
                        }] as StaticFormatDescription
    }format_description!(
145        "[year]-[month]-[day]T[hour]:[minute]:[second].[subsecond][offset_hour sign:mandatory]:[offset_minute]"
146    ),
147];
148
149fn naive_utc(dt: OffsetDateTime) -> PrimitiveDateTime {
150    let dt = dt.to_offset(UtcOffset::UTC);
151    PrimitiveDateTime::new(dt.date(), dt.time())
152}
153
154fn parse_julian(julian_days: f64) -> Result<PrimitiveDateTime, ComponentRange> {
155    const EPOCH_IN_JULIAN_DAYS: f64 = 2_440_587.5;
156    const SECONDS_IN_DAY: f64 = 86400.0;
157    let timestamp = (julian_days - EPOCH_IN_JULIAN_DAYS) * SECONDS_IN_DAY;
158    #[allow(clippy::cast_possible_truncation)] // we multiply by 1E9 to prevent that
159    OffsetDateTime::from_unix_timestamp_nanos((timestamp * 1E9) as i128).map(naive_utc)
160}
161
162#[cfg(all(feature = "__sqlite-shared", feature = "time"))]
163impl FromSql<Date, Sqlite> for NaiveDate {
164    fn from_sql(mut value: <Sqlite as Backend>::RawValue<'_>) -> deserialize::Result<Self> {
165        value
166            .parse_string(|s| Self::parse(s, DATE_FORMAT))
167            .map_err(Into::into)
168    }
169}
170
171#[cfg(all(feature = "__sqlite-shared", feature = "time"))]
172impl ToSql<Date, Sqlite> for NaiveDate {
173    fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Sqlite>) -> serialize::Result {
174        out.set_value(self.format(DATE_FORMAT).map_err(|err| err.to_string())?);
175        Ok(IsNull::No)
176    }
177}
178
179#[cfg(all(feature = "__sqlite-shared", feature = "time"))]
180impl FromSql<Time, Sqlite> for NaiveTime {
181    fn from_sql(mut value: <Sqlite as Backend>::RawValue<'_>) -> deserialize::Result<Self> {
182        value.parse_string(|text| {
183            for format in TIME_FORMATS {
184                if let Ok(time) = Self::parse(text, format) {
185                    return Ok(time);
186                }
187            }
188
189            Err(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("Invalid time {0}", text))
    })format!("Invalid time {text}").into())
190        })
191    }
192}
193
194#[cfg(all(feature = "__sqlite-shared", feature = "time"))]
195impl ToSql<Time, Sqlite> for NaiveTime {
196    fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Sqlite>) -> serialize::Result {
197        let format = if self.microsecond() == 0 {
198            ENCODE_TIME_FORMAT_WHOLE_SECOND
199        } else {
200            ENCODE_TIME_FORMAT_SUBSECOND
201        };
202        out.set_value(self.format(format).map_err(|err| err.to_string())?);
203        Ok(IsNull::No)
204    }
205}
206
207#[cfg(all(feature = "__sqlite-shared", feature = "time"))]
208impl FromSql<Timestamp, Sqlite> for PrimitiveDateTime {
209    fn from_sql(mut value: <Sqlite as Backend>::RawValue<'_>) -> deserialize::Result<Self> {
210        value.parse_string(|text| {
211            for format in PRIMITIVE_DATETIME_FORMATS {
212                if let Ok(dt) = Self::parse(text, format) {
213                    return Ok(dt);
214                }
215            }
216
217            if let Ok(julian_days) = text.parse::<f64>()
218                && let Ok(timestamp) = parse_julian(julian_days)
219            {
220                return Ok(timestamp);
221            }
222
223            Err(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("Invalid datetime {0}", text))
    })format!("Invalid datetime {text}").into())
224        })
225    }
226}
227
228#[cfg(all(feature = "__sqlite-shared", feature = "time"))]
229impl ToSql<Timestamp, Sqlite> for PrimitiveDateTime {
230    fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Sqlite>) -> serialize::Result {
231        let format = if self.nanosecond() == 0 {
232            ENCODE_PRIMITIVE_DATETIME_FORMAT_WHOLE_SECOND
233        } else {
234            ENCODE_PRIMITIVE_DATETIME_FORMAT_SUBSECOND
235        };
236        out.set_value(self.format(format).map_err(|err| err.to_string())?);
237        Ok(IsNull::No)
238    }
239}
240
241#[cfg(all(feature = "__sqlite-shared", feature = "time"))]
242impl FromSql<TimestamptzSqlite, Sqlite> for PrimitiveDateTime {
243    fn from_sql(mut value: <Sqlite as Backend>::RawValue<'_>) -> deserialize::Result<Self> {
244        value.parse_string(|text| {
245            for format in PRIMITIVE_DATETIME_FORMATS {
246                if let Ok(dt) = Self::parse(text, format) {
247                    return Ok(dt);
248                }
249            }
250
251            if let Ok(julian_days) = text.parse::<f64>()
252                && let Ok(timestamp) = parse_julian(julian_days)
253            {
254                return Ok(timestamp);
255            }
256
257            Err(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("Invalid datetime {0}", text))
    })format!("Invalid datetime {text}").into())
258        })
259    }
260}
261
262#[cfg(all(feature = "__sqlite-shared", feature = "time"))]
263impl ToSql<TimestamptzSqlite, Sqlite> for PrimitiveDateTime {
264    fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Sqlite>) -> serialize::Result {
265        let format = if self.nanosecond() == 0 {
266            ENCODE_PRIMITIVE_DATETIME_FORMAT_WHOLE_SECOND
267        } else {
268            ENCODE_PRIMITIVE_DATETIME_FORMAT_SUBSECOND
269        };
270        out.set_value(self.format(format).map_err(|err| err.to_string())?);
271        Ok(IsNull::No)
272    }
273}
274
275#[cfg(all(feature = "__sqlite-shared", feature = "time"))]
276impl FromSql<TimestamptzSqlite, Sqlite> for OffsetDateTime {
277    fn from_sql(mut value: <Sqlite as Backend>::RawValue<'_>) -> deserialize::Result<Self> {
278        // First try to parse the timezone
279        if let Ok(dt) = value.parse_string(|text| {
280            for format in DATETIME_FORMATS {
281                if let Ok(dt) = OffsetDateTime::parse(text, format) {
282                    return Ok(dt);
283                }
284            }
285
286            Err(())
287        }) {
288            return Ok(dt);
289        }
290
291        // Fallback on assuming UTC
292        let primitive_date_time =
293            <PrimitiveDateTime as FromSql<TimestamptzSqlite, Sqlite>>::from_sql(value)?;
294        Ok(primitive_date_time.assume_utc())
295    }
296}
297
298#[cfg(all(feature = "__sqlite-shared", feature = "time"))]
299impl ToSql<TimestamptzSqlite, Sqlite> for OffsetDateTime {
300    fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Sqlite>) -> serialize::Result {
301        // Converting to UTC ensures consistency
302        let dt_utc = self.to_offset(UtcOffset::UTC);
303        let format = if self.nanosecond() == 0 {
304            ENCODE_DATETIME_FORMAT_WHOLE_SECOND
305        } else {
306            ENCODE_DATETIME_FORMAT_SUBSECOND
307        };
308        out.set_value(dt_utc.format(format).map_err(|err| err.to_string())?);
309        Ok(IsNull::No)
310    }
311}
312
313#[cfg(all(test, not(all(target_family = "wasm", target_os = "unknown"))))]
314mod tests {
315    extern crate dotenvy;
316
317    use super::time::{
318        Date as NaiveDate, Duration, OffsetDateTime, PrimitiveDateTime, Time as NaiveTime,
319        macros::{date, datetime},
320    };
321
322    use super::naive_utc;
323
324    use crate::dsl::{now, sql};
325    use crate::prelude::*;
326    use crate::select;
327    use crate::sql_types::{Text, Time, Timestamp, TimestamptzSqlite};
328    use crate::test_helpers::connection;
329
330    #[declare_sql_function]
331    extern "SQL" {
332        fn datetime(x: Text) -> Timestamp;
333        fn time(x: Text) -> Time;
334        fn date(x: Text) -> Date;
335    }
336
337    #[diesel_test_helper::test]
338    fn unix_epoch_encodes_correctly() {
339        let connection = &mut connection();
340        let time = datetime!(1970-1-1 0:0:0);
341        let query = select(datetime("1970-01-01 00:00:00.000000").eq(time));
342        assert_eq!(Ok(true), query.get_result(connection));
343    }
344
345    #[diesel_test_helper::test]
346    fn unix_epoch_decodes_correctly_in_all_possible_formats() {
347        let connection = &mut connection();
348        let time = datetime!(1970-1-1 0:0:0);
349        let valid_epoch_formats = vec![
350            "1970-01-01 00:00",
351            "1970-01-01 00:00:00",
352            "1970-01-01 00:00:00.000",
353            "1970-01-01 00:00:00.000000",
354            "1970-01-01T00:00",
355            "1970-01-01T00:00:00",
356            "1970-01-01T00:00:00.000",
357            "1970-01-01T00:00:00.000000",
358            "1970-01-01 00:00Z",
359            "1970-01-01 00:00:00Z",
360            "1970-01-01 00:00:00.000Z",
361            "1970-01-01 00:00:00.000000Z",
362            "1970-01-01T00:00Z",
363            "1970-01-01T00:00:00Z",
364            "1970-01-01T00:00:00.000Z",
365            "1970-01-01T00:00:00.000000Z",
366            "1970-01-01 00:00+00:00",
367            "1970-01-01 00:00:00+00:00",
368            "1970-01-01 00:00:00.000+00:00",
369            "1970-01-01 00:00:00.000000+00:00",
370            "1970-01-01T00:00+00:00",
371            "1970-01-01T00:00:00+00:00",
372            "1970-01-01T00:00:00.000+00:00",
373            "1970-01-01T00:00:00.000000+00:00",
374            "1970-01-01 00:00+01:00",
375            "1970-01-01 00:00:00+01:00",
376            "1970-01-01 00:00:00.000+01:00",
377            "1970-01-01 00:00:00.000000+01:00",
378            "1970-01-01T00:00+01:00",
379            "1970-01-01T00:00:00+01:00",
380            "1970-01-01T00:00:00.000+01:00",
381            "1970-01-01T00:00:00.000000+01:00",
382            "1970-01-01T00:00-01:00",
383            "1970-01-01T00:00:00-01:00",
384            "1970-01-01T00:00:00.000-01:00",
385            "1970-01-01T00:00:00.000000-01:00",
386            "1970-01-01T00:00-01:00",
387            "1970-01-01T00:00:00-01:00",
388            "1970-01-01T00:00:00.000-01:00",
389            "1970-01-01T00:00:00.000000-01:00",
390            "2440587.5",
391        ];
392
393        for s in valid_epoch_formats {
394            let epoch_from_sql = select(sql::<Timestamp>(&format!("'{s}'"))).get_result(connection);
395            assert_eq!(Ok(time), epoch_from_sql, "format {s} failed");
396        }
397    }
398
399    #[diesel_test_helper::test]
400    fn times_relative_to_now_encode_correctly() {
401        let connection = &mut connection();
402        let time = naive_utc(OffsetDateTime::now_utc()) + Duration::seconds(60);
403        let query = select(now.lt(time));
404        assert_eq!(Ok(true), query.get_result(connection));
405
406        let time = naive_utc(OffsetDateTime::now_utc()) - Duration::seconds(600);
407        let query = select(now.gt(time));
408        assert_eq!(Ok(true), query.get_result(connection));
409    }
410
411    #[diesel_test_helper::test]
412    fn times_of_day_encode_correctly() {
413        let connection = &mut connection();
414
415        let midnight = NaiveTime::from_hms(0, 0, 0).unwrap();
416        let query = select(time("00:00:00").eq(midnight));
417        assert!(query.get_result::<bool>(connection).unwrap());
418
419        let noon = NaiveTime::from_hms(12, 0, 0).unwrap();
420        let query = select(time("12:00:00").eq(noon));
421        assert!(query.get_result::<bool>(connection).unwrap());
422
423        let roughly_half_past_eleven = NaiveTime::from_hms_micro(23, 37, 4, 2200).unwrap();
424        let query = select(sql::<Time>("'23:37:04.0022'").eq(roughly_half_past_eleven));
425        assert!(query.get_result::<bool>(connection).unwrap());
426    }
427
428    #[diesel_test_helper::test]
429    fn times_of_day_decode_correctly() {
430        let connection = &mut connection();
431        let midnight = NaiveTime::from_hms(0, 0, 0).unwrap();
432        let valid_midnight_formats = &[
433            "00:00",
434            "00:00:00",
435            "00:00:00.000",
436            "00:00:00.000000",
437            "00:00Z",
438            "00:00:00Z",
439            "00:00:00.000Z",
440            "00:00:00.000000Z",
441            "00:00+00:00",
442            "00:00:00+00:00",
443            "00:00:00.000+00:00",
444            "00:00:00.000000+00:00",
445            "00:00+01:00",
446            "00:00:00+01:00",
447            "00:00:00.000+01:00",
448            "00:00:00.000000+01:00",
449            "00:00-01:00",
450            "00:00:00-01:00",
451            "00:00:00.000-01:00",
452            "00:00:00.000000-01:00",
453        ];
454        for format in valid_midnight_formats {
455            let query = select(sql::<Time>(&format!("'{format}'")));
456            assert_eq!(
457                Ok(midnight),
458                query.get_result::<NaiveTime>(connection),
459                "format {format} failed"
460            );
461        }
462
463        let noon = NaiveTime::from_hms(12, 0, 0).unwrap();
464        let query = select(sql::<Time>("'12:00:00'"));
465        assert_eq!(Ok(noon), query.get_result::<NaiveTime>(connection));
466
467        let roughly_half_past_eleven = NaiveTime::from_hms_micro(23, 37, 4, 2200).unwrap();
468        let query = select(sql::<Time>("'23:37:04.002200'"));
469        assert_eq!(
470            Ok(roughly_half_past_eleven),
471            query.get_result::<NaiveTime>(connection)
472        );
473    }
474
475    #[diesel_test_helper::test]
476    fn dates_encode_correctly() {
477        let connection = &mut connection();
478        let january_first_2000 = date!(2000 - 1 - 1);
479        let query = select(date("2000-01-01").eq(january_first_2000));
480        assert!(query.get_result::<bool>(connection).unwrap());
481
482        let distant_past = date!(0 - 4 - 11);
483        let query = select(date("0000-04-11").eq(distant_past));
484        assert!(query.get_result::<bool>(connection).unwrap());
485
486        let january_first_2018 = date!(2018 - 1 - 1);
487        let query = select(date("2018-01-01").eq(january_first_2018));
488        assert!(query.get_result::<bool>(connection).unwrap());
489
490        let distant_future = date!(9999 - 1 - 8);
491        let query = select(date("9999-01-08").eq(distant_future));
492        assert!(query.get_result::<bool>(connection).unwrap());
493    }
494
495    #[diesel_test_helper::test]
496    fn dates_decode_correctly() {
497        let connection = &mut connection();
498        let january_first_2000 = date!(2000 - 1 - 1);
499        let query = select(date("2000-01-01"));
500        assert_eq!(
501            Ok(january_first_2000),
502            query.get_result::<NaiveDate>(connection)
503        );
504
505        let distant_past = date!(0 - 4 - 11);
506        let query = select(date("0000-04-11"));
507        assert_eq!(Ok(distant_past), query.get_result::<NaiveDate>(connection));
508
509        let january_first_2018 = date!(2018 - 1 - 1);
510        let query = select(date("2018-01-01"));
511        assert_eq!(
512            Ok(january_first_2018),
513            query.get_result::<NaiveDate>(connection)
514        );
515
516        let distant_future = date!(9999 - 1 - 8);
517        let query = select(date("9999-01-08"));
518        assert_eq!(
519            Ok(distant_future),
520            query.get_result::<NaiveDate>(connection)
521        );
522    }
523
524    #[diesel_test_helper::test]
525    fn datetimes_decode_correctly() {
526        let connection = &mut connection();
527        let january_first_2000 = datetime!(2000-1-1 1:1:1);
528        let query = select(datetime("2000-01-01 01:01:01.000000"));
529        assert_eq!(
530            Ok(january_first_2000),
531            query.get_result::<PrimitiveDateTime>(connection)
532        );
533
534        let distant_past = datetime!(0-4-11 2:2:2);
535        let query = select(datetime("0000-04-11 02:02:02.000000"));
536        assert_eq!(
537            Ok(distant_past),
538            query.get_result::<PrimitiveDateTime>(connection)
539        );
540
541        let january_first_2018 = date!(2018 - 1 - 1);
542        let query = select(date("2018-01-01"));
543        assert_eq!(
544            Ok(january_first_2018),
545            query.get_result::<NaiveDate>(connection)
546        );
547
548        let distant_future = datetime!(9999 - 1 - 8 23:59:59.0001);
549        let query = select(sql::<Timestamp>("'9999-01-08 23:59:59.000100'"));
550        assert_eq!(
551            Ok(distant_future),
552            query.get_result::<PrimitiveDateTime>(connection)
553        );
554    }
555
556    #[diesel_test_helper::test]
557    fn datetimes_encode_correctly() {
558        let connection = &mut connection();
559        let january_first_2000 = datetime!(2000-1-1 0:0:0);
560        let query = select(datetime("2000-01-01 00:00:00").eq(january_first_2000));
561        assert!(query.get_result::<bool>(connection).unwrap());
562
563        let distant_past = datetime!(0-4-11 20:00:20);
564        let query = select(datetime("0000-04-11 20:00:20").eq(distant_past));
565        assert!(query.get_result::<bool>(connection).unwrap());
566
567        let january_first_2018 = datetime!(2018 - 1 - 1 12:00:00.0005);
568        let query = select(sql::<Timestamp>("'2018-01-01 12:00:00.0005'").eq(january_first_2018));
569        assert!(query.get_result::<bool>(connection).unwrap());
570
571        let distant_future = datetime!(9999-1-8 0:0:0);
572        let query = select(datetime("9999-01-08 00:00:00").eq(distant_future));
573        assert!(query.get_result::<bool>(connection).unwrap());
574    }
575
576    #[diesel_test_helper::test]
577    fn insert_timestamptz_into_table_as_text() {
578        crate::table! {
579            #[allow(unused_parens)]
580            test_insert_timestamptz_into_table_as_text(id) {
581                id -> Integer,
582                timestamp_with_tz -> TimestamptzSqlite,
583            }
584        }
585        let conn = &mut connection();
586        crate::sql_query(
587            "CREATE TABLE test_insert_timestamptz_into_table_as_text(id INTEGER PRIMARY KEY, timestamp_with_tz TEXT);",
588        )
589        .execute(conn)
590        .unwrap();
591
592        let time: OffsetDateTime = datetime!(1970-1-1 0:0:0.0 utc);
593
594        crate::insert_into(test_insert_timestamptz_into_table_as_text::table)
595            .values(vec![(
596                test_insert_timestamptz_into_table_as_text::id.eq(1),
597                test_insert_timestamptz_into_table_as_text::timestamp_with_tz.eq(sql::<
598                    TimestamptzSqlite,
599                >(
600                    "'1970-01-01 00:00:00.000000+00:00'",
601                )),
602            )])
603            .execute(conn)
604            .unwrap();
605
606        let result = test_insert_timestamptz_into_table_as_text::table
607            .select(test_insert_timestamptz_into_table_as_text::timestamp_with_tz)
608            .get_result::<OffsetDateTime>(conn)
609            .unwrap();
610        assert_eq!(result, time);
611    }
612
613    #[diesel_test_helper::test]
614    fn can_query_timestamptz_column_with_between() {
615        crate::table! {
616            #[allow(unused_parens)]
617            test_query_timestamptz_column_with_between(id) {
618                id -> Integer,
619                timestamp_with_tz -> TimestamptzSqlite,
620            }
621        }
622        let conn = &mut connection();
623        crate::sql_query(
624            "CREATE TABLE test_query_timestamptz_column_with_between(id INTEGER PRIMARY KEY, timestamp_with_tz TEXT);",
625        )
626        .execute(conn)
627        .unwrap();
628
629        crate::insert_into(test_query_timestamptz_column_with_between::table)
630            .values(vec![
631                (
632                    test_query_timestamptz_column_with_between::id.eq(1),
633                    test_query_timestamptz_column_with_between::timestamp_with_tz.eq(sql::<
634                        TimestamptzSqlite,
635                    >(
636                        "'1970-01-01 00:00:01.000000+00:00'",
637                    )),
638                ),
639                (
640                    test_query_timestamptz_column_with_between::id.eq(2),
641                    test_query_timestamptz_column_with_between::timestamp_with_tz.eq(sql::<
642                        TimestamptzSqlite,
643                    >(
644                        "'1970-01-01 00:00:02.000000+00:00'",
645                    )),
646                ),
647                (
648                    test_query_timestamptz_column_with_between::id.eq(3),
649                    test_query_timestamptz_column_with_between::timestamp_with_tz.eq(sql::<
650                        TimestamptzSqlite,
651                    >(
652                        "'1970-01-01 00:00:03.000000+00:00'",
653                    )),
654                ),
655                (
656                    test_query_timestamptz_column_with_between::id.eq(4),
657                    test_query_timestamptz_column_with_between::timestamp_with_tz.eq(sql::<
658                        TimestamptzSqlite,
659                    >(
660                        "'1970-01-01 00:00:04.000000+00:00'",
661                    )),
662                ),
663            ])
664            .execute(conn)
665            .unwrap();
666
667        let result = test_query_timestamptz_column_with_between::table
668            .select(test_query_timestamptz_column_with_between::timestamp_with_tz)
669            .filter(
670                test_query_timestamptz_column_with_between::timestamp_with_tz
671                    .gt(datetime!(1970-1-1 0:0:0.0 utc)),
672            )
673            .filter(
674                test_query_timestamptz_column_with_between::timestamp_with_tz
675                    .lt(datetime!(1970-1-1 0:0:4.0 utc)),
676            )
677            .count()
678            .get_result::<_>(conn);
679        assert_eq!(result, Ok(3));
680    }
681
682    #[diesel_test_helper::test]
683    fn unix_epoch_encodes_correctly_with_timezone() {
684        let connection = &mut connection();
685        // West one hour is negative offset
686        let time = datetime!(1970-1-1 0:00:00.001 -1:00);
687        let query = select(sql::<TimestamptzSqlite>("'1970-01-01 01:00:00.001+00:00'").eq(time));
688        assert!(query.get_result::<bool>(connection).unwrap());
689    }
690
691    #[diesel_test_helper::test]
692    fn unix_epoch_encodes_correctly_with_utc_timezone() {
693        let connection = &mut connection();
694        let time: OffsetDateTime = datetime!(1970-1-1 0:0:0.001 utc);
695        let query = select(sql::<TimestamptzSqlite>("'1970-01-01 00:00:00.001+00:00'").eq(time));
696        assert!(query.get_result::<bool>(connection).unwrap());
697
698        // and without millisecond
699        let time: OffsetDateTime = datetime!(1970-1-1 0:0:0 utc);
700        let query = select(sql::<TimestamptzSqlite>("'1970-01-01 00:00:00+00:00'").eq(time));
701        assert!(query.get_result::<bool>(connection).unwrap());
702    }
703
704    #[diesel_test_helper::test]
705    fn unix_epoch_decodes_correctly_with_utc_timezone_in_all_possible_formats() {
706        let connection = &mut connection();
707        let time: OffsetDateTime = datetime!(1970-1-1 0:0:0 utc);
708        let valid_epoch_formats = vec![
709            "1970-01-01 00:00Z",
710            "1970-01-01 00:00:00Z",
711            "1970-01-01 00:00:00.000Z",
712            "1970-01-01 00:00:00.000000Z",
713            "1970-01-01T00:00Z",
714            "1970-01-01T00:00:00Z",
715            "1970-01-01T00:00:00.000Z",
716            "1970-01-01T00:00:00.000000Z",
717            "1970-01-01 00:00+00:00",
718            "1970-01-01 00:00:00+00:00",
719            "1970-01-01 00:00:00.000+00:00",
720            "1970-01-01 00:00:00.000000+00:00",
721            "1970-01-01T00:00+00:00",
722            "1970-01-01T00:00:00+00:00",
723            "1970-01-01T00:00:00.000+00:00",
724            "1970-01-01T00:00:00.000000+00:00",
725            "2440587.5",
726        ];
727
728        for s in valid_epoch_formats {
729            let epoch_from_sql =
730                select(sql::<TimestamptzSqlite>(&format!("'{s}'"))).get_result(connection);
731            assert_eq!(Ok(time), epoch_from_sql, "format {s} failed");
732        }
733    }
734}