mirror of
https://github.com/nushell/nushell.git
synced 2025-06-19 17:38:14 +02:00
wip: nano second working and error handling
This commit is contained in:
parent
12a1eefe73
commit
4587c8c9d4
12
Cargo.lock
generated
12
Cargo.lock
generated
@ -206,9 +206,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "array-init-cursor"
|
name = "array-init-cursor"
|
||||||
version = "0.2.1"
|
version = "0.2.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ed51fe0f224d1d4ea768be38c51f9f831dee9d05c163c11fba0b8c44387b1fc3"
|
checksum = "bf7d0a018de4f6aa429b9d33d69edf69072b1c5b1cb8d3e4a5f7ef898fc3eb76"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "arrayref"
|
name = "arrayref"
|
||||||
@ -4488,9 +4488,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "openssl"
|
name = "openssl"
|
||||||
version = "0.10.72"
|
version = "0.10.70"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "fedfea7d58a1f73118430a55da6a286e7b044961736ce96a16a17068ea25e5da"
|
checksum = "61cfb4e166a8bb8c9b55c500bc2308550148ece889be90f609377e58140f42c6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 2.6.0",
|
"bitflags 2.6.0",
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
@ -4529,9 +4529,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "openssl-sys"
|
name = "openssl-sys"
|
||||||
version = "0.9.107"
|
version = "0.9.105"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8288979acd84749c744a9014b4382d42b8f7b2592847b5afb2ed29e5d16ede07"
|
checksum = "8b22d5b84be05a8d6947c7cb71f7c849aa0f112acd4bf51c2a7c1c988ac0a9dc"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cc",
|
"cc",
|
||||||
"libc",
|
"libc",
|
||||||
|
@ -1,9 +1,20 @@
|
|||||||
use crate::{generate_strftime_list, parse_date_from_string};
|
use crate::{generate_strftime_list, parse_date_from_string};
|
||||||
use chrono::{DateTime, FixedOffset, Local, NaiveDateTime, TimeZone, Utc};
|
use chrono::{DateTime, FixedOffset, Local, NaiveDate, NaiveDateTime, NaiveTime, TimeZone, Utc};
|
||||||
use nu_cmd_base::input_handler::{operate, CmdArgument};
|
|
||||||
use nu_engine::command_prelude::*;
|
use nu_engine::command_prelude::*;
|
||||||
|
|
||||||
const HOUR: i32 = 60 * 60;
|
const HOUR: i32 = 60 * 60;
|
||||||
|
const ALLOWED_COLUMNS: [&str; 10] = [
|
||||||
|
"year",
|
||||||
|
"month",
|
||||||
|
"day",
|
||||||
|
"hour",
|
||||||
|
"minute",
|
||||||
|
"second",
|
||||||
|
"millisecond",
|
||||||
|
"microsecond",
|
||||||
|
"nanosecond",
|
||||||
|
"timezone",
|
||||||
|
];
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
struct Arguments {
|
struct Arguments {
|
||||||
@ -255,7 +266,86 @@ impl Command for IntoDatetime {
|
|||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
struct DatetimeFormat(String);
|
struct DatetimeFormat(String);
|
||||||
|
|
||||||
|
fn merge_record(record: &Record, head: Span, span: Span) -> Value {
|
||||||
|
for key in record.columns() {
|
||||||
|
if !ALLOWED_COLUMNS.contains(&key.as_str()) {
|
||||||
|
let allowed_cols = ALLOWED_COLUMNS.join(", ");
|
||||||
|
return Value::error(ShellError::UnsupportedInput {
|
||||||
|
msg: format!(
|
||||||
|
"Column '{key}' is not valid for a structured datetime. Allowed columns are: {allowed_cols}"
|
||||||
|
),
|
||||||
|
input: "value originates from here".into(),
|
||||||
|
msg_span: head,
|
||||||
|
input_span: span
|
||||||
|
},
|
||||||
|
span,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let nanosecond: u32 = match record.get("nanosecond") {
|
||||||
|
Some(val) => match val {
|
||||||
|
Value::Int { val, .. } => {
|
||||||
|
dbg!(val);
|
||||||
|
if *val < 0 || *val > u32::MAX as i64 {
|
||||||
|
return Value::error(
|
||||||
|
ShellError::IncorrectValue {
|
||||||
|
msg: "incorrect value for nanosecond".to_string(),
|
||||||
|
val_span: head,
|
||||||
|
call_span: span,
|
||||||
|
},
|
||||||
|
span,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
*val as u32
|
||||||
|
}
|
||||||
|
other => {
|
||||||
|
dbg!(other);
|
||||||
|
return Value::error(
|
||||||
|
ShellError::OnlySupportsThisInputType {
|
||||||
|
exp_input_type: "record<int>".to_string(),
|
||||||
|
wrong_type: other.get_type().to_string(),
|
||||||
|
dst_span: head,
|
||||||
|
src_span: other.span(),
|
||||||
|
},
|
||||||
|
span,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
None => 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
dbg!(&nanosecond);
|
||||||
|
|
||||||
|
let timezone = "+01:00";
|
||||||
|
|
||||||
|
let date = NaiveDate::from_ymd_opt(2025, 1, 1).unwrap();
|
||||||
|
let time = match NaiveTime::from_hms_nano_opt(0, 0, 0, nanosecond) {
|
||||||
|
Some(d) => d,
|
||||||
|
None => {
|
||||||
|
return Value::error(
|
||||||
|
ShellError::IncorrectValue {
|
||||||
|
msg: "one of more values are incorrect and do not represent valid date time"
|
||||||
|
.to_string(),
|
||||||
|
val_span: head,
|
||||||
|
call_span: span,
|
||||||
|
},
|
||||||
|
span,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let datetime = NaiveDateTime::new(date, time);
|
||||||
|
|
||||||
|
let offset: FixedOffset = timezone
|
||||||
|
.parse()
|
||||||
|
.unwrap_or(FixedOffset::east_opt(0).unwrap()); // TODO return error instead
|
||||||
|
|
||||||
|
let datetime_with_timezone = DateTime::from_naive_utc_and_offset(datetime, offset);
|
||||||
|
Value::date(datetime_with_timezone, span)
|
||||||
|
}
|
||||||
|
|
||||||
fn action(input: &Value, args: &Arguments, head: Span) -> Value {
|
fn action(input: &Value, args: &Arguments, head: Span) -> Value {
|
||||||
|
dbg!(input, args);
|
||||||
let timezone = &args.zone_options;
|
let timezone = &args.zone_options;
|
||||||
let dateformat = &args.format_options;
|
let dateformat = &args.format_options;
|
||||||
|
|
||||||
@ -264,6 +354,45 @@ fn action(input: &Value, args: &Arguments, head: Span) -> Value {
|
|||||||
return input.clone();
|
return input.clone();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Value::Record {
|
||||||
|
val: record,
|
||||||
|
internal_span,
|
||||||
|
} = input
|
||||||
|
{
|
||||||
|
match timezone {
|
||||||
|
None => (),
|
||||||
|
Some(tz) => {
|
||||||
|
return Value::error(
|
||||||
|
ShellError::IncompatibleParameters {
|
||||||
|
left_message: "left message".into(),
|
||||||
|
left_span: head,
|
||||||
|
right_message: "right message".into(),
|
||||||
|
right_span: tz.span,
|
||||||
|
},
|
||||||
|
head,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// TODO
|
||||||
|
// match dateformat {
|
||||||
|
// None => (),
|
||||||
|
// Some(dt) => {
|
||||||
|
// return Value::error(
|
||||||
|
// ShellError::IncompatibleParameters {
|
||||||
|
// left_message: "left message".into(),
|
||||||
|
// left_span: head,
|
||||||
|
// right_message: "right message".into(),
|
||||||
|
// right_span: dt,
|
||||||
|
// },
|
||||||
|
// head,
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
dbg!(input);
|
||||||
|
return merge_record(record, head, *internal_span);
|
||||||
|
}
|
||||||
|
|
||||||
// Let's try dtparse first
|
// Let's try dtparse first
|
||||||
if matches!(input, Value::String { .. }) && dateformat.is_none() {
|
if matches!(input, Value::String { .. }) && dateformat.is_none() {
|
||||||
let span = input.span();
|
let span = input.span();
|
||||||
@ -281,6 +410,7 @@ fn action(input: &Value, args: &Arguments, head: Span) -> Value {
|
|||||||
// Propagate errors by explicitly matching them before the final case.
|
// Propagate errors by explicitly matching them before the final case.
|
||||||
Value::Error { .. } => return input.clone(),
|
Value::Error { .. } => return input.clone(),
|
||||||
other => {
|
other => {
|
||||||
|
dbg!(other);
|
||||||
return Value::error(
|
return Value::error(
|
||||||
ShellError::OnlySupportsThisInputType {
|
ShellError::OnlySupportsThisInputType {
|
||||||
exp_input_type: "string and int".into(),
|
exp_input_type: "string and int".into(),
|
||||||
@ -432,6 +562,7 @@ fn action(input: &Value, args: &Arguments, head: Span) -> Value {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
dbg!(input);
|
||||||
match input {
|
match input {
|
||||||
Value::String { val, .. } => parse_as_string(val),
|
Value::String { val, .. } => parse_as_string(val),
|
||||||
Value::Int { val, .. } => parse_as_string(&val.to_string()),
|
Value::Int { val, .. } => parse_as_string(&val.to_string()),
|
||||||
|
@ -1,5 +1,15 @@
|
|||||||
use nu_test_support::nu;
|
use nu_test_support::nu;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn into_datetime_from_record() {
|
||||||
|
let actual = nu!(
|
||||||
|
r#"{year: 2023, month: 1, day: 1, hour: 0, minute: 0, second: 0, millisecond: 0, microsecond: 0, nanosecond: 0, timezone: "+01:00"} | into datetime"#
|
||||||
|
);
|
||||||
|
let expected = nu!(r#"'01/01/2023' | into datetime"#);
|
||||||
|
|
||||||
|
assert_eq!(expected.out, actual.out);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn into_datetime_table_column() {
|
fn into_datetime_table_column() {
|
||||||
let actual = nu!(r#"[[date]; ["2022-01-01"] ["2023-01-01"]] | into datetime date"#);
|
let actual = nu!(r#"[[date]; ["2022-01-01"] ["2023-01-01"]] | into datetime date"#);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user