diff --git a/crates/nu-cli/src/cli.rs b/crates/nu-cli/src/cli.rs
index 65abe93a7..530bfa179 100644
--- a/crates/nu-cli/src/cli.rs
+++ b/crates/nu-cli/src/cli.rs
@@ -298,6 +298,7 @@ pub fn create_default_context(
             whole_stream_command(Prepend),
             whole_stream_command(SortBy),
             whole_stream_command(GroupBy),
+            whole_stream_command(GroupByDate),
             whole_stream_command(First),
             whole_stream_command(Last),
             whole_stream_command(Nth),
diff --git a/crates/nu-cli/src/commands.rs b/crates/nu-cli/src/commands.rs
index 8e1b4fec2..0b7ef21f7 100644
--- a/crates/nu-cli/src/commands.rs
+++ b/crates/nu-cli/src/commands.rs
@@ -50,6 +50,7 @@ pub(crate) mod from_xml;
 pub(crate) mod from_yaml;
 pub(crate) mod get;
 pub(crate) mod group_by;
+pub(crate) mod group_by_date;
 pub(crate) mod headers;
 pub(crate) mod help;
 pub(crate) mod histogram;
@@ -178,6 +179,7 @@ pub(crate) use from_yaml::FromYAML;
 pub(crate) use from_yaml::FromYML;
 pub(crate) use get::Get;
 pub(crate) use group_by::GroupBy;
+pub(crate) use group_by_date::GroupByDate;
 pub(crate) use headers::Headers;
 pub(crate) use help::Help;
 pub(crate) use histogram::Histogram;
diff --git a/crates/nu-cli/src/commands/group_by.rs b/crates/nu-cli/src/commands/group_by.rs
index 2ce86f392..235365c06 100644
--- a/crates/nu-cli/src/commands/group_by.rs
+++ b/crates/nu-cli/src/commands/group_by.rs
@@ -8,9 +8,7 @@ pub struct GroupBy;
 
 #[derive(Deserialize)]
 pub struct GroupByArgs {
-    column_name: Tagged<String>,
-    date: Tagged<bool>,
-    format: Option<Tagged<String>>,
+    column_name: Option<Tagged<String>>,
 }
 
 impl WholeStreamCommand for GroupBy {
@@ -19,19 +17,11 @@ impl WholeStreamCommand for GroupBy {
     }
 
     fn signature(&self) -> Signature {
-        Signature::build("group-by")
-            .required(
-                "column_name",
-                SyntaxShape::String,
-                "the name of the column to group by",
-            )
-            .named(
-                "format",
-                SyntaxShape::String,
-                "Specify date and time formatting",
-                Some('f'),
-            )
-            .switch("date", "by date", Some('d'))
+        Signature::build("group-by").optional(
+            "column_name",
+            SyntaxShape::String,
+            "the name of the column to group by",
+        )
     }
 
     fn usage(&self) -> &str {
@@ -54,17 +44,8 @@ impl WholeStreamCommand for GroupBy {
     }
 }
 
-enum Grouper {
-    Default,
-    ByDate(Option<String>),
-}
-
 pub fn group_by(
-    GroupByArgs {
-        column_name,
-        date,
-        format,
-    }: GroupByArgs,
+    GroupByArgs { column_name }: GroupByArgs,
     RunnableContext { input, name, .. }: RunnableContext,
 ) -> Result<OutputStream, ShellError> {
     let stream = async_stream! {
@@ -74,42 +55,15 @@ pub fn group_by(
             yield Err(ShellError::labeled_error(
                     "Expected table from pipeline",
                     "requires a table input",
-                    column_name.span()
+                    name
                 ))
         } else {
 
-            let grouper = if let Tagged { item: true, tag } = date {
-                if let Some(Tagged { item: fmt, tag }) = format {
-                    Grouper::ByDate(Some(fmt))
-                } else {
-                    Grouper::ByDate(None)
-                }
-            } else {
-                Grouper::Default
-            };
-
-            match grouper {
-                Grouper::Default => {
-                    match crate::utils::data::group(column_name, &values, None, &name) {
-                        Ok(grouped) => yield ReturnSuccess::value(grouped),
-                        Err(err) => yield Err(err),
-                    }
-                }
-                Grouper::ByDate(None) => {
-                    match crate::utils::data::group(column_name, &values, Some(Box::new(|row: &Value| row.format("%Y-%b-%d"))), &name) {
-                        Ok(grouped) => yield ReturnSuccess::value(grouped),
-                        Err(err) => yield Err(err),
-                    }
-                }
-                Grouper::ByDate(Some(fmt)) => {
-                    match crate::utils::data::group(column_name, &values, Some(Box::new(move |row: &Value| {
-                        row.format(&fmt)
-                    })), &name) {
-                        Ok(grouped) => yield ReturnSuccess::value(grouped),
-                        Err(err) => yield Err(err),
-                    }
-                }
+            match crate::utils::data::group(column_name, &values, None, &name) {
+                Ok(grouped) => yield ReturnSuccess::value(grouped),
+                Err(err) => yield Err(err),
             }
+
         }
     };
 
@@ -121,7 +75,7 @@ pub fn group(
     values: Vec<Value>,
     tag: impl Into<Tag>,
 ) -> Result<Value, ShellError> {
-    crate::utils::data::group(column_name.clone(), &values, None, tag)
+    crate::utils::data::group(Some(column_name.clone()), &values, None, tag)
 }
 
 #[cfg(test)]
diff --git a/crates/nu-cli/src/commands/group_by_date.rs b/crates/nu-cli/src/commands/group_by_date.rs
new file mode 100644
index 000000000..2bdae9f99
--- /dev/null
+++ b/crates/nu-cli/src/commands/group_by_date.rs
@@ -0,0 +1,103 @@
+use crate::commands::WholeStreamCommand;
+use crate::prelude::*;
+use nu_errors::ShellError;
+use nu_protocol::{ReturnSuccess, Signature, SyntaxShape, Value};
+use nu_source::Tagged;
+
+pub struct GroupByDate;
+
+#[derive(Deserialize)]
+pub struct GroupByDateArgs {
+    column_name: Option<Tagged<String>>,
+    format: Option<Tagged<String>>,
+}
+
+impl WholeStreamCommand for GroupByDate {
+    fn name(&self) -> &str {
+        "group-by date"
+    }
+
+    fn signature(&self) -> Signature {
+        Signature::build("group-by date")
+            .optional(
+                "column_name",
+                SyntaxShape::String,
+                "the name of the column to group by",
+            )
+            .named(
+                "format",
+                SyntaxShape::String,
+                "Specify date and time formatting",
+                Some('f'),
+            )
+    }
+
+    fn usage(&self) -> &str {
+        "Creates a new table with the data from the table rows grouped by the column given."
+    }
+
+    fn run(
+        &self,
+        args: CommandArgs,
+        registry: &CommandRegistry,
+    ) -> Result<OutputStream, ShellError> {
+        args.process(registry, group_by_date)?.run()
+    }
+
+    fn examples(&self) -> &[Example] {
+        &[Example {
+            description: "Group files by type",
+            example: "ls | group-by date --fmt '%d/%m/%Y'",
+        }]
+    }
+}
+
+enum Grouper {
+    ByDate(Option<String>),
+}
+
+pub fn group_by_date(
+    GroupByDateArgs {
+        column_name,
+        format,
+    }: GroupByDateArgs,
+    RunnableContext { input, name, .. }: RunnableContext,
+) -> Result<OutputStream, ShellError> {
+    let stream = async_stream! {
+        let values: Vec<Value> = input.collect().await;
+
+        if values.is_empty() {
+            yield Err(ShellError::labeled_error(
+                    "Expected table from pipeline",
+                    "requires a table input",
+                    name
+                ))
+        } else {
+
+            let grouper = if let Some(Tagged { item: fmt, tag }) = format {
+                    Grouper::ByDate(Some(fmt))
+                } else {
+                    Grouper::ByDate(None)
+                };
+
+            match grouper {
+                Grouper::ByDate(None) => {
+                    match crate::utils::data::group(column_name, &values, Some(Box::new(|row: &Value| row.format("%Y-%b-%d"))), &name) {
+                        Ok(grouped) => yield ReturnSuccess::value(grouped),
+                        Err(err) => yield Err(err),
+                    }
+                }
+                Grouper::ByDate(Some(fmt)) => {
+                    match crate::utils::data::group(column_name, &values, Some(Box::new(move |row: &Value| {
+                        row.format(&fmt)
+                    })), &name) {
+                        Ok(grouped) => yield ReturnSuccess::value(grouped),
+                        Err(err) => yield Err(err),
+                    }
+                }
+            }
+        }
+    };
+
+    Ok(stream.to_output_stream())
+}
diff --git a/crates/nu-cli/src/utils/data/group.rs b/crates/nu-cli/src/utils/data/group.rs
index 3c468033a..e7b6161e0 100644
--- a/crates/nu-cli/src/utils/data/group.rs
+++ b/crates/nu-cli/src/utils/data/group.rs
@@ -1,12 +1,12 @@
 use indexmap::IndexMap;
 use nu_errors::ShellError;
 use nu_protocol::{TaggedDictBuilder, UntaggedValue, Value};
-use nu_source::{Tag, Tagged};
+use nu_source::{Tag, Tagged, TaggedItem};
 use nu_value_ext::{as_string, get_data_by_key};
 
 #[allow(clippy::type_complexity)]
 pub fn group(
-    column_name: Tagged<String>,
+    column_name: Option<Tagged<String>>,
     values: &[Value],
     grouper: Option<Box<dyn Fn(&Value) -> Result<String, ShellError> + Send>>,
     tag: impl Into<Tag>,
@@ -16,7 +16,11 @@ pub fn group(
     let mut groups: IndexMap<String, Vec<Value>> = IndexMap::new();
 
     for value in values {
-        let group_key = get_data_by_key(&value, column_name.borrow_spanned());
+        let group_key = if let Some(ref column_name) = column_name {
+            get_data_by_key(&value, column_name.borrow_spanned())
+        } else {
+            Some(value.clone())
+        };
 
         if let Some(group_key) = group_key {
             let group_key = if let Some(ref grouper) = grouper {
@@ -27,6 +31,8 @@ pub fn group(
             let group = groups.entry(group_key?).or_insert(vec![]);
             group.push((*value).clone());
         } else {
+            let column_name = column_name.unwrap_or_else(|| String::from("").tagged(&tag));
+
             let possibilities = value.data_descriptors();
 
             let mut possible_matches: Vec<_> = possibilities
diff --git a/crates/nu-value-ext/src/lib.rs b/crates/nu-value-ext/src/lib.rs
index 6f76d8212..6c0f79db9 100644
--- a/crates/nu-value-ext/src/lib.rs
+++ b/crates/nu-value-ext/src/lib.rs
@@ -392,6 +392,7 @@ pub fn as_path_member(value: &Value) -> Result<PathMember, ShellError> {
 pub fn as_string(value: &Value) -> Result<String, ShellError> {
     match &value.value {
         UntaggedValue::Primitive(Primitive::String(s)) => Ok(s.clone()),
+        UntaggedValue::Primitive(Primitive::Date(dt)) => Ok(dt.format("%Y-%b-%d").to_string()),
         UntaggedValue::Primitive(Primitive::Boolean(x)) => Ok(format!("{}", x)),
         UntaggedValue::Primitive(Primitive::Decimal(x)) => Ok(format!("{}", x)),
         UntaggedValue::Primitive(Primitive::Int(x)) => Ok(format!("{}", x)),