HowardHinnant / date

A date and time library based on the C++11/14/17 <chrono> header
Other
3.07k stars 669 forks source link

date::parse doesn't work in MSVC #792

Closed BenSleat closed 11 months ago

BenSleat commented 11 months ago

I've been trying to use the date::parse functions on MSVC (VS 2022) but I'm getting compilation errors saying that none of the overloads can be found. I've tried the example code from lots of sources, including those posted by Howard here:

In every case I get the same error about not being able to find the matching overload.

If I compile the same code using GCC it seems to work fine. Interestingly if I use std::chrono::parse on MSVC that works fine, so currently I'm having to use conditional compilation so that on MSVC I use std::chrono::parse and on GCC I use date::parse

I just wanted to check if this is expected, as I've not seen it mentioned anywhere despite extensive searching.

Kind Regards Ben

HowardHinnant commented 11 months ago

I'm not sure if it is expected or not because I would need to see example code along with the error message.

That being said, it is intended that people migrate from this library to std::chrono. So imho using std::chrono on MSVC is a good thing. And when gcc gets it all implemented, it would be good to use std::chrono there too.

BenSleat commented 11 months ago

Thanks Howard,

The example code (Taken from your top answer post here) is:

#include "date/date.h"
#include <iostream>
#include <sstream>

date::sys_time<std::chrono::milliseconds>
parse8601(std::istream&& is)
{
    std::string save;
    is >> save;
    std::istringstream in{save};
    date::sys_time<std::chrono::milliseconds> tp;
    in >> date::parse("%FT%TZ", tp);
    if (in.fail())
    {
        in.clear();
        in.exceptions(std::ios::failbit);
        in.str(save);
        in >> date::parse("%FT%T%Ez", tp);
    }
    return tp;
}

int
main()
{
    using namespace date;
    using namespace std;
    cout << parse8601(istringstream{ "2014-11-12T19:12:14.505Z" }) << '\n';
    cout << parse8601(istringstream{ "2014-11-12T12:12:14.505-5:00" }) << '\n';
}

And the compiler output on MSVC (VS 2022) is:

>------ Build All started: Project: CommonCpp, Configuration: x64-debug ------
  [1/2] Building CXX object tests\DateTimeUtils\CMakeFiles\DateTimeUtilsTests.dir\DateTimeUtilsTests.cpp.obj
  FAILED: tests/DateTimeUtils/CMakeFiles/DateTimeUtilsTests.dir/DateTimeUtilsTests.cpp.obj 
  C:\PROGRA~1\MIB055~1\2022\ENTERP~1\VC\Tools\MSVC\1436~1.325\bin\Hostx64\x64\cl.exe  /nologo /TP  -ID:\Projects\CommonCpp\out\build\x64-debug\_deps\fmt-src\include -ID:\Projects\CommonCpp\out\build\x64-debug\_deps\date-src\include -ID:\Projects\DateTimeUtils\..\..\include -external:ID:\Projects\CommonCpp\out\build\x64-debug\_deps\googletest-src\googletest\include -external:ID:\Projects\CommonCpp\out\build\x64-debug\_deps\googletest-src\googlemock\include -external:ID:\Projects\CommonCpp\out\build\x64-debug\_deps\googletest-src\googletest -external:ID:\Projects\CommonCpp\out\build\x64-debug\_deps\googletest-src\googlemock -external:W0 /DWIN32 /D_WINDOWS /EHsc /Zi /Ob0 /Od /RTC1 -std:c++20 -MDd /showIncludes /Fotests\DateTimeUtils\CMakeFiles\DateTimeUtilsTests.dir\DateTimeUtilsTests.cpp.obj /Fdtests\DateTimeUtils\CMakeFiles\DateTimeUtilsTests.dir\ /FS -c D:\Projects\DateTimeUtils\DateTimeUtilsTests.cpp
