You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Rust中DateTime::parse_from_rfc3339解析Bungie API日期报错排查

解析Bungie API返回的RFC3339日期时触发Panic的原因

我尝试通过Bungie API获取数据,返回的JSON中包含格式为"2022-09-18T02:17:59Z"的最后游玩日期,希望将其解析为DateTime对象。

以下是我的代码(个人数据已替换为XXX):

const API_ROOT: &str = "https://www.bungie.net/Platform";
const API_KEY_HEADER: &str = "X-API-Key";

const MY_API_KEY: &str = "XXX";

const MEMBERSHIP_TYPE: &str = "XXX";
const MEMBERSHIP_ID: &str = "XXX";

#[tokio::main]
async fn main() -> Result<(), reqwest::Error> {
    let url = format!("{}/Destiny2/{}/Profile/{}/?components=100", API_ROOT, MEMBERSHIP_TYPE, MEMBERSHIP_ID);

    let req = reqwest::Client::new()
        .get(url)
        .header(API_KEY_HEADER, MY_API_KEY)
        .send()
        .await?
        .text()
        .await?;

    let data: JsonValue = serde_json::from_str(&req).expect("Failed to read json from response!");

    let name = &data["Response"]["profile"]["data"]["userInfo"]["displayName"].to_string();
    println!("Name: {}", name);

    let last_played_raw = &data["Response"]["profile"]["data"]["dateLastPlayed"].to_string();
    println!("{}", last_played_raw);
    let last_played_raw = last_played_raw.replace("Z", "+00:00");
    println!("{}", last_played_raw);

    let last_played = DateTime::parse_from_rfc3339(&last_played_raw).unwrap();

    println!("Last played: {}", last_played);

    Ok(())
}

问题在于解析last_played_raw字符串时触发了panic:

"2022-09-18T02:17:59Z"
"2022-09-18T02:17:59+00:00"
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: ParseError(Invalid)', src\main.rs:37:70

原因与解决方法

核心问题

你调用to_string()获取JSON中的日期字符串时,返回的结果包含了JSON原生的双引号。比如原本的日期值是2022-09-18T02:17:59Z,但to_string()后得到的是"2022-09-18T02:17:59Z"(带首尾双引号)。替换Z为+00:00后变成"2022-09-18T02:17:59+00:00",这种带引号的字符串不符合RFC3339格式,导致解析失败。

解决方式1:使用as_str()获取无引号的字符串切片

直接用as_str()代替to_string(),它会返回JSON字符串的原始内容(不带引号),而且parse_from_rfc3339原生支持Z作为UTC标识,不需要手动替换:

// 替换日期获取与解析的代码
let last_played_raw = data["Response"]["profile"]["data"]["dateLastPlayed"]
    .as_str()
    .expect("dateLastPlayed is not a valid string");
let last_played = DateTime::parse_from_rfc3339(last_played_raw).unwrap();

解决方式2:手动去除字符串首尾的引号

如果坚持用to_string(),需要先去掉首尾的双引号:

let last_played_raw = &data["Response"]["profile"]["data"]["dateLastPlayed"].to_string();
// 去除首尾的双引号
let last_played_raw = last_played_raw.trim_matches('"');
let last_played = DateTime::parse_from_rfc3339(last_played_raw).unwrap();

内容的提问来源于stack exchange,提问作者Roman Theuer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 20:40:31