У меня проблема с использованием функции std :: localtime. Когда я преобразовываю std :: time_t в локальную структуру tm, она всегда использует американское летнее время, тогда как я хочу использовать европейское (Франция).
UTC: 19.03.16 16:56 преобразован в Локальный: 19.03.16 18:56.
На эту дату обычно местное время — 17:56 (UTC + 1). Летнее время происходит 27-го во Франции.
После нескольких испытаний кажется, что используемый DST основан на американском правиле: DST происходит во второе воскресенье марта.
Я также изменил переменную окружения TZ, но она также не работает.
`
if( putenv( "TZ=CET-1CEST-2,M3.5.0/2,M10.5.0/3" ) != 0 ) {
std::cout << "Unable to set TZ" << std::endl;
} else {
tz = getenv("TZ");
if (tz) std::cout << tz << std::endl;
else std::cout << "TZ not defined" << std::endl; tzset();
}
struct std::tm t;
t.tm_sec = 0;
t.tm_min = 56;
t.tm_hour = 18;
t.tm_mday = 19;
t.tm_mon = 3-1;
t.tm_year = 2016-1900;
t.tm_isdst = -1;
std::time_t tt = std::mktime(&t);
std::cout << "UTC: " << std::put_time(std::gmtime(&tt), "%c %Z") << '\n'; // UTC : 03/19/16 16:56
std::cout << "local: " << std::put_time(std::localtime(&tt), "%c %Z") << '\n'; // Local : 03/19/16 18:56 (not waited result)
`
В качестве точности я использую компилятор bcc32c (компьютер на основе Clang Embarcadero C ++).
Надеюсь, я достаточно ясна, и вы сможете мне помочь.
заранее спасибо
Если у вас есть C ++ 11 (или более поздняя версия), которая включает <chrono>
и если вы готовы работать с <chrono>
система. И если вы готовы использовать это бесплатная библиотека часовых поясов с открытым исходным кодом. Тогда это очень простой вопрос:
#include "tz.h"#include <iostream>
int
main()
{
using namespace date;
using namespace std::chrono_literals;
auto zt = make_zoned("Europe/Paris", sys_days{2016_y/mar/19} + 18h + 56min);
std::cout << format("%m/%d/%y %H:%M %Z", zt.get_sys_time()) << '\n';
std::cout << format("%m/%d/%y %H:%M %Z", zt) << '\n';
}
Выход:
03/19/16 18:56 UTC
03/19/16 19:56 CET
Короче говоря, вы формируете один zoned_time
сопоставляя часовой пояс по вашему выбору
(«Европа / Париж»), с sys_time
(УНИВЕРСАЛЬНОЕ ГЛОБАЛЬНОЕ ВРЕМЯ). Тогда вы можете отформатировать это zoned_time
оба путем извлечения sys_time
отступить от него, и отформатировав zoned_time
сам, который будет использовать local_time
из zoned_time
,
Я попытался использовать форматирование, соответствующее вашим комментариям. Вы можете, конечно, любой формат, который вы хотите. Вы также можете включить любой std::locale
ваша система поддерживает в качестве первого аргумента в вызовах format
(который %c
бы воспользоваться).
Вы также можете извлечь отдельные поля как из sys_time
и из local_time
если вам нужно, или делать другие вычисления даты или времени. Это больше, чем просто библиотека форматирования.
Если вы начинаете с time_t
есть статическая функция-член std::chrono::system_clock
преобразовать time_t
к system_clock::time_point
, Вы можете использовать это time_point
на месте sys_days{2016_y/mar/19} + 18h + 56min
в этом примере:
auto zt = make_zoned("Europe/Paris", system_clock::from_time_t(t));
Других решений пока нет …