mirror of
https://github.com/nushell/nushell
synced 2024-12-27 13:33:16 +00:00
Avoid using time conversion methods that may panic (#5365)
This commit is contained in:
parent
b4f8798a3a
commit
fa27110651
1 changed files with 57 additions and 25 deletions
|
@ -1,6 +1,6 @@
|
||||||
use crate::DirBuilder;
|
use crate::DirBuilder;
|
||||||
use crate::DirInfo;
|
use crate::DirInfo;
|
||||||
use chrono::{DateTime, Local};
|
use chrono::{DateTime, Local, LocalResult, TimeZone, Utc};
|
||||||
use nu_engine::env::current_dir;
|
use nu_engine::env::current_dir;
|
||||||
use nu_engine::CallExt;
|
use nu_engine::CallExt;
|
||||||
use nu_path::expand_to_real_path;
|
use nu_path::expand_to_real_path;
|
||||||
|
@ -15,6 +15,7 @@ use pathdiff::diff_paths;
|
||||||
use std::os::unix::fs::PermissionsExt;
|
use std::os::unix::fs::PermissionsExt;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
use std::time::{SystemTime, UNIX_EPOCH};
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Ls;
|
pub struct Ls;
|
||||||
|
@ -489,37 +490,46 @@ pub(crate) fn dir_entry_dict(
|
||||||
if let Some(md) = metadata {
|
if let Some(md) = metadata {
|
||||||
if long {
|
if long {
|
||||||
cols.push("created".to_string());
|
cols.push("created".to_string());
|
||||||
if let Ok(c) = md.created() {
|
{
|
||||||
let utc: DateTime<Local> = c.into();
|
let mut val = Value::nothing(span);
|
||||||
vals.push(Value::Date {
|
if let Ok(c) = md.created() {
|
||||||
val: utc.with_timezone(utc.offset()),
|
if let Some(local) = try_convert_to_local_date_time(c) {
|
||||||
span,
|
val = Value::Date {
|
||||||
});
|
val: local.with_timezone(local.offset()),
|
||||||
} else {
|
span,
|
||||||
vals.push(Value::nothing(span));
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
vals.push(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
cols.push("accessed".to_string());
|
cols.push("accessed".to_string());
|
||||||
if let Ok(a) = md.accessed() {
|
{
|
||||||
let utc: DateTime<Local> = a.into();
|
let mut val = Value::nothing(span);
|
||||||
vals.push(Value::Date {
|
if let Ok(a) = md.accessed() {
|
||||||
val: utc.with_timezone(utc.offset()),
|
if let Some(local) = try_convert_to_local_date_time(a) {
|
||||||
span,
|
val = Value::Date {
|
||||||
});
|
val: local.with_timezone(local.offset()),
|
||||||
} else {
|
span,
|
||||||
vals.push(Value::nothing(span));
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
vals.push(val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cols.push("modified".to_string());
|
cols.push("modified".to_string());
|
||||||
if let Ok(m) = md.modified() {
|
{
|
||||||
let utc: DateTime<Local> = m.into();
|
let mut val = Value::nothing(span);
|
||||||
vals.push(Value::Date {
|
if let Ok(m) = md.modified() {
|
||||||
val: utc.with_timezone(utc.offset()),
|
if let Some(local) = try_convert_to_local_date_time(m) {
|
||||||
span,
|
val = Value::Date {
|
||||||
});
|
val: local.with_timezone(local.offset()),
|
||||||
} else {
|
span,
|
||||||
vals.push(Value::nothing(span));
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
vals.push(val);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if long {
|
if long {
|
||||||
|
@ -536,3 +546,25 @@ pub(crate) fn dir_entry_dict(
|
||||||
|
|
||||||
Ok(Value::Record { cols, vals, span })
|
Ok(Value::Record { cols, vals, span })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn try_convert_to_local_date_time(t: SystemTime) -> Option<DateTime<Local>> {
|
||||||
|
// Adapted from https://github.com/chronotope/chrono/blob/v0.4.19/src/datetime.rs#L755-L767.
|
||||||
|
let (sec, nsec) = match t.duration_since(UNIX_EPOCH) {
|
||||||
|
Ok(dur) => (dur.as_secs() as i64, dur.subsec_nanos()),
|
||||||
|
Err(e) => {
|
||||||
|
// unlikely but should be handled
|
||||||
|
let dur = e.duration();
|
||||||
|
let (sec, nsec) = (dur.as_secs() as i64, dur.subsec_nanos());
|
||||||
|
if nsec == 0 {
|
||||||
|
(-sec, 0)
|
||||||
|
} else {
|
||||||
|
(-sec - 1, 1_000_000_000 - nsec)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
match Utc.timestamp_opt(sec, nsec) {
|
||||||
|
LocalResult::Single(t) => Some(t.with_timezone(&Local)),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue