Home > Net >  How to Convert excel Date into Year, month and date component or NaiveDate?
How to Convert excel Date into Year, month and date component or NaiveDate?

Time:01-31

I'm using rust and chrono::NaiveDate to read an Excel file with date column type in it.

The date itself is formatted with "dd-mm-yyyy"

I can read the excel file and found out that the reader I use (https://docs.rs/calamine/latest/calamine/) returns float value for the date

A documentation in Microsoft site states that the date starts from January 1st, 1900

The float value in it corresponds to this dates:

date_value (FLOAT) real value (in dd-mm-yyyy)
44198 02-01-2021
44199 03-01-2021
44200 04-01-2021
etc...

Basically I need a function or crate that can calculate month, date, and years from the float value I get. I have no clue on how to do this.

Below is my code

let data_type = calamine::DataType::deserialize(deserializer);
    match data_type {
        Ok(DataType::Error(_)) => {
            Ok(None)
        }
        Ok(DataType::String(date_str)) => {
            let msg = "Failed to convert Date. Wrong format or empty.";
            let val = NaiveDate::parse_from_str(&date_str, DATE_FORMAT)
                .map_err(|_| Error::custom(msg))?;
            Ok(Some(val))
        }
        Ok(DataType::Float(dt)) => {
            println!("this is float!!!");
            println!("dt: {}", dt); // dt is a float number that count the number of days from January 1st 1900
            let year  = ? // what should I do here ?
            let month = ?
            let day = ?
            let val = NaiveDate::from_ymd_opt(year, month, day)
            Ok(None)
        }
        _ => {
            Ok(None)
        }
    }

CodePudding user response:

calamine has a dates feature that adds a DataType.as_date() method returning an Option<chrono::NaiveDate>. There are also DataType.as_datetime() and DataType.as_time().

I don't know why it isn't documented, so use carefully.

At least, the method code could be a starting point for your own implementation.

CodePudding user response:

A possible solution regarding my comment would be:

use chrono::{Duration, NaiveDate};

fn main() {
    let start = NaiveDate::from_ymd(1900, 1, 1);
    let date = start.checked_add_signed(Duration::days(44198));  // date_value
    println!("{}", date.unwrap());
}

There is a newer function as substitute for from_ymd().

  • Related