2016-11-14 4 views
9

Wie könnte ich den Wochentag in Kalifornien (Pacific Time) anhand eines beliebigen Unix-Zeitstempels (Sekunden) ermitteln? Ich habe gesucht, aber keine integrierte Bibliothek für C++ gefunden.Unix-Zeitstempel in Wochentag in C++ konvertieren?

UTC ist in der Regel 8 Stunden vor PT, aber einfach subtrahieren 8 Stunden von der Unix-Zeitmarke und Erstellen einer tm Struktur funktioniert nicht, da dies Sommerzeit Nuancen rabattiert.

+1

Ich habe Sie nicht abgelehnt, aber wie wäre es mit ['std :: localtime'] (http://en.cppreference.com/w/cpp/chrono/c/localtime)? – Danh

+1

Danke - was ist, wenn die lokale Zeit nicht PT für mich ist? –

+3

[strftime] (http://en.cppreference.com/w/cpp/chrono/c/strftime). Oder [time_put] (http://en.cppreference.com/w/cpp/locale/time_put). Oder [Howard Hinnants Datum] (https://github.com/HowardHinnant/date) - Zeiger, keine Antworten, deshalb ein Kommentar. –

Antwort

9

So geht's mit Howard Hinnant's date library. Dies ist eine kostenlose MIT-Lizenz C++ 14.11 Bibliothek basierend auf <chrono>:

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

int 
main() 
{ 
    using namespace std::chrono_literals; 
    using namespace date; 
    auto unix_timestamp = sys_seconds{1479664467s}; 
    auto zt = make_zoned("America/Los_Angeles", unix_timestamp); 
    auto wd = weekday{floor<days>(zt.get_local_time())}; 
    std::cout << wd << '\n'; 
} 

Die erste Zeile nur konstruiert den Unix-Zeitstempel (die Sie aus anderen Quellen haben können). In C++ 11 haben wir nicht die chrono Literale und so würde diese Linie stattdessen sein:

auto unix_timestamp = sys_seconds{seconds{1479664467}}; 

make_zoned() schafft eine zoned_time<seconds> basierend auf dem unix_timestamp und den time_zone „Amerika/Los_Angeles“. A zoned_time ist eine Sammlung von time_zone und Unix-Zeitstempel.

Sie können die lokale Zeit von zoned_time mit zt.get_local_time() abrufen. Dies ist ein chrono::time_point, aber ohne Uhr damit verbunden. Die Genauigkeit dieses Zeitpunkts entspricht der Genauigkeit Ihres ursprünglichen Zeitstempels (in diesem Fall in Sekunden).

Sie können den lokalen Tag der Woche der local_time erhalten, indem die local_time mit einer Genauigkeit von days Kürzen:

floor<days>(zt.get_local_time()) 

Und diese Tag-Präzision time_point konvertieren weekday eingeben.

Ein weekday kann ausgedruckt werden, an weekday Arithmetik und Vergleichen teilnehmen oder explizit in einen unsigned im Bereich [0, 6] konvertiert werden.

Das Programm über Ausgänge:

Sun 

Die Zeitzone Teil dieser Bibliothek ist eine getreue Darstellung der IANA timezone database. Es wird korrekte Anpassungen zwischen lokalen Zeitzonen und UTC bis in die Mitte des 19. Jahrhunderts bis zum heutigen Tag geben. Wenn Sie die Bibliothekszeitstempel vor der Mitte des 19. Jahrhunderts übergeben, wird der früheste bekannte UTC-Offset rückwärts auf das Jahr -32768 extrapoliert. Sie können Zeitstempel auch so weit in der Zukunft wie das Jahr 32767 übergeben und die aktuellen Offset- und Sommerzeit-Regeln werden weiter verbreitet.

Da diese Bibliothek auf <chrono> aufgebaut ist, wird sie jede Präzision verarbeiten, die <chrono> liefert. Beachten Sie, dass einige chrono::duration s wie nanoseconds einen eingeschränkteren Bereich haben (+/- 292 Jahre für nanoseconds).

Die Bibliothek/der Prozess ist threadsicher. Das heißt, das Programm arbeitet direkt mit der von Ihnen angegebenen Zeitzone, ohne die Zeitzone oder Umgebungsvariablen Ihres Computers unter der Haube zu ändern. Es beinhaltet auch nicht den Teil der C-Timing-API, von dem bekannt ist, dass er nicht threadsicher ist, weil die lokale Statik nicht konstant ist.

Portiert auf die neuesten Versionen von gcc, clang und VS.

1

Können Sie Boost-Bibliothek verwenden? Wenn Sie die Posix-Zeitzonen-Zeichenfolge (IEEE Std 1003.1, siehe http://www.boost.org/doc/libs/1_62_0/doc/html/date_time/local_time.html#date_time.local_time.posix_time_zone) für Ihre Zeitzone (PST) herausfinden können, hilft Ihnen das Beispiel unten.

#include <iostream> 
#include <ctime> 
#include <boost/date_time.hpp> 

int main(int argc, char ** argv) 
{ 
    std::string posix_time_zone_string = "EST-05:00:00"; // you need to change this to the posix time representation of your desired timezone 

    time_t unix_time = 1479641855; //1479641855 = Sun, 20 Nov 2016 11:37:35 GMT 

    boost::posix_time::ptime pt = boost::posix_time::from_time_t(unix_time); 
    std::cout << "time in UTC: " << boost::posix_time::to_iso_extended_string(pt) << std::endl; 


    boost::local_time::time_zone_ptr zone(new boost::local_time::posix_time_zone(posix_time_zone_string)); 

    boost::local_time::local_date_time dt_with_zone(pt, zone); 
    std::cout << "time in local timezone: " << boost::posix_time::to_iso_extended_string(dt_with_zone.local_time()) << std::endl; 

    // Get the week day (alternative 1) 
    std::cout << "local week day integer: " << boost::local_time::to_tm(dt_with_zone).tm_wday << std::endl; // 0=sunday, 1=monday, etc. 

    // Get the week day (alternative 2) 
    std::cout << "local week day name: " << dt_with_zone.local_time().date().day_of_week() << std::endl; 
    std::cout << "local week day integer: " << int(dt_with_zone.local_time().date().day_of_week()) << std::endl; 
    return 0; 
} 
2

Hacky Weise Standard-UNIX-C (nicht Thread-sicher-Version) mit:

#include <stddef.h> 
#include <stdlib.h> 
#include <stdio.h> 
#include <time.h> 

void print_times() { 
    char my_buf[100]; 
    time_t now = time(NULL); 
    printf(ctime(&now)); 
    strftime(my_buf, 100, "DoW=%w Tz=%Z\n", localtime(&now)); 
    printf(my_buf); 
} 

int main(int argc, char * argv[]) { 
    print_times(); 
    setenv("TZ", "America/Los_Angeles", 1); 
    print_times(); 
    unsetenv("TZ"); 
    print_times(); 
} 

Leider TZ env var oder das Ändern der Datei /etc/localtime die einzigen Möglichkeiten sind, können Sie Zeitzone Einstellungen für die UNIX-Zeitfunktionen (unter Einwirkung Die Steuerzentrale tzset() verwendet diese Quellen, um eine Gruppe von gemeinsam genutzten Variablen zu initialisieren, die die Zeitzoneneinstellungen für alle Bibliotheksfunktionen kodieren.

Ein Problem ist, dass Sie die UNIX TZ Zeichenfolge (n) für die Zone (n) benötigen, die Sie benötigen. zoneinfo Format ist das einfachste und empfohlene Format zu verwenden. Ich habe tzselect verwendet, um diesen TZ-Wert für Pacific Time zu generieren.

Siehe auch man 5 localtime, man tzselect für Informationen zum UNIX-Standardzeitzonen-Setup.