## Coverage Report

#### Created: 2025-11-22 06:00

next uncovered line (L), next uncovered region (R), next uncovered branch (B)

    /Users/andrewlamb/Software/datafusion/datafusion/functions/src/datetime/mod.rs

    Line
    Count
    Source
    1
    // Licensed to the Apache Software Foundation (ASF) under one
    2
    // or more contributor license agreements.  See the NOTICE file
    3
    // distributed with this work for additional information
    4
    // regarding copyright ownership.  The ASF licenses this file
    5
    // to you under the Apache License, Version 2.0 (the
    6
    // "License"); you may not use this file except in compliance
    7
    // with the License.  You may obtain a copy of the License at
    8
    //
    9
    //   http://www.apache.org/licenses/LICENSE-2.0
    10
    //
    11
    // Unless required by applicable law or agreed to in writing,
    12
    // software distributed under the License is distributed on an
    13
    // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    14
    // KIND, either express or implied.  See the License for the
    15
    // specific language governing permissions and limitations
    16
    // under the License.
    17
    18
    //! date & time DataFusion functions
    19
    20
    use std::sync::Arc;
    21
    22
    use datafusion_expr::ScalarUDF;
    23
    24
    pub mod common;
    25
    pub mod current_date;
    26
    pub mod current_time;
    27
    pub mod date_bin;
    28
    pub mod date_part;
    29
    pub mod date_trunc;
    30
    pub mod from_unixtime;
    31
    pub mod make_date;
    32
    pub mod now;
    33
    pub mod planner;
    34
    pub mod to_char;
    35
    pub mod to_date;
    36
    pub mod to_local_time;
    37
    pub mod to_timestamp;
    38
    pub mod to_unixtime;
    39
    40
    // create UDFs
    41
    make_udf_function!(current_date::CurrentDateFunc, current_date);
    42
    make_udf_function!(current_time::CurrentTimeFunc, current_time);
    43
    make_udf_function!(date_bin::DateBinFunc, date_bin);
    44
    make_udf_function!(date_part::DatePartFunc, date_part);
    45
    make_udf_function!(date_trunc::DateTruncFunc, date_trunc);
    46
    make_udf_function!(make_date::MakeDateFunc, make_date);
    47
    make_udf_function!(from_unixtime::FromUnixtimeFunc, from_unixtime);
    48
    make_udf_function!(to_char::ToCharFunc, to_char);
    49
    make_udf_function!(to_date::ToDateFunc, to_date);
    50
    make_udf_function!(to_local_time::ToLocalTimeFunc, to_local_time);
    51
    make_udf_function!(to_unixtime::ToUnixtimeFunc, to_unixtime);
    52
    make_udf_function!(to_timestamp::ToTimestampFunc, to_timestamp);
    53
    make_udf_function!(to_timestamp::ToTimestampSecondsFunc, to_timestamp_seconds);
    54
    make_udf_function!(to_timestamp::ToTimestampMillisFunc, to_timestamp_millis);
    55
    make_udf_function!(to_timestamp::ToTimestampMicrosFunc, to_timestamp_micros);
    56
    make_udf_function!(to_timestamp::ToTimestampNanosFunc, to_timestamp_nanos);
    57
    58
    // create UDF with config
    59
    make_udf_function_with_config!(now::NowFunc, now);
    60
    61
    // we cannot currently use the export_functions macro since it doesn't handle
    62
    // functions with varargs currently
    63
    64
    pub mod expr_fn {
    65
        use datafusion_expr::Expr;
    66
    67
        export_functions!((
    68
            current_date,
    69
            "returns current UTC date as a Date32 value",
    70
        ),(
    71
            current_time,
    72
            "returns current UTC time as a Time64 value",
    73
        ),(
    74
            from_unixtime,
    75
            "converts an integer to RFC3339 timestamp format string",
    76
            unixtime
    77
        ),(
    78
            date_bin,
    79
            "coerces an arbitrary timestamp to the start of the nearest specified interval",
    80
            stride source origin
    81
        ),(
    82
            date_part,
    83
            "extracts a subfield from the date",
    84
            part date
    85
        ),(
    86
            date_trunc,
    87
            "truncates the date to a specified level of precision",
    88
            part date
    89
        ),(
    90
            make_date,
    91
            "make a date from year, month and day component parts",
    92
            year month day
    93
        ),(
    94
            now,
    95
            "returns the current timestamp in nanoseconds, using the same value for all instances of now() in same statement",
    96
            @config
    97
        ),
    98
        (
    99
            to_local_time,
    100
            "converts a timezone-aware timestamp to local time (with no offset or timezone information), i.e. strips off the timezone from the timestamp",
    101
            args,
    102
        ),
    103
        (
    104
            to_unixtime,
    105
            "converts a string and optional formats to a Unixtime",
    106
            args,
    107
        ),(
    108
            to_timestamp,
    109
            "converts a string and optional formats to a `Timestamp(Nanoseconds, None)`",
    110
            args,
    111
        ),(
    112
            to_timestamp_seconds,
    113
            "converts a string and optional formats to a `Timestamp(Seconds, None)`",
    114
            args,
    115
        ),(
    116
            to_timestamp_millis,
    117
            "converts a string and optional formats to a `Timestamp(Milliseconds, None)`",
    118
            args,
    119
        ),(
    120
            to_timestamp_micros,
    121
            "converts a string and optional formats to a `Timestamp(Microseconds, None)`",
    122
            args,
    123
        ),(
    124
            to_timestamp_nanos,
    125
            "converts a string and optional formats to a `Timestamp(Nanoseconds, None)`",
    126
            args,
    127
        ));
    128
    129
        /// Returns a string representation of a date, time, timestamp or duration based
    130
        /// on a Chrono pattern.
    131
        ///
    132
        /// The syntax for the patterns can be found at
    133
        /// <https://docs.rs/chrono/latest/chrono/format/strftime/index.html>
    134
        ///
    135
        /// # Examples
    136
        ///
    137
        /// ```ignore
    138
        /// # use chrono::prelude::*;
    139
        /// # use datafusion::prelude::*;
    140
        /// # use datafusion::error::Result;
    141
        /// # use datafusion_common::ScalarValue::TimestampNanosecond;
    142
        /// # use std::sync::Arc;
    143
        /// # use arrow::array::{Date32Array, RecordBatch, StringArray};
    144
        /// # use arrow::datatypes::{DataType, Field, Schema};
    145
        /// # #[tokio::main]
    146
        /// # async fn main() -> Result<()> {
    147
        /// let schema = Arc::new(Schema::new(vec![
    148
        ///     Field::new("values", DataType::Date32, false),
    149
        ///     Field::new("patterns", DataType::Utf8, false),
    150
        /// ]));
    151
        ///
    152
        /// let batch = RecordBatch::try_new(
    153
        ///     schema,
    154
        ///     vec![
    155
        ///         Arc::new(Date32Array::from(vec![
    156
        ///             18506,
    157
        ///             18507,
    158
        ///             18508,
    159
        ///             18509,
    160
        ///         ])),
    161
        ///         Arc::new(StringArray::from(vec![
    162
        ///             "%Y-%m-%d",
    163
        ///             "%Y:%m:%d",
    164
        ///             "%Y%m%d",
    165
        ///             "%d-%m-%Y",
    166
        ///         ])),
    167
        ///     ],
    168
        /// )?;
    169
        ///
    170
        /// let ctx = SessionContext::new();
    171
        /// ctx.register_batch("t", batch)?;
    172
        /// let df = ctx.table("t").await?;
    173
        ///
    174
        /// // use the to_char function to convert col 'values',
    175
        /// // to strings using patterns in col 'patterns'
    176
        /// let df = df.with_column(
    177
        ///     "date_str",
    178
        ///     to_char(col("values"), col("patterns"))
    179
        /// )?;
    180
        /// // Note that providing a scalar value for the pattern
    181
        /// // is more performant
    182
        /// let df = df.with_column(
    183
        ///     "date_str2",
    184
        ///     to_char(col("values"), lit("%d-%m-%Y"))
    185
        /// )?;
    186
        /// // literals can be used as well with dataframe calls
    187
        /// let timestamp = "2026-07-08T09:10:11"
    188
        ///     .parse::<NaiveDateTime>()
    189
        ///     .unwrap()
    190
        ///     .with_nanosecond(56789)
    191
        ///     .unwrap()
    192
        ///     .timestamp_nanos_opt()
    193
        ///     .unwrap();
    194
        /// let df = df.with_column(
    195
        ///     "timestamp_str",
    196
        ///     to_char(lit(TimestampNanosecond(Some(timestamp), None)), lit("%d-%m-%Y %H:%M:%S"))
    197
        /// )?;
    198
        ///
    199
        /// df.show().await?;
    200
        ///
    201
        /// # Ok(())
    202
        /// # }
    203
        /// ```
    204
        pub fn to_char(datetime: Expr, format: Expr) -> Expr {
    205
            super::to_char().call(vec![datetime, format])
    206
        }
    207
    208
        /// ```ignore
    209
        /// # use std::sync::Arc;
    210
        ///
    211
        /// # use datafusion_common::Result;
    212
        ///
    213
        /// # #[tokio::main]
    214
        /// # async fn main() -> Result<()> {
    215
        /// #  use arrow::array::StringArray;
    216
        /// #  use arrow::datatypes::{DataType, Field, Schema};
    217
        /// #  use arrow::record_batch::RecordBatch;
    218
        /// #  use datafusion_expr::col;
    219
        /// #  use datafusion::prelude::*;
    220
        /// #  use datafusion_functions::expr_fn::to_date;
    221
        ///
    222
        ///     // define a schema.
    223
        ///     let schema = Arc::new(Schema::new(vec![Field::new("a", DataType::Utf8, false)]));
    224
        ///
    225
        ///     // define data.
    226
        ///     let batch = RecordBatch::try_new(
    227
        ///         schema,
    228
        ///         vec![Arc::new(StringArray::from(vec![
    229
        ///             "2020-09-08T13:42:29Z",
    230
        ///             "2020-09-08T13:42:29.190855-05:00",
    231
        ///             "2020-08-09 12:13:29",
    232
        ///             "2020-01-02",
    233
        ///         ]))],
    234
        ///     )?;
    235
        ///
    236
        ///     // declare a new context. In spark API, this corresponds to a new spark SQLsession
    237
        ///     let ctx = SessionContext::new();
    238
        ///
    239
        ///     // declare a table in memory. In spark API, this corresponds to createDataFrame(...).
    240
        ///     ctx.register_batch("t", batch)?;
    241
        ///     let df = ctx.table("t").await?;
    242
        ///
    243
        ///     // use to_date function to convert col 'a' to timestamp type using the default parsing
    244
        ///     let df = df.with_column("a", to_date(vec![col("a")]))?;
    245
        ///
    246
        ///     let df = df.select_columns(&["a"])?;
    247
        ///
    248
        ///     // print the results
    249
        ///     df.show().await?;
    250
        ///
    251
        ///     # Ok(())
    252
        /// # }
    253
        /// ```
    254
        pub fn to_date(args: Vec<Expr>) -> Expr {
    255
            super::to_date().call(args)
    256
        }
    257
    }
    258
    259
    /// Returns all DataFusion functions defined in this package
    260
    0
    pub fn functions() -> Vec<Arc<ScalarUDF>> {
    261
        use datafusion_common::config::ConfigOptions;
    262
    0
        vec![
    263
    0
            current_date(),
    264
    0
            current_time(),
    265
    0
            date_bin(),
    266
    0
            date_part(),
    267
    0
            date_trunc(),
    268
    0
            from_unixtime(),
    269
    0
            make_date(),
    270
    0
            now(&ConfigOptions::default()),
    271
    0
            to_char(),
    272
    0
            to_date(),
    273
    0
            to_local_time(),
    274
    0
            to_unixtime(),
    275
    0
            to_timestamp(),
    276
    0
            to_timestamp_seconds(),
    277
    0
            to_timestamp_millis(),
    278
    0
            to_timestamp_micros(),
    279
    0
            to_timestamp_nanos(),
    280
        ]
    281
    0
    }