@@ -54,7 +54,8 @@ use datafusion_common::cast::{
5454 as_timestamp_nanosecond_array, as_timestamp_second_array,
5555} ;
5656use datafusion_common:: {
57- exec_err, not_impl_err, DataFusionError , Result , ScalarType , ScalarValue ,
57+ exec_err, internal_datafusion_err, internal_err, not_impl_err, DataFusionError ,
58+ Result , ScalarType , ScalarValue ,
5859} ;
5960use datafusion_expr:: ColumnarValue ;
6061
@@ -424,6 +425,84 @@ fn to_timestamp_impl<T: ArrowTimestampType + ScalarType<i64>>(
424425 }
425426}
426427
428+ /// # Examples
429+ ///
430+ /// ```
431+ /// use std::sync::Arc;
432+
433+ /// use datafusion::arrow::array::StringArray;
434+ /// use datafusion::arrow::datatypes::{DataType, Field, Schema};
435+ /// use datafusion::arrow::record_batch::RecordBatch;
436+ /// use datafusion::error::Result;
437+ /// use datafusion::prelude::*;
438+
439+ /// #[tokio::main]
440+ /// async fn main() -> Result<()> {
441+ /// // define a schema.
442+ /// let schema = Arc::new(Schema::new(vec![Field::new("a", DataType::Utf8, false)]));
443+
444+ /// // define data.
445+ /// let batch = RecordBatch::try_new(
446+ /// schema,
447+ /// vec![Arc::new(StringArray::from(vec![
448+ /// "2020-09-08T13:42:29Z",
449+ /// "2020-09-08T13:42:29.190855-05:00",
450+ /// "2020-08-09 12:13:29",
451+ /// "2020-01-02",
452+ /// ]))],
453+ /// )?;
454+
455+ /// // declare a new context. In spark API, this corresponds to a new spark SQLsession
456+ /// let ctx = SessionContext::new();
457+
458+ /// // declare a table in memory. In spark API, this corresponds to createDataFrame(...).
459+ /// ctx.register_batch("t", batch)?;
460+ /// let df = ctx.table("t").await?;
461+
462+ /// // use to_timestamp function to convert col 'a' to timestamp type using the default parsing
463+ /// let df = df.with_column("a", to_date(vec![col("a")]))?;
464+
465+ /// let df = df.select_columns(&["a"])?;
466+
467+ /// // print the results
468+ /// df.show().await?;
469+
470+ /// Ok(())
471+ /// }
472+ /// ```
473+ pub fn to_date ( args : & [ ColumnarValue ] ) -> Result < ColumnarValue > {
474+ match args. len ( ) {
475+ 1 => handle :: < Date32Type , _ , Date32Type > (
476+ args,
477+ |s| {
478+ string_to_timestamp_nanos_shim ( s)
479+ . map ( |n| n / ( 1_000_000 * 24 * 60 * 60 * 1_000 ) )
480+ . and_then ( |v| {
481+ v. try_into ( ) . map_err ( |_| {
482+ internal_datafusion_err ! ( "Unable to cast to Date32 for converting from i64 to i32 failed" )
483+ } )
484+ } )
485+ } ,
486+ "to_date" ,
487+ ) ,
488+ n if n >= 2 => handle_multiple :: < Date32Type , _ , Date32Type , _ > (
489+ args,
490+ |s, format| {
491+ string_to_timestamp_nanos_formatted ( s, format)
492+ . map ( |n| n / ( 1_000_000 * 24 * 60 * 60 * 1_000 ) )
493+ . and_then ( |v| {
494+ v. try_into ( ) . map_err ( |_| {
495+ internal_datafusion_err ! ( "Unable to cast to Date32 for converting from i64 to i32 failed" )
496+ } )
497+ } )
498+ } ,
499+ |n| n,
500+ "to_date" ,
501+ ) ,
502+ _ => internal_err ! ( "Unsupported 0 argument count for function to_date" ) ,
503+ }
504+ }
505+
427506/// to_timestamp SQL function
428507///
429508/// Note: `to_timestamp` returns `Timestamp(Nanosecond)` though its arguments are interpreted as **seconds**.
@@ -1567,6 +1646,36 @@ fn validate_to_timestamp_data_types(
15671646 None
15681647}
15691648
1649+ /// to_date SQL function implementation
1650+ pub fn to_date_invoke ( args : & [ ColumnarValue ] ) -> Result < ColumnarValue > {
1651+ if args. is_empty ( ) {
1652+ return exec_err ! (
1653+ "to_date function requires 1 or more arguments, got {}" ,
1654+ args. len( )
1655+ ) ;
1656+ }
1657+
1658+ // validate that any args after the first one are Utf8
1659+ if args. len ( ) > 1 {
1660+ if let Some ( value) = validate_to_timestamp_data_types ( args, "to_date" ) {
1661+ return value;
1662+ }
1663+ }
1664+
1665+ match args[ 0 ] . data_type ( ) {
1666+ DataType :: Int32
1667+ | DataType :: Int64
1668+ | DataType :: Null
1669+ | DataType :: Float64
1670+ | DataType :: Date32
1671+ | DataType :: Date64 => cast_column ( & args[ 0 ] , & DataType :: Date32 , None ) ,
1672+ DataType :: Utf8 => to_date ( args) ,
1673+ other => {
1674+ internal_err ! ( "Unsupported data type {:?} for function to_date" , other)
1675+ }
1676+ }
1677+ }
1678+
15701679/// to_timestamp() SQL function implementation
15711680pub fn to_timestamp_invoke ( args : & [ ColumnarValue ] ) -> Result < ColumnarValue > {
15721681 if args. is_empty ( ) {
0 commit comments