## 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/current_date.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
    use std::any::Any;
    19
    20
    use arrow::array::timezone::Tz;
    21
    use arrow::datatypes::DataType;
    22
    use arrow::datatypes::DataType::Date32;
    23
    use chrono::{Datelike, NaiveDate, TimeZone};
    24
    25
    use datafusion_common::{internal_err, Result, ScalarValue};
    26
    use datafusion_expr::simplify::{ExprSimplifyResult, SimplifyInfo};
    27
    use datafusion_expr::{
    28
        ColumnarValue, Documentation, Expr, ScalarUDFImpl, Signature, Volatility,
    29
    };
    30
    use datafusion_macros::user_doc;
    31
    32
    #[user_doc(
    33
        doc_section(label = "Time and Date Functions"),
    34
        description = r#"
    35
    Returns the current date in the session time zone.
    36
    37
    The `current_date()` return value is determined at query time and will return the same date, no matter when in the query plan the function executes.
    38
    "#,
    39
        syntax_example = r#"current_date()
    40
        (optional) SET datafusion.execution.time_zone = '+00:00';
    41
        SELECT current_date();"#
    42
    )]
    43
    #[derive(Debug, PartialEq, Eq, Hash)]
    44
    pub struct CurrentDateFunc {
    45
        signature: Signature,
    46
        aliases: Vec<String>,
    47
    }
    48
    49
    impl Default for CurrentDateFunc {
    50
    0
        fn default() -> Self {
    51
    0
            Self::new()
    52
    0
        }
    53
    }
    54
    55
    impl CurrentDateFunc {
    56
    0
        pub fn new() -> Self {
    57
    0
            Self {
    58
    0
                signature: Signature::nullary(Volatility::Stable),
    59
    0
                aliases: vec![String::from("today")],
    60
    0
            }
    61
    0
        }
    62
    }
    63
    64
    /// Create an implementation of `current_date()` that always returns the
    65
    /// specified current date.
    66
    ///
    67
    /// The semantics of `current_date()` require it to return the same value
    68
    /// wherever it appears within a single statement. This value is
    69
    /// chosen during planning time.
    70
    impl ScalarUDFImpl for CurrentDateFunc {
    71
    0
        fn as_any(&self) -> &dyn Any {
    72
    0
            self
    73
    0
        }
    74
    75
    0
        fn name(&self) -> &str {
    76
    0
            "current_date"
    77
    0
        }
    78
    79
    0
        fn signature(&self) -> &Signature {
    80
    0
            &self.signature
    81
    0
        }
    82
    83
    0
        fn return_type(&self, _arg_types: &[DataType]) -> Result<DataType> {
    84
    0
            Ok(Date32)
    85
    0
        }
    86
    87
    0
        fn invoke_with_args(
    88
    0
            &self,
    89
    0
            _args: datafusion_expr::ScalarFunctionArgs,
    90
    0
        ) -> Result<ColumnarValue> {
    91
    0
            internal_err!(
    92
    0
                "invoke should not be called on a simplified current_date() function"
    93
            )
    94
    0
        }
    95
    96
    0
        fn aliases(&self) -> &[String] {
    97
    0
            &self.aliases
    98
    0
        }
    99
    100
    0
        fn simplify(
    101
    0
            &self,
    102
    0
            _args: Vec<Expr>,
    103
    0
            info: &dyn SimplifyInfo,
    104
    0
        ) -> Result<ExprSimplifyResult> {
    105
    0
            let now_ts = info.execution_props().query_execution_start_time;
    106
    107
            // Get timezone from config and convert to local time
    108
    0
            let days = info
    109
    0
                .execution_props()
    110
    0
                .config_options()
    111
    0
                .and_then(|config| {
    112
    0
                    config
    113
    0
                        .execution
    114
    0
                        .time_zone
    115
    0
                        .as_ref()
    116
    0
                        .map(|tz| tz.parse::<Tz>().ok())
    117
    0
                })
    118
    0
                .flatten()
    119
    0
                .map_or_else(
    120
    0
                    || datetime_to_days(&now_ts),
    121
    0
                    |tz| {
    122
    0
                        let local_now = tz.from_utc_datetime(&now_ts.naive_utc());
    123
    0
                        datetime_to_days(&local_now)
    124
    0
                    },
    125
                );
    126
    0
            Ok(ExprSimplifyResult::Simplified(Expr::Literal(
    127
    0
                ScalarValue::Date32(Some(days)),
    128
    0
                None,
    129
    0
            )))
    130
    0
        }
    131
    132
    0
        fn documentation(&self) -> Option<&Documentation> {
    133
    0
            self.doc()
    134
    0
        }
    135
    }
    136
    137
    /// Converts a DateTime to the number of days since Unix epoch (1970-01-01)
    138
    0
    fn datetime_to_days<T: Datelike>(dt: &T) -> i32 {
    139
    0
        dt.num_days_from_ce()
    140
    0
            - NaiveDate::from_ymd_opt(1970, 1, 1)
    141
    0
                .unwrap()
    142
    0
                .num_days_from_ce()
    143
    0
    }