# 22007 — invalid_datetime_format

> PostgreSQL SQLSTATE 22007 的源码与诊断参考。
---

# 22007

## 速览 {#at-a-glance}

固定 interval 格式化路径报告 `invalid format specification for an interval value`，并说明 interval 不绑定到特定日历日期。

<!-- BEGIN SQLSTATE FACTS: generated by scripts/generate.py; do not edit -->

| 字段 | 值 |
| --- | --- |
| SQLSTATE | `22007` |
| 条件名 | `invalid_datetime_format` |
| 状态 | `有效` |
| 已知存在于 | `7.4` |
| 锁定快照 | `9.0.23, 9.1.24, 9.2.24, 9.3.25, 9.4.26, 9.5.25, 9.6.24, 10.23, 11.22, 12.22, 13.23, 14.24, 15.19, 16.15, 17.11, 18.6, 19beta3` |
| 宏 | `ERRCODE_INVALID_DATETIME_FORMAT` |
| 别名 | `—` |

<!-- source facts: data/errcodes/22007.json -->
<!-- END SQLSTATE FACTS -->

共享案例用无效的 `ID` mask 格式化 `interval '1 day'`，再用 `DD` 作为修复后的 interval 格式。本案例应分开发送两条 SELECT；第一条预期失败，之后再执行修复格式。本案例只验证 interval 格式化路径；会话清理由运行器负责。

<!-- BEGIN SQLSTATE SNIPPET: invalid_interval_format -->
```sql
SELECT to_char(interval '1 day', 'ID');
SELECT to_char(interval '1 day', 'DD');
```
<!-- END SQLSTATE SNIPPET -->

校准实测了 interval 的 DCH 格式化路径：无效格式报告 `invalid format specification for an interval value`，提示为 `Intervals are not tied to specific calendar dates.`；有效 `DD` 格式返回 `01`，运行器的两条自动提交会话均回到 `IDLE`。本次运行只覆盖 interval 格式化；一般日期解析和 DateStyle 仍属于源码/文档范围。

## 报文 {#messages}

`INVALID_FOR_INTERVAL` guard 以 `ERROR` 严重性报告 primary：`invalid format specification for an interval value`，HINT 为 `Intervals are not tied to specific calendar dates.`。引用分支没有独立 DETAIL。固定日期输入解析的 `DTERR_BAD_FORMAT`/default 分支把 22007 映射为通用 primary 模板 `invalid input syntax for type %s: "%s"`；相邻的字段越界和月日越界分支使用 22008，后者才会增加 HINT `Perhaps you need a different "DateStyle" setting.`。其他日期时间格式解析器也可能使用 22007 并产生不同的 primary/detail/hint，因此应保留完整诊断。

## 含义 {#meaning}

`22007` 表示所选日期时间转换的输入或格式说明无效。固定 18.6 interval 格式化路径报告 `invalid format specification for an interval value`，并说明 interval 不绑定到特定日历日期。在这个 DCH 路径中，`ID` 是带日历语义的星期几 token，interval 不支持；`DD` 则可用。固定日期输入路径会通过 `ParseDateTime`/`DecodeDateTime` 和 `DateTimeParseError` 处理文本：bad-format/default 分支使用 `invalid input syntax for type %s: "%s"`；字段越界属于 22008，其月日歧义分支才可能提示调整 `DateStyle`。18.6 文档说明 `DateStyle` 选择含糊数字日期的解释顺序。`DateTimeParseError` 可以填充 `ErrorSaveContext` 而不直接抛错，因此 soft-validation 调用与正常 cast/input 传播 `ERROR` 的行为不同。

## 诊断 {#diagnosis}

记录原始文本、目标类型、`DateStyle`、`TimeZone`、format mask，以及操作是 cast、输入函数、`to_date`/`to_timestamp` 还是 interval 格式化。在改变数据前，用部署会话设置重现同一文本。区分无效 token/分隔符与已解析但超出范围的月日字段；后者可能产生 22008。

## 处置 {#response}

让输入无歧义，在适当场景使用显式格式或 ISO 形式，并在应用边界明确设置会话解析选项。interval 格式化应使用支持 interval 的 mask，而不是日历日期 mask。本次固定案例使用自动提交，失败格式化调用后会话仍为 `IDLE`；显式事务中应先回滚整个事务，或回滚到失败调用前已有的保存点，再继续执行。写入前拒绝或修正无效文本，不要用切换 `DateStyle` 的方式静默改写含义。

## 版本 {#versions}

锁定目录从 7.4 记录该条件，并在列出的正式快照及 19beta3 中出现；固定源码覆盖为 PostgreSQL 18.6。

## 相关条件 {#related}

[`22008`](../22008/) 是日期时间字段/范围越界，[`22009`](../22009/) 是时区位移越界，[`22003`](../22003/) 是数值范围错误。

## 来源 {#sources}

固定 interval 格式化路径见 [`formatting.c#L555-L558`](https://github.com/postgres/postgres/blob/724edf9bde9d356724ad384a2e196edc3c9f80f7/src/backend/utils/adt/formatting.c#L555-L558)；固定日期输入 dispatch 见 [`date.c#L110-L178`](https://github.com/postgres/postgres/blob/724edf9bde9d356724ad384a2e196edc3c9f80f7/src/backend/utils/adt/date.c#L110-L178)，通用解析错误映射见 [`datetime.c#L4195-L4266`](https://github.com/postgres/postgres/blob/724edf9bde9d356724ad384a2e196edc3c9f80f7/src/backend/utils/adt/datetime.c#L4195-L4266)。PostgreSQL 18 的[日期时间输入文档](https://www.postgresql.org/docs/18/datatype-datetime.html#DATATYPE-DATETIME-INPUT)说明了 `DateStyle` 和含糊日期文本。结构化[证据记录](../../data/evidence/22007.json)固定了这些源码、消息与 hint。
