![](/img/trans.png)
[英]Rust chrono::NaiveTime::parse_from_str() fails to parse PM
[英]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.