繁体   English   中英

在一个地方调用 NaiveDateTime::parse_from_str 失败,但在另一点工作

[英]Call to NaiveDateTime::parse_from_str fails when invoked at one place but works from other point

我正在尝试实现一个例程,该例程读取 JSON 中具有“@timestamp”键的文件。 我需要将时间戳从类似于“2022-01-19T18:15:36.283Z”的格式转换为纪元时间(自 1970 年 1 月 1 日以来的毫秒)。 Rust代码如下:

use chrono::*;
use serde_json::{Result, Value};

fn convert_to_epoch(ddd: &str) -> i64 {
    println!(">>>> {}", ddd);
    let tmp = NaiveDateTime::parse_from_str(ddd, "%Y-%m-%dT%H:%M:%S%.3fZ");
    println!(">>>> {:?}", tmp);
    let epoch_time = tmp.unwrap();
    return epoch_time.timestamp_millis();
}

fn get_ts(v: &Value) -> (bool, String) {
    if let Some(field) = v.get("@timestamp") {
        return (true, field.to_string());
    } else {
        if let Some(field) = v.get("date") {
            return (true, field.to_string());
        } else {
            if let Some(field) = v.get("timestamp") {
                return (true, field.to_string());
            } else {
                if let Some(field) = v.get("time") {
                    return (true, field.to_string());
                } else {
                    return (false, "".to_string());
                }
            }
        }
    }
}

fn parse_file() -> Result<()> {
    let filepath = "/tmp/input.txt";
    println!("######## filepath={}", filepath);
    let data = std::fs::read_to_string(filepath).expect("file not found!");
    let lines = data.lines();
    for line in lines {
        if line.starts_with('{') && line.ends_with('}') {
            let v: Value = serde_json::from_str(line)?;
            let (exists, ts) = get_ts(&v);
            if !exists {
                println!("ts not found");
            } else {
                println!("{}", ts);
            }
            let ddd = String::from(ts);
            let epoch_time = convert_to_epoch(&ddd);
            println!("{}", epoch_time);
        } else {
            println!("Found a non JSON line: {}", line);
        }
    }
    let ddd = String::from("2022-01-19T18:15:36.283Z");
    let epoch_time = convert_to_epoch(&ddd);
    println!("{:?}", epoch_time);
    Ok(())
}
fn main() {
    let _result = parse_file();
}

当我按原样运行代码时,它会恐慌并打印以下内容:

   Compiling p1 v0.1.0 (/Users/abc/rust/p1)
    Finished dev [unoptimized + debuginfo] target(s) in 1.24s
     Running `target/debug/p1`
######## filepath=/tmp/input.txt
"2022-01-19T18:15:36.283Z"
>>>> "2022-01-19T18:15:36.283Z"
>>>> Err(ParseError(Invalid))
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: ParseError(Invalid)', src/main.rs:8:26
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

但是当我注释掉第 46、47 和 48 行时,第 53、54 和 55 行的代码执行得很好,并打印出以下内容:

   Compiling p1 v0.1.0 (/Users/abc/rust/p1)
    Finished dev [unoptimized + debuginfo] target(s) in 0.40s
     Running `target/debug/p1`
######## filepath=/tmp/input.txt
"2022-01-19T18:15:36.283Z"
"2022-01-19T18:15:36.298Z"
"2022-01-19T18:15:41.161Z"
"2022-01-19T18:15:41.164Z"
"2022-01-19T18:16:38.281Z"
>>>> 2022-01-19T18:15:36.283Z
>>>> Ok(2022-01-19T18:15:36.283)
1642616136283

据我所知,第 46 到 48 行的代码与第 53 到 55 行的代码相同。第 53 到 55 行的调用有效,但第 46 到 48 行的调用失败。

input.txt文件内容如下:

{"@timestamp":"2022-01-19T18:15:36.283Z"}
{"@timestamp":"2022-01-19T18:15:36.298Z"}
{"@timestamp":"2022-01-19T18:15:41.161Z"}
{"@timestamp":"2022-01-19T18:15:41.164Z"}
{"@timestamp":"2022-01-19T18:16:38.281Z"}

我能够检测并解决问题。 出于某种原因,行let ddd = String::from(ts); 导致 ddd 在字符串的开头和结尾有双引号。 当我修改该行以let ddd = String::from(ts).replace("\"", "");时,它不再崩溃。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM