Repository: tikv/tikv
File: components/tidb_query_expr/src/impl_time.rs (Rust)

Code before:
    let day = time.day();
    let hour = time.hour();
    let minute = time.minute();
    let second = time.second();
    let naive_date = chrono::NaiveDate::from_ymd(year, month, day);
    let naive_time = chrono::NaiveTime::from_hms_micro(hour, minute, second, time.micro());
    let naive_datetime = chrono::NaiveDateTime::new(naive_date, naive_time);

    // MySQL chooses earliest time when there are multi mapped time
    let res_opt = tz.from_local_datetime(&naive_datetime).earliest();
    let res = match res_opt {
        Some(val) => val,
        None => {
            let tz_opt = tz.get_chrono_tz();
            let chrono_tz = match tz_opt {
                Some(val) => val,
                None => return Err(Error::incorrect_parameters("Can't get chrono tz").into()),
            };

            // year, month, day, hour, minute and second is enough
            let time_with_tz = chrono::Utc
                .ymd(year, month, day)
                .and_hms(hour, minute, second)
                .with_timezone(&chrono_tz);
            let ret_res = find_zone_transition(time_with_tz);
            match ret_res {
                Ok(val) => return Ok(val.naive_utc().timestamp_micros()),
                Err(err) => return Err(err),
            }
        }
    };
    return Ok(res.naive_utc().timestamp_micros());
}

#[rpn_fn(capture = [ctx])]
#[inline]
pub fn unix_timestamp_int(ctx: &mut EvalContext, time: &DateTime) -> Result<Option<i64>> {
    let timestamp_res = get_micro_timestamp(time, &ctx.cfg.tz);
    let timestamp = match timestamp_res {
        Ok(val) => val,
        Err(err) => return Err(err),
    };

    let res: std::result::Result<i64, Error> =
        unix_timestamp_to_mysql_unix_timestamp(ctx, timestamp, 1)?
            .as_i64()
            .into();
    Ok(Some(res?))
}

#[rpn_fn(capture = [ctx, extra])]

Review comment (suggestion):
```suggestion
            match find_zone_transition(time_with_tz) {
```

Code after:
fn get_micro_timestamp(time: &DateTime, tz: &Tz) -> Result<i64> {
    let year = time.year() as i32;
    let month = time.month();
    let day = time.day();
    let hour = time.hour();
    let minute = time.minute();
    let second = time.second();
    let naive_date = chrono::NaiveDate::from_ymd(year, month, day);
    let naive_time = chrono::NaiveTime::from_hms_micro(hour, minute, second, time.micro());
    let naive_datetime = chrono::NaiveDateTime::new(naive_date, naive_time);

    // MySQL chooses earliest time when there are multi mapped time
    let res = match tz.from_local_datetime(&naive_datetime).earliest() {
        Some(val) => val,
        None => {
            let chrono_tz = match tz.get_chrono_tz() {
                Some(val) => val,
                None => return Err(Error::incorrect_parameters("Can't get chrono tz").into()),
            };

            // year, month, day, hour, minute and second is enough
            let time_with_tz = chrono::Utc
                .ymd(year, month, day)
                .and_hms(hour, minute, second)
                .with_timezone(&chrono_tz);
            match find_zone_transition(time_with_tz) {
                Ok(val) => return Ok(val.naive_utc().timestamp_micros()),
                Err(err) => return Err(err),
            }
        }
    };
    Ok(res.naive_utc().timestamp_micros())
}

#[rpn_fn(capture = [ctx])]
#[inline]
pub fn unix_timestamp_int(ctx: &mut EvalContext, time: &DateTime) -> Result<Option<i64>> {
    let timestamp = match get_micro_timestamp(time, &ctx.cfg.tz) {
        Ok(val) => val,
        Err(err) => return Err(err),
    };

    let res: std::result::Result<i64, Error> =
        unix_timestamp_to_mysql_unix_timestamp(ctx, timestamp, 1)?
            .as_i64()
            .into();
    Ok(Some(res?))
}

#[rpn_fn(capture = [ctx, extra])]
#[inline]