c++string-conversionxlnt

xlnt library : date to std::string conversion error


With xlnt library:

How to convert a date value to std::string ?

const auto vdate = cell.value<xlnt::date>(); 
    
std::string vdates = std::string(vdate);

I get :

error: no matching function for call to ‘std::__cxx11::basic_string<char>::basic_string(const xlnt::date&)’
 4259 |                         std::string vdates = std::string(vdate);

    
error: no matching function for call to ‘std::__cxx11::basic_string<char>::basic_string(const xlnt::date&)’
 4259 |                         std::string vdates = static_cast<std::string>(vdate);

Solution

  • Although xlnt::cell has a number of formatting options

    cell.number_format(xlnt::number_format::date_yyyymmdd2()); // example
    

    they seem to only affect the visual appearance in Excel and does not affect the outcome when using for example

    std::string vdates = cell.to_string();
    // or
    std::cout << cell << '\n';
    

    but instead shows an integer number representing the date.

    xlnt::date is a rather simple placeholder for three ints and doesn't seem to support any kind of formatting either directly or by helper functions.


    I would therefore convert xlnt::date to std::chrono::year_month_day and do all the work in the chrono domain. If needed, convert the result back to xlnt::date.

    Conversion functions could look like this:

    #include <xlnt/xlnt.hpp>
    #include <chrono>
    
    std::chrono::year_month_day xlnt2chrono(const xlnt::date& in) {
        if(in.is_null()) {
            // Extracting year/month/day from xlnt::date
            // will throw an exception if you do that when is_null()
            // is true. If you want that behavior, just remove this:
            return {}; // 0000-00-00
        }
        return std::chrono::year_month_day(
            std::chrono::year(in.get_year()),
            std::chrono::month(static_cast<unsigned>(in.get_month())),
            std::chrono::day(static_cast<unsigned>(in.get_day())));
    }
    
    xlnt::date chrono2xlnt(const std::chrono::year_month_day& in) {
        return xlnt::date(static_cast<int>(in.year()),
                          static_cast<int>(static_cast<unsigned>(in.month())),
                          static_cast<int>(static_cast<unsigned>(in.day())));
    }
    

    Note: The cast to unsigned in chrono2xlnt is to extract the numeric month and day and the cast to int is to provide it to xlnt::date without getting warnings.

    When you then have a std::chrono::year_month_day formatting it to your pleasure is just a matter of specifying the format to std::format which will then use the formatter std::formatter<std::chrono::year_month_day>.

    Example:

    #include <format>
    #include <string>
    
    //...
    
    const auto vdate = cell.value<xlnt::date>();
    
    std::string vdates = std::format("{:%Y-%m-%d}", xlnt2chrono(vdate)); // YYYY-mm-dd