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