nu_command/date/
humanize.rs1use crate::date::utils::parse_date_from_string;
2use chrono::{DateTime, FixedOffset, Local};
3use nu_engine::command_prelude::*;
4
5#[derive(Clone)]
6pub struct DateHumanize;
7
8impl Command for DateHumanize {
9 fn name(&self) -> &str {
10 "date humanize"
11 }
12
13 fn signature(&self) -> Signature {
14 Signature::build("date humanize")
15 .input_output_types(vec![
16 (Type::Date, Type::String),
17 (Type::String, Type::String),
18 (
19 Type::List(Box::new(Type::Date)),
20 Type::List(Box::new(Type::String)),
21 ),
22 (
23 Type::List(Box::new(Type::String)),
24 Type::List(Box::new(Type::String)),
25 ),
26 ])
27 .allow_variants_without_examples(true)
28 .category(Category::Date)
29 }
30
31 fn description(&self) -> &str {
32 "Print a 'humanized' format for the date, relative to now."
33 }
34
35 fn search_terms(&self) -> Vec<&str> {
36 vec![
37 "relative",
38 "now",
39 "today",
40 "tomorrow",
41 "yesterday",
42 "weekday",
43 "weekday_name",
44 "timezone",
45 ]
46 }
47
48 fn run(
49 &self,
50 engine_state: &EngineState,
51 _stack: &mut Stack,
52 call: &Call,
53 input: PipelineData,
54 ) -> Result<PipelineData, ShellError> {
55 let head = call.head;
56 if let PipelineData::Empty = input {
58 return Err(ShellError::PipelineEmpty { dst_span: head });
59 }
60 input.map(move |value| helper(value, head), engine_state.signals())
61 }
62
63 fn examples(&self) -> Vec<Example<'_>> {
64 vec![
65 Example {
66 description: "Print a 'humanized' format for the date, relative to now.",
67 example: r#""2021-10-22 20:00:12 +01:00" | date humanize"#,
68 result: None,
69 },
70 Example {
71 description: "Humanize a list of datetimes.",
72 example: "[2021-10-22T20:00:12+01:00, 2021-10-23T20:00:00+01:00] | date humanize",
73 result: None,
74 },
75 Example {
76 description: "Humanize a list of date strings.",
77 example: r#"["2021-10-22 20:00:12 +01:00", "2021-10-22 21:00:00 +01:00"] | date humanize"#,
78 result: None,
79 },
80 ]
81 }
82}
83
84fn helper(value: Value, head: Span) -> Value {
85 let span = value.span();
86 match value {
87 Value::Nothing { .. } => {
88 let dt = Local::now();
89 Value::string(humanize_date(dt.with_timezone(dt.offset())), head)
90 }
91 Value::String { val, .. } => {
92 let dt = parse_date_from_string(&val, span);
93 match dt {
94 Ok(x) => Value::string(humanize_date(x), head),
95 Err(e) => e,
96 }
97 }
98 Value::Date { val, .. } => Value::string(humanize_date(val), head),
99 _ => Value::error(
100 ShellError::OnlySupportsThisInputType {
101 exp_input_type: "date, string (that represents datetime), or nothing".into(),
102 wrong_type: value.get_type().to_string(),
103 dst_span: head,
104 src_span: span,
105 },
106 head,
107 ),
108 }
109}
110
111fn humanize_date(dt: DateTime<FixedOffset>) -> String {
112 nu_protocol::human_time_from_now(&dt).to_string()
113}
114
115#[cfg(test)]
116mod test {
117 use super::*;
118
119 #[test]
120 fn test_examples() -> nu_test_support::Result {
121 nu_test_support::test().examples(DateHumanize)
122 }
123}