Eu tenho esse código em C++20 funcionando bem no MSVC. No entanto, minha versão do GCC não suporta fuso horário, então eu queria usar a biblioteca Howard Hinnant.
#include <chrono>
using LocalTime = std::chrono::time_point<std::chrono::local_t, std::chrono::system_clock::duration>;
//using LocalTime = std::chrono::local_time<std::chrono::system_clock::duration>;
using UtcTime = std::chrono::time_point<std::chrono::system_clock>;
LocalTime UtcToLocal(UtcTime t)
{
auto tz = std::chrono::current_zone();
LocalTime tLocal = tz->to_local(t);
return tLocal;
}
UtcTime LocalToUtc(LocalTime t)
{
auto tz = chronoExt::current_zone();
UtcTime tUtc = tz->to_sys(t);
return tUtc;
}
Se eu mudar o código para:
#include "tz.h"
#include "date.h"
LocalTime UtcToLocal(UtcTime t)
{
auto tz = date::current_zone();
LocalTime tLocal = tz->to_local(t);
return tLocal;
}
UtcTime LocalToUtc(LocalTime t)
{
auto tz = date::current_zone();
UtcTime tUtc = tz->to_sys(t);
return tUtc;
}
No MSVC recebi erros:
error C2440: 'initializing': cannot convert from 'std::chrono::time_point<date::local_t,std::chrono::duration<std::chrono::system_clock::rep,std::chrono::system_clock::period>>' to 'std::chrono::time_point<std::chrono::local_t,std::chrono::system_clock::duration>'
message : No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called
error C2672: 'date::time_zone::to_sys': no matching overloaded function found
message : could be 'std::chrono::time_point<std::chrono::system_clock,common_type<_Duration,std::chrono::seconds>::type> date::time_zone::to_sys(std::chrono::time_point<date::local_t,Duration>,date::choose) const'
message : 'std::chrono::time_point<std::chrono::system_clock,common_type<_Duration,std::chrono::seconds>::type> date::time_zone::to_sys(std::chrono::time_point<date::local_t,Duration>,date::choose) const': expects 2 arguments - 1 provided
message : or 'std::chrono::time_point<std::chrono::system_clock,common_type<_Duration,std::chrono::seconds>::type> date::time_zone::to_sys(std::chrono::time_point<date::local_t,Duration>) const'
message : 'std::chrono::time_point<std::chrono::system_clock,common_type<_Duration,std::chrono::seconds>::type> date::time_zone::to_sys(std::chrono::time_point<date::local_t,Duration>) const': could not deduce template argument for 'std::chrono::time_point<date::local_t,Duration>' from 'LocalTime'
Eu recomendo algo assim:
Ou seja,
#define USE_DATE_LIB 1
(ou0
) para informar ao compilador em qual namespace procurar os chrono bits do C++ 20. No uso do MSVCUSE_DATE_LIB = 0
e no gcc (antes de 14) useUSE_DATE_LIB = 1
.Então você pode dizer:
E as coisas deveriam funcionar.
É possível fazer com que a biblioteca de datas de Howard Hinnant funcione em C++ 20 tanto no msvc quanto no gcc. Existem algumas vantagens, por exemplo, se você quiser ter certeza de que possui o mesmo banco de dados de fuso horário no Windows e no Linux (ou se sua caixa do Windows não for recente o suficiente para suportar o banco de dados de fuso horário) e, obviamente, se você não conseguir atualizar ao gcc mais recente por motivos corporativos. No entanto, se possível, recomendo atualizar para o gcc13 - eu fiz isso e tudo funciona no Windows e no Linux :).
Para que a biblioteca de datas funcione, você precisa ter muito cuidado com o que escolher em qual biblioteca (ou seja, de quais bits vêm
date
e de quaisstd::chrono
). Eu recomendo importar o que você precisastd::chrono
para odates
namespace e, em seguida, usar odates
namespace em todo o seu código. No seu caso, especificamente,local_t
precisa vir dedate
notstd::chrono
. Ou sejaPara fazer com que seu programa seja compilado com/sem datas.h, configurei uma compilação condicional
(Observe também que se você usar o recurso de inserção ostream muito útil da biblioteca de HH, a linha
return (os << sys_time<Duration>{ut.time_since_epoch()});
poderá ser relatada como ambígua no Visual C++, caso em que poderá ser alterada parareturn date::operator<<(os, sys_time<Duration>{ut.time_since_epoch()});
.)