2016-07-11 8 views
0

Я нарушающие покоем голову с умом, пытаясь понять это with this APIПреобразовать местное время с часовым поясом в UTC с CTime

Моей первоначальная реализация была что-то вроде:

// TimezonePtr is just a share_ptr to the timezone 
std::tm getGMT(const std::tm& rawtime, TimezonePtr tz) 
{ 
    std::tm result = rawtime; 
    const auto loct = mktime_z(tz.get(), &result); 
    gmtime_r(&loct, &result); 
    return result; 
} 

Однако, это не займет с учетом ДСТ. Например, если я подаю ему дату Sep 28 2012 15:54:24, я вернусь Sep 28 2012 20:54:24, что неверно. Похоже, я хочу использовать localtime_rz, за исключением того, что занимает эпоху, которая меня заводит, потому что, если бы я мог получить эпоху, то у меня уже был бы мой ответ. :(

Как я могу это сделать?

+1

STD имеет функцию: tm * gmtime (const time_t * time); Вы пробовали это? –

ответ

2

mktime_z занимает struct tm в качестве одного из своих аргументов. Если вы не знаете ли DST действует на дату ввода, вы хотите установить tm_isdst член что tm к -1, чтобы показать, что система должна выяснить, является ли DST в силу для этой даты/времени/часового пояса, когда вы звоните mktime.

по крайней мере, для меня, это, кажется, работает неправильно (то есть, он правильно делает вывод, что по крайней мере, в моем часовом поясе, DST действовал в сентябре 2012 года).

0

В дополнение к правильному (и опрошенному) ответу Jerry Coffin, я хотел показать, как это вычисление может быть выполнено с помощью modern C++11/14 library (бесплатный и с открытым исходным кодом).

я сохранил API же в интересах сделать код легко сравнить:

template <class Duration> 
auto 
getGMT(date::local_time<Duration> rawtime, const date::time_zone* tz) 
{ 
    return tz->to_sys(rawtime); 
} 

Это возвращает std::chrono::time_point<system_clock, Duration> где Duration является мельче входа Duration и seconds. Если ragtime не имеет уникального отображения в UTC в соответствии с указанным часовым поясом, будет выбрано исключение. Такое событие может произойти (например), если rawtime во время перехода на летнее время происходит и происходит дважды, или вообще нет. При желании существует API для исключения исключения, если вы хотите «заранее решить», как вы хотите сопоставить двусмысленные и несуществующие локальные времена в UTC.

Эта функция может осуществляться следующим образом:

#include "tz.h" 
#include <iostream> 

int 
main() 
{ 
    using namespace date; 
    using namespace std::chrono_literals; 
    std::cout << getGMT(local_days{sep/28/2012} + 15h + 54min + 24s, 
         current_zone()) << " UTC\n"; 
    std::cout << getGMT(local_days{sep/28/2012} + 15h + 54min + 24s, 
         locate_zone("America/New_York")) << " UTC\n"; 
} 

Это упражнения код дважды:

  1. С независимо от текущего часового пояса для этого компьютера.
  2. С часовым поясом «Америка/New_York»

Для меня эти оба являются в то же время зона, в результате чего следующий вывод:

2012-09-28 19:54:24 UTC 
2012-09-28 19:54:24 UTC 

не только проще использовать эту библиотеку чем BSD ctime API, , но этот API имеет тип безопасности. Например, точка времени UTC и местная точка времени представлены различными типами, позволяя компилятору рассказать вам, случайно ли вы используете неправильный. В отличие от этого BSD ctime API использует тот же тип (tm) как по местному времени, так и по UTC.