D:\Projects\DateTimeUtils\DateTimeUtilsTests.cpp(12): error C2672: 'date::parse': no matching overloaded function found
  D:\Projects\CommonCpp\out\build\x64-debug\_deps\date-src\include\date/date.h(8169): note: could be 'unknown-type date::parse(const CharT *,Parsable &,std::basic_string<CharT,Traits,Alloc> &,std::chrono::minutes &)'
  D:\Projects\DateTimeUtils\DateTimeUtilsTests.cpp(12): note: 'unknown-type date::parse(const CharT *,Parsable &,std::basic_string<CharT,Traits,Alloc> &,std::chrono::minutes &)': expects 4 arguments - 2 provided
  D:\Projects\CommonCpp\out\build\x64-debug\_deps\date-src\include\date/date.h(8158): note: or       'unknown-type date::parse(const CharT *,Parsable &,std::chrono::minutes &)'
  D:\Projects\DateTimeUtils\DateTimeUtilsTests.cpp(12): note: 'unknown-type date::parse(const CharT *,Parsable &,std::chrono::minutes &)': expects 3 arguments - 2 provided
  D:\Projects\CommonCpp\out\build\x64-debug\_deps\date-src\include\date/date.h(8147): note: or       'unknown-type date::parse(const CharT *,Parsable &,std::basic_string<CharT,Traits,Alloc> &)'
  D:\Projects\DateTimeUtils\DateTimeUtilsTests.cpp(12): note: 'unknown-type date::parse(const CharT *,Parsable &,std::basic_string<CharT,Traits,Alloc> &)': expects 3 arguments - 2 provided
  D:\Projects\CommonCpp\out\build\x64-debug\_deps\date-src\include\date/date.h(8137): note: or       'unknown-type date::parse(const CharT *,Parsable &)'
  D:\Projects\DateTimeUtils\DateTimeUtilsTests.cpp(12): note: Failed to specialize function template 'unknown-type date::parse(const CharT *,Parsable &)'
  D:\Projects\DateTimeUtils\DateTimeUtilsTests.cpp(12): note: With the following template arguments:
  D:\Projects\DateTimeUtils\DateTimeUtilsTests.cpp(12): note: 'Parsable=std::chrono::time_point<std::chrono::system_clock,std::chrono::milliseconds>'
  D:\Projects\DateTimeUtils\DateTimeUtilsTests.cpp(12): note: 'CharT=char'
  D:\Projects\CommonCpp\out\build\x64-debug\_deps\date-src\include\date/date.h(8123): note: or       'unknown-type date::parse(const std::basic_string<CharT,Traits,Alloc> &,Parsable &,std::basic_string<CharT,Traits,Alloc> &,std::chrono::minutes &)'
  D:\Projects\DateTimeUtils\DateTimeUtilsTests.cpp(12): note: 'unknown-type date::parse(const std::basic_string<CharT,Traits,Alloc> &,Parsable &,std::basic_string<CharT,Traits,Alloc> &,std::chrono::minutes &)': expects 4 arguments - 2 provided
  D:\Projects\CommonCpp\out\build\x64-debug\_deps\date-src\include\date/date.h(8109): note: or       'unknown-type date::parse(const std::basic_string<CharT,Traits,Alloc> &,Parsable &,std::chrono::minutes &)'
  D:\Projects\DateTimeUtils\DateTimeUtilsTests.cpp(12): note: 'unknown-type date::parse(const std::basic_string<CharT,Traits,Alloc> &,Parsable &,std::chrono::minutes &)': expects 3 arguments - 2 provided
  D:\Projects\CommonCpp\out\build\x64-debug\_deps\date-src\include\date/date.h(8097): note: or       'unknown-type date::parse(const std::basic_string<CharT,Traits,Alloc> &,Parsable &,std::basic_string<CharT,Traits,Alloc> &)'
  D:\Projects\DateTimeUtils\DateTimeUtilsTests.cpp(12): note: 'unknown-type date::parse(const std::basic_string<CharT,Traits,Alloc> &,Parsable &,std::basic_string<CharT,Traits,Alloc> &)': expects 3 arguments - 2 provided
  D:\Projects\CommonCpp\out\build\x64-debug\_deps\date-src\include\date/date.h(8086): note: or       'unknown-type date::parse(const std::basic_string<CharT,Traits,Alloc> &,Parsable &)'
  D:\Projects\DateTimeUtils\DateTimeUtilsTests.cpp(12): note: 'unknown-type date::parse(const std::basic_string<CharT,Traits,Alloc> &,Parsable &)': could not deduce template argument for 'const std::basic_string<CharT,Traits,Alloc> &' from 'const char [7]'
