2016-07-11 6 views
0

Ich habe meinen Kopf verrückt worden wracking versuchen, diese with this APIeine lokale Zeit mit Zeitzone in UTC mit Ctime

Meine ursprüngliche Implementierung, um herauszufinden, war so etwas wie:

// 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; 
} 

Dies ist jedoch nicht braucht DST berücksichtigen. Zum Beispiel, wenn ich es ein Datum Sep 28 2012 15:54:24 füttere bekomme ich Sep 28 2012 20:54:24, was falsch ist. Es sieht so aus, als ob ich localtime_rz verwenden möchte, außer dass es eine Epoche braucht, die mich verrückt macht, denn wenn ich die Epoche bekommen könnte, hätte ich schon meine Antwort. :(

Wie kann ich das erreichen?

+1

Das STD hat eine Funktion: tm * gmtime (const time_t * time); Hast du das probiert? –

Antwort

2

mktime_z ein struct tm als eines ihres Argument übernimmt. Wenn Sie nicht wissen, ob DST in der Tat für das Eingangsdatum ist, mögen Sie das tm_isdst Mitglied Set dass tm zu -1 um anzuzeigen, dass das System herauszufinden sollte, ob DST in der Tat für diese Datum/Zeit/Zeitzone ist, wenn Sie mktime nennen.

zumindest für mich, dies richtig zu funktionieren scheint (dh schließt es richtig, dass zumindest in meiner Zeitzone war DST im September 2012 in Kraft.)

0

Zusätzlich zu Jerry Coffin 's richtige (und abgestimmt) Antwort, wollte ich zeigen, wie diese Berechnung mit einem modern C++11/14 library (freie und Open Source) durchgeführt werden könnte.

Ich habe die API das gleiche im Interesse der Herstellung der Code einfach gehalten zu vergleichen:

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

Dies gibt ein std::chrono::time_point<system_clock, Duration> wo Duration desto feiner die Eingabe ist Duration und seconds. Wenn die ragtime keine eindeutige Zuordnung zu UTC gemäß der angegebenen Zeitzone aufweist, wird eine Ausnahme ausgelöst. Ein solches Ereignis kann zum Beispiel auftreten, wenn rawtime während eines Übergangs zu Sommerzeit ist und zweimal oder gar nicht auftritt. Falls gewünscht, gibt es eine API zum Vermeiden der Ausnahme, wenn Sie "vorab entscheiden" wollen, wie Sie mehrdeutige und nicht existierende lokale Zeiten in UTC abbilden möchten.

Diese Funktion kann wie folgt ausgeübt werden:

#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"; 
} 

Diese Übungen den Code zweimal:

  1. Mit was auch immer die aktuelle Zeitzone für diesen Computer ist.
  2. Mit der Zeitzone „Amerika/New_York“

Für mich sind diese beiden sind die gleichen Zeitzone, in der folgenden Ausgabe führt:

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

Nicht nur ist es einfacher, diese Bibliothek zu verwenden, als die BSD ctime API, aber diese API hat Typ Sicherheit. Zum Beispiel werden der UTC-Zeitpunkt und der lokale Zeitpunkt durch unterschiedliche Typen repräsentiert, so dass der Compiler Ihnen sagen kann, ob Sie versehentlich den falschen verwendet haben. Im Gegensatz dazu verwendet die BSD ctime API den gleichen Typ (tm) für die lokale Zeit und UTC.

Verwandte Themen