📣 极限科技诚招搜索运维工程师(Elasticsearch/Easysearch)- 全职/北京 👉 : 立即申请加入

为什么这个错误发生 #

timestamp_parsing_exception 表示解析时间戳字符串时失败。这通常发生在尝试将字符串转换为日期时间类型时。

这个错误可能由以下原因引起:

  1. 格式不匹配:时间戳格式与预期不匹配
  2. 无效的日期值:包含无效的日期(如 2 月 30 日)
  3. 时区问题:时区信息缺失或错误
  4. 格式字符串错误:指定的日期格式字符串不正确
  5. 空值或 null:时间戳为空或 null
  6. 特殊字符:包含无法解析的特殊字符
  7. 非标准格式:使用了非标准的日期格式
  8. 编码问题:字符编码问题
  9. 多位数年份:年份位数不正确
  10. 本地化格式:使用了本地化的日期格式

如何修复这个错误 #

1. 查看错误的时间戳 #

# 错误响应包含无法解析的时间戳
{
  "error": {
    "type": "timestamp_parsing_exception",
    "reason": "failed to parse timestamp [invalid_timestamp]"
  }
}

2. 使用标准日期格式 #

# 使用 ISO 8601 格式(推荐)
GET /<index>/_search
{
  "query": {
    "range": {
      "date_field": {
        "gte": "2024-01-01T00:00:00Z",
        "lte": "2024-12-31T23:59:59Z"
      }
    }
  }
}

3. 指定日期格式 #

# 在查询中指定格式
GET /<index>/_search
{
  "query": {
    "range": {
      "date_field": {
        "gte": "01/01/2024",
        "lte": "12/31/2024",
        "format": "MM/dd/yyyy"
      }
    }
  }
}

4. 在映射中定义格式 #

# 在索引映射中定义日期格式
PUT /<index>
{
  "mappings": {
    "properties": {
      "date_field": {
        "type": "date",
        "format": "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis"
      }
    }
  }
}

5. 使用日期数学 #

# 使用日期数学表达式
GET /<index>/_search
{
  "query": {
    "range": {
      "date_field": {
        "gte": "now-1d/d",
        "lte": "now/d"
      }
    }
  }
}

6. 处理多种格式 #

# 支持多种日期格式
GET /<index>/_mapping
{
  "properties": {
    "date_field": {
      "type": "date",
      "format": "strict_date_optional_time||epoch_millis"
    }
  }
}

7. 使用毫秒时间戳 #

# 使用 epoch 毫秒时间戳
GET /<index>/_search
{
  "query": {
    "range": {
      "date_field": {
        "gte": 1704067200000,
        "lte": 1735660799999
      }
    }
  }
}

8. 验证日期值 #

# 确保日期值有效
# 正确:2024-02-29(2024 是闰年)
# 错误:2023-02-29(2023 不是闰年)

9. 处理时区 #

# 指定时区
GET /<index>/_search
{
  "query": {
    "range": {
      "date_field": {
        "gte": "2024-01-01T00:00:00+08:00",
        "lte": "2024-12-31T23:59:59+08:00"
      }
    }
  }
}

# 或使用时区名称
{
  "range": {
    "date_field": {
      "gte": "2024-01-01T00:00:00",
      "lte": "2024-12-31T23:59:59",
      "time_zone": "+08:00"
    }
  }
}

10. 使用严格格式 #

# 使用严格格式避免歧义
PUT /<index>
{
  "mappings": {
    "properties": {
      "date_field": {
        "type": "date",
        "format": "strict_date_optional_time"
      }
    }
  }
}

11. 预处理时间戳 #

// 在客户端预处理时间戳
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
String formattedDate = date.format(formatter);

12. 处理空值 #

# 处理可能为空的时间戳
GET /<index>/_search
{
  "query": {
    "bool": {
      "must_not": {
        "exists": {
          "field": "date_field"
        }
      }
    }
  }
}

13. 使用脚本处理 #

# 使用脚本转换时间戳
GET /<index>/_search
{
  "query": {
    "script": {
      "script": {
        "source": "doc['date_field'].size() > 0",
        "lang": "painless"
      }
    }
  }
}

14. 验证输入格式 #

# 在发送请求前验证格式
# 使用日期验证工具

15. 使用客户端库 #

// 使用客户端库处理日期
// 确保格式正确
ZonedDateTime datetime = ZonedDateTime.now(ZoneId.of("Asia/Shanghai"));
String formatted = DateTimeFormatter.ISO_OFFSET_DATE_TIME.format(datetime);

预防措施 #

  • 使用标准日期格式(ISO 8601)
  • 在映射中明确定义格式
  • 验证输入日期值
  • 处理时区信息
  • 使用日期数学表达式
  • 在客户端预处理日期
  • 使用严格格式避免歧义
  • 测试日期解析逻辑
  • 处理空值和异常
  • 文档化日期格式要求