D:\Projects\DateTimeUtils\DateTimeUtilsTests.cpp(18): error C2672: 'date::parse': no matching overloaded function found
  D:\Projects\CommonCpp\out\build\x64-debug\_deps\date-src\include\date/date.h(8169): note: could be 'unknown-type date::parse(const CharT *,Parsable &,std::basic_string<CharT,Traits,Alloc> &,std::chrono::minutes &)'
  D:\Projects\DateTimeUtils\DateTimeUtilsTests.cpp(18): note: 'unknown-type date::parse(const CharT *,Parsable &,std::basic_string<CharT,Traits,Alloc> &,std::chrono::minutes &)': expects 4 arguments - 2 provided
  D:\Projects\CommonCpp\out\build\x64-debug\_deps\date-src\include\date/date.h(8158): note: or       'unknown-type date::parse(const CharT *,Parsable &,std::chrono::minutes &)'
  D:\Projects\DateTimeUtils\DateTimeUtilsTests.cpp(18): note: 'unknown-type date::parse(const CharT *,Parsable &,std::chrono::minutes &)': expects 3 arguments - 2 provided
  D:\Projects\CommonCpp\out\build\x64-debug\_deps\date-src\include\date/date.h(8147): note: or       'unknown-type date::parse(const CharT *,Parsable &,std::basic_string<CharT,Traits,Alloc> &)'
  D:\Projects\DateTimeUtils\DateTimeUtilsTests.cpp(18): note: 'unknown-type date::parse(const CharT *,Parsable &,std::basic_string<CharT,Traits,Alloc> &)': expects 3 arguments - 2 provided
  D:\Projects\CommonCpp\out\build\x64-debug\_deps\date-src\include\date/date.h(8137): note: or       'unknown-type date::parse(const CharT *,Parsable &)'
  D:\Projects\DateTimeUtils\DateTimeUtilsTests.cpp(18): note: Failed to specialize function template 'unknown-type date::parse(const CharT *,Parsable &)'
  D:\Projects\DateTimeUtils\DateTimeUtilsTests.cpp(18): note: With the following template arguments:
  D:\Projects\DateTimeUtils\DateTimeUtilsTests.cpp(18): note: 'Parsable=std::chrono::time_point<std::chrono::system_clock,std::chrono::milliseconds>'
  D:\Projects\DateTimeUtils\DateTimeUtilsTests.cpp(18): note: 'CharT=char'
  D:\Projects\CommonCpp\out\build\x64-debug\_deps\date-src\include\date/date.h(8123): note: or       'unknown-type date::parse(const std::basic_string<CharT,Traits,Alloc> &,Parsable &,std::basic_string<CharT,Traits,Alloc> &,std::chrono::minutes &)'
  D:\Projects\DateTimeUtils\DateTimeUtilsTests.cpp(18): note: 'unknown-type date::parse(const std::basic_string<CharT,Traits,Alloc> &,Parsable &,std::basic_string<CharT,Traits,Alloc> &,std::chrono::minutes &)': expects 4 arguments - 2 provided
  D:\Projects\CommonCpp\out\build\x64-debug\_deps\date-src\include\date/date.h(8109): note: or       'unknown-type date::parse(const std::basic_string<CharT,Traits,Alloc> &,Parsable &,std::chrono::minutes &)'
  D:\Projects\DateTimeUtils\DateTimeUtilsTests.cpp(18): note: 'unknown-type date::parse(const std::basic_string<CharT,Traits,Alloc> &,Parsable &,std::chrono::minutes &)': expects 3 arguments - 2 provided
  D:\Projects\CommonCpp\out\build\x64-debug\_deps\date-src\include\date/date.h(8097): note: or       'unknown-type date::parse(const std::basic_string<CharT,Traits,Alloc> &,Parsable &,std::basic_string<CharT,Traits,Alloc> &)'
  D:\Projects\DateTimeUtils\DateTimeUtilsTests.cpp(18): note: 'unknown-type date::parse(const std::basic_string<CharT,Traits,Alloc> &,Parsable &,std::basic_string<CharT,Traits,Alloc> &)': expects 3 arguments - 2 provided
  D:\Projects\CommonCpp\out\build\x64-debug\_deps\date-src\include\date/date.h(8086): note: or       'unknown-type date::parse(const std::basic_string<CharT,Traits,Alloc> &,Parsable &)'
  D:\Projects\DateTimeUtils\DateTimeUtilsTests.cpp(18): note: 'unknown-type date::parse(const std::basic_string<CharT,Traits,Alloc> &,Parsable &)': could not deduce template argument for 'const std::basic_string<CharT,Traits,Alloc> &' from 'const char [9]'
  ninja: build stopped: subcommand failed.

Build All failed.

Kind Regards Ben

HowardHinnant commented 11 months ago

That is most definitely disappointing. :-\ I can think of two workarounds, and of the two, I think you've already implemented the best one: use std::chrono::parse. The other workaround is to use date::from_stream:

date::from_stream(in, "%FT%TZ", tp);
BenSleat commented 11 months ago

Thank you Howard, much appreciated.