mirror of
https://github.com/nushell/nushell
synced 2024-11-10 15:14:14 +00:00
Add string to datetime to str plugin (#1381)
* Add string to datetime to str plugin * Test string to date/time conversion
This commit is contained in:
parent
84927d52b5
commit
0961da406d
6 changed files with 70 additions and 20 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -2555,6 +2555,7 @@ dependencies = [
|
||||||
name = "nu_plugin_str"
|
name = "nu_plugin_str"
|
||||||
version = "0.9.0"
|
version = "0.9.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"chrono",
|
||||||
"nu-build",
|
"nu-build",
|
||||||
"nu-errors",
|
"nu-errors",
|
||||||
"nu-plugin",
|
"nu-plugin",
|
||||||
|
|
|
@ -15,6 +15,7 @@ use crate::value::primitive::Primitive;
|
||||||
use crate::value::range::{Range, RangeInclusion};
|
use crate::value::range::{Range, RangeInclusion};
|
||||||
use crate::{ColumnPath, PathMember};
|
use crate::{ColumnPath, PathMember};
|
||||||
use bigdecimal::BigDecimal;
|
use bigdecimal::BigDecimal;
|
||||||
|
use chrono::{DateTime, Utc};
|
||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
use nu_errors::ShellError;
|
use nu_errors::ShellError;
|
||||||
use nu_source::{AnchorLocation, HasSpan, Span, Spanned, Tag};
|
use nu_source::{AnchorLocation, HasSpan, Span, Spanned, Tag};
|
||||||
|
@ -201,6 +202,10 @@ impl UntaggedValue {
|
||||||
UntaggedValue::Primitive(Primitive::Date(s.into()))
|
UntaggedValue::Primitive(Primitive::Date(s.into()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn date(d: impl Into<DateTime<Utc>>) -> UntaggedValue {
|
||||||
|
UntaggedValue::Primitive(Primitive::Date(d.into()))
|
||||||
|
}
|
||||||
|
|
||||||
/// Helper for creating the Nothing value
|
/// Helper for creating the Nothing value
|
||||||
pub fn nothing() -> UntaggedValue {
|
pub fn nothing() -> UntaggedValue {
|
||||||
UntaggedValue::Primitive(Primitive::Nothing)
|
UntaggedValue::Primitive(Primitive::Nothing)
|
||||||
|
|
|
@ -15,6 +15,7 @@ nu-protocol = { path = "../nu-protocol", version = "0.9.0" }
|
||||||
nu-source = { path = "../nu-source", version = "0.9.0" }
|
nu-source = { path = "../nu-source", version = "0.9.0" }
|
||||||
nu-errors = { path = "../nu-errors", version = "0.9.0" }
|
nu-errors = { path = "../nu-errors", version = "0.9.0" }
|
||||||
nu-value-ext = { path = "../nu-value-ext", version = "0.9.0" }
|
nu-value-ext = { path = "../nu-value-ext", version = "0.9.0" }
|
||||||
|
chrono = { version = "0.4.10", features = ["serde"] }
|
||||||
|
|
||||||
regex = "1"
|
regex = "1"
|
||||||
num-bigint = "0.2.3"
|
num-bigint = "0.2.3"
|
||||||
|
|
|
@ -36,6 +36,12 @@ impl Plugin for Str {
|
||||||
"convert string to portion of original, requires \"start,end\"",
|
"convert string to portion of original, requires \"start,end\"",
|
||||||
Some('s'),
|
Some('s'),
|
||||||
)
|
)
|
||||||
|
.named(
|
||||||
|
"to-date-time",
|
||||||
|
SyntaxShape::String,
|
||||||
|
"Convert string to Date/Time",
|
||||||
|
Some('D'),
|
||||||
|
)
|
||||||
.rest(SyntaxShape::ColumnPath, "the column(s) to convert")
|
.rest(SyntaxShape::ColumnPath, "the column(s) to convert")
|
||||||
.filter())
|
.filter())
|
||||||
}
|
}
|
||||||
|
@ -117,6 +123,11 @@ impl Plugin for Str {
|
||||||
self.for_field(possible_field);
|
self.for_field(possible_field);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(dt) = args.get("to-date-time") {
|
||||||
|
let dt = dt.as_string()?;
|
||||||
|
self.for_date_time(dt);
|
||||||
|
}
|
||||||
|
|
||||||
match &self.error {
|
match &self.error {
|
||||||
Some(reason) => Err(ShellError::untagged_runtime_error(format!(
|
Some(reason) => Err(ShellError::untagged_runtime_error(format!(
|
||||||
"{}: {}",
|
"{}: {}",
|
||||||
|
|
|
@ -7,7 +7,37 @@ mod integration {
|
||||||
unstructured_sample_record,
|
unstructured_sample_record,
|
||||||
};
|
};
|
||||||
use nu_plugin::test_helpers::{expect_return_value_at, plugin, CallStub};
|
use nu_plugin::test_helpers::{expect_return_value_at, plugin, CallStub};
|
||||||
use nu_protocol::UntaggedValue;
|
use nu_protocol::{Primitive, UntaggedValue};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn picks_up_date_time() {
|
||||||
|
let run = plugin(&mut Str::new())
|
||||||
|
.args(
|
||||||
|
CallStub::new()
|
||||||
|
.with_named_parameter("to-date-time", string("%d.%m.%Y %H:%M %P %z"))
|
||||||
|
.create(),
|
||||||
|
)
|
||||||
|
.input(string("5.8.1994 8:00 am +0000"))
|
||||||
|
.input(string("6.9.1995 10:00 am +0000"))
|
||||||
|
.input(string("5.8.1994 20:00 pm +0000"))
|
||||||
|
.input(string("20.4.2020 8:00 am +0000"))
|
||||||
|
.setup(|_, _| {})
|
||||||
|
.test();
|
||||||
|
let ret_vals = run.unwrap();
|
||||||
|
for r in ret_vals {
|
||||||
|
let r = r
|
||||||
|
.as_ref()
|
||||||
|
.unwrap()
|
||||||
|
.raw_value()
|
||||||
|
.unwrap()
|
||||||
|
.as_primitive()
|
||||||
|
.unwrap();
|
||||||
|
match r {
|
||||||
|
Primitive::Date(_) => (),
|
||||||
|
_ => assert!(false, "failed to convert string to date"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn picks_up_one_action_flag_only() {
|
fn picks_up_one_action_flag_only() {
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
extern crate chrono;
|
||||||
|
|
||||||
|
use chrono::DateTime;
|
||||||
use nu_errors::ShellError;
|
use nu_errors::ShellError;
|
||||||
use nu_protocol::{did_you_mean, ColumnPath, Primitive, ShellTypeName, UntaggedValue, Value};
|
use nu_protocol::{did_you_mean, ColumnPath, Primitive, ShellTypeName, UntaggedValue, Value};
|
||||||
use nu_source::{span_for_spanned_list, Tagged};
|
use nu_source::{span_for_spanned_list, Tagged};
|
||||||
|
@ -12,6 +15,7 @@ pub enum Action {
|
||||||
ToInteger,
|
ToInteger,
|
||||||
Substring(usize, usize),
|
Substring(usize, usize),
|
||||||
Replace(ReplaceAction),
|
Replace(ReplaceAction),
|
||||||
|
ToDateTime(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Eq, PartialEq)]
|
#[derive(Debug, Eq, PartialEq)]
|
||||||
|
@ -70,6 +74,10 @@ impl Str {
|
||||||
Err(_) => UntaggedValue::string(input),
|
Err(_) => UntaggedValue::string(input),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
Some(Action::ToDateTime(dt)) => match DateTime::parse_from_str(input, dt) {
|
||||||
|
Ok(d) => UntaggedValue::date(d),
|
||||||
|
Err(_) => UntaggedValue::string(input),
|
||||||
|
},
|
||||||
None => UntaggedValue::string(input),
|
None => UntaggedValue::string(input),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -89,27 +97,15 @@ impl Str {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn for_to_int(&mut self) {
|
pub fn for_to_int(&mut self) {
|
||||||
if self.permit() {
|
self.add_action(Action::ToInteger);
|
||||||
self.action = Some(Action::ToInteger);
|
|
||||||
} else {
|
|
||||||
self.log_error("can only apply one");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn for_downcase(&mut self) {
|
pub fn for_downcase(&mut self) {
|
||||||
if self.permit() {
|
self.add_action(Action::Downcase);
|
||||||
self.action = Some(Action::Downcase);
|
|
||||||
} else {
|
|
||||||
self.log_error("can only apply one");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn for_upcase(&mut self) {
|
pub fn for_upcase(&mut self) {
|
||||||
if self.permit() {
|
self.add_action(Action::Upcase);
|
||||||
self.action = Some(Action::Upcase);
|
|
||||||
} else {
|
|
||||||
self.log_error("can only apply one");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn for_substring(&mut self, s: String) -> Result<(), ShellError> {
|
pub fn for_substring(&mut self, s: String) -> Result<(), ShellError> {
|
||||||
|
@ -130,18 +126,24 @@ impl Str {
|
||||||
};
|
};
|
||||||
if start > end {
|
if start > end {
|
||||||
self.log_error("End must be greater than or equal to Start");
|
self.log_error("End must be greater than or equal to Start");
|
||||||
} else if self.permit() {
|
|
||||||
self.action = Some(Action::Substring(start, end));
|
|
||||||
} else {
|
} else {
|
||||||
self.log_error("can only apply one");
|
self.add_action(Action::Substring(start, end));
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn for_replace(&mut self, mode: ReplaceAction) {
|
pub fn for_replace(&mut self, mode: ReplaceAction) {
|
||||||
|
self.add_action(Action::Replace(mode));
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn for_date_time(&mut self, dt: String) {
|
||||||
|
self.add_action(Action::ToDateTime(dt));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn add_action(&mut self, act: Action) {
|
||||||
if self.permit() {
|
if self.permit() {
|
||||||
self.action = Some(Action::Replace(mode));
|
self.action = Some(act);
|
||||||
} else {
|
} else {
|
||||||
self.log_error("can only apply one");
|
self.log_error("can only apply one");
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue