2012-10-11 7 views

Antwort

48

Wenn system_clock, diese Klasse hat time_t Konvertierung.

#include <iostream> 
#include <chrono> 
#include <ctime> 

using namespace std::chrono; 

int main() 
{ 
    system_clock::time_point p = system_clock::now(); 

    std::time_t t = system_clock::to_time_t(p); 
    std::cout << std::ctime(&t) << std::endl; // for example : Tue Sep 27 14:21:13 2011 
} 

Beispiel Ergebnis:

Thu Oct 11 19:10:24 2012 

EDIT: Aber Time_t enthält keine Sekundenbruchteile. Alternative Möglichkeit ist die Verwendung der Funktion time_point :: time_since_epoch(). Diese Funktion gibt die Dauer aus der Epoche zurück. Beispiel folgt Millisekunden Auflösung ist fraktional.

#include <iostream> 
#include <chrono> 
#include <ctime> 

using namespace std::chrono; 

int main() 
{ 
    high_resolution_clock::time_point p = high_resolution_clock::now(); 

    milliseconds ms = duration_cast<milliseconds>(p.time_since_epoch()); 

    seconds s = duration_cast<seconds>(ms); 
    std::time_t t = s.count(); 
    std::size_t fractional_seconds = ms.count() % 1000; 

    std::cout << std::ctime(&t) << std::endl; 
    std::cout << fractional_seconds << std::endl; 
} 

Beispiel Ergebnis:

Thu Oct 11 19:10:24 2012 

925 
+0

Und, wie die Bruchteilsekunden zur Ausgabezeichenfolge hinzuzufügen? –

+0

time_t enthält keine Sekundenbruchteile. Ich füge mehr Beispielcode hinzu. –

+0

Danke! Jetzt sind die Antworten besser und näher an dem, was die OP gefragt hat. –

6

In der Regel können Sie diese nicht in irgendeiner Art und Weise einfach tun. time_point ist im Wesentlichen nur eine duration aus einer Clock-spezifischen Epoche.

Wenn Sie ein std::chrono::system_clock::time_point haben, dann können Sie std::chrono::system_clock::to_time_t verwenden, um die time_point zu einem time_t, zu konvertieren und dann verwenden, um die normalen C-Funktionen wie ctime oder strftime es zu formatieren.


Beispielcode:

std::chrono::system_clock::time_point tp = std::chrono::system_clock::now(); 
std::time_t time = std::chrono::system_clock::to_time_t(tp); 
std::tm timetm = *std::localtime(&time); 
std::cout << "output : " << std::put_time(&timetm, "%c %Z") << "+" 
      << std::chrono::duration_cast<std::chrono::milliseconds>(tp.time_since_epoch()).count() % 1000 << std::endl; 
+1

Das Problem mit dieser Lösung ist, dass std :: localtime nicht Thread-sicher ist. – minexew

23

Selbsterklär Code folgt dem zunächst ein std::tm zu 10-10-2012 12.38.40 entsprechenden schafft umwandelt, das zu einem std::chrono::system_clock::time_point, 0,123456 Sekunden lang hinzufügt, und druckt das dann aus, indem es zurück in std::tm konvertiert. Wie man mit den Sekundenbruchteilen umgeht, ist im allerletzten Schritt.

#include <iostream> 
#include <chrono> 
#include <ctime> 

int main() 
{ 
    // Create 10-10-2012 12:38:40 UTC as a std::tm 
    std::tm tm = {0}; 
    tm.tm_sec = 40; 
    tm.tm_min = 38; 
    tm.tm_hour = 12; 
    tm.tm_mday = 10; 
    tm.tm_mon = 9; 
    tm.tm_year = 112; 
    tm.tm_isdst = -1; 
    // Convert std::tm to std::time_t (popular extension) 
    std::time_t tt = timegm(&tm); 
    // Convert std::time_t to std::chrono::system_clock::time_point 
    std::chrono::system_clock::time_point tp = 
            std::chrono::system_clock::from_time_t(tt); 
    // Add 0.123456 seconds 
    // This will not compile if std::chrono::system_clock::time_point has 
    // courser resolution than microseconds 
    tp += std::chrono::microseconds(123456); 

    // Now output tp 

    // Convert std::chrono::system_clock::time_point to std::time_t 
    tt = std::chrono::system_clock::to_time_t(tp); 
    // Convert std::time_t to std::tm (popular extension) 
    tm = std::tm{0}; 
    gmtime_r(&tt, &tm); 
    // Output month 
    std::cout << tm.tm_mon + 1 << '-'; 
    // Output day 
    std::cout << tm.tm_mday << '-'; 
    // Output year 
    std::cout << tm.tm_year+1900 << ' '; 
    // Output hour 
    if (tm.tm_hour <= 9) 
     std::cout << '0'; 
    std::cout << tm.tm_hour << ':'; 
    // Output minute 
    if (tm.tm_min <= 9) 
     std::cout << '0'; 
    std::cout << tm.tm_min << ':'; 
    // Output seconds with fraction 
    // This is the heart of the question/answer. 
    // First create a double-based second 
    std::chrono::duration<double> sec = tp - 
            std::chrono::system_clock::from_time_t(tt) + 
            std::chrono::seconds(tm.tm_sec); 
    // Then print out that double using whatever format you prefer. 
    if (sec.count() < 10) 
     std::cout << '0'; 
    std::cout << std::fixed << sec.count() << '\n'; 
} 

Für mich ist diese Ausgänge:

10-10-2012 12:38:40.123456 

Ihre std::chrono::system_clock::time_point kann oder nicht präzise genug sein, Mikrosekunden zu halten.

aktualisieren

Ein einfacherer Weg ist, einfach this date library zu verwenden. Der Code vereinfacht bis auf (unter Verwendung von C++ 14 Dauer Literale):

#include "date.h" 
#include <iostream> 
#include <type_traits> 

int 
main() 
{ 
    using namespace date; 
    using namespace std::chrono; 
    auto t = sys_days{10_d/10/2012} + 12h + 38min + 40s + 123456us; 
    static_assert(std::is_same<decltype(t), 
           time_point<system_clock, microseconds>>{}, ""); 
    std::cout << t << '\n'; 
} 

die Ausgänge:

2012-10-10 12:38:40.123456 

Sie können die static_assert überspringen, wenn Sie nicht beweisen müssen, dass die Art der t ist ein std::chrono::time_point.

Wenn die Ausgabe nicht nach Ihrem Geschmack ist, können Sie zum Beispiel würde wirklich gerne dd-mm-yyyy Ordnung, man kann:

#include "date.h" 
#include <iomanip> 
#include <iostream> 

int 
main() 
{ 
    using namespace date; 
    using namespace std::chrono; 
    using namespace std; 
    auto t = sys_days{10_d/10/2012} + 12h + 38min + 40s + 123456us; 
    auto dp = floor<days>(t); 
    auto time = make_time(t-dp); 
    auto ymd = year_month_day{dp}; 
    cout.fill('0'); 
    cout << ymd.day() << '-' << setw(2) << static_cast<unsigned>(ymd.month()) 
     << '-' << ymd.year() << ' ' << time << '\n'; 
} 

das gibt genau die gewünschte Ausgabe:

10-10-2012 12:38:40.123456 

aktualisiert

Hier ist, wie fein säuberlich mit Millisekunden Genauigkeit der aktuellen Uhrzeit UTC zu formatieren:

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

int 
main() 
{ 
    using namespace std::chrono; 
    std::cout << date::format("%F %T\n", time_point_cast<milliseconds>(system_clock::now())); 
} 

, die nur für mich ausgegeben:

2016-10-17 16:36:02.975 

C++ 17 ermöglicht es Ihnen, time_point_cast<milliseconds> mit floor<milliseconds> zu ersetzen. Bis dahin ist date::floor in "date.h" verfügbar.

+3

Dies wird derzeit dem C++ - Standardkomitee vorgeschlagen: https://howardhinnant.github.io/date/d0355r1.html –

1

Das funktionierte für mich für ein Format wie YYYY.MM.DD-HH.MM.SS.fff. Der Versuch, diesen Code zu machen fähig ist jedes String-Format zu akzeptieren, wie das Rad neu erfinden sein wird (dh es gibt Funktionen für das alles in-Boost.

std::chrono::system_clock::time_point string_to_time_point(const std::string &str) 
{ 
    using namespace std; 
    using namespace std::chrono; 

    int yyyy, mm, dd, HH, MM, SS, fff; 

    char scanf_format[] = "%4d.%2d.%2d-%2d.%2d.%2d.%3d"; 

    sscanf(str.c_str(), scanf_format, &yyyy, &mm, &dd, &HH, &MM, &SS, &fff); 

    tm ttm = tm(); 
    ttm.tm_year = yyyy - 1900; // Year since 1900 
    ttm.tm_mon = mm - 1; // Month since January 
    ttm.tm_mday = dd; // Day of the month [1-31] 
    ttm.tm_hour = HH; // Hour of the day [00-23] 
    ttm.tm_min = MM; 
    ttm.tm_sec = SS; 

    time_t ttime_t = mktime(&ttm); 

    system_clock::time_point time_point_result = std::chrono::system_clock::from_time_t(ttime_t); 

    time_point_result += std::chrono::milliseconds(fff); 
    return time_point_result; 
} 

std::string time_point_to_string(std::chrono::system_clock::time_point &tp) 
{ 
    using namespace std; 
    using namespace std::chrono; 

    auto ttime_t = system_clock::to_time_t(tp); 
    auto tp_sec = system_clock::from_time_t(ttime_t); 
    milliseconds ms = duration_cast<milliseconds>(tp - tp_sec); 

    std::tm * ttm = localtime(&ttime_t); 

    char date_time_format[] = "%Y.%m.%d-%H.%M.%S"; 

    char time_str[] = "yyyy.mm.dd.HH-MM.SS.fff"; 

    strftime(time_str, strlen(time_str), date_time_format, ttm); 

    string result(time_str); 
    result.append("."); 
    result.append(to_string(ms.count())); 

    return result; 
} 
+0

Wenn tatsächlich nur 1 MS vorhanden ist, erhalten Sie ein falsches Ergebnis, wenn to_String() konvertiert wird long (ms.count (()). du musst die millisekunden mit einem sprintf_s konvertieren –

2

Ich habe dies auf der akzeptierte Antwort in einem Kommentar setzen würde, denn das ist, wo es hingehört, aber ich kann nicht. Also, falls jemand unzuverlässige Ergebnisse bekommt, könnte dies sein, warum.

der akzeptierte Antwort Seien sie vorsichtig, es schlägt fehl, wenn die time_point vor der Epoche ist.

Diese Codezeile:

std::size_t fractional_seconds = ms.count() % 1000; 

werden unerwartete Werte ergeben, wenn ms.count() negativ ist (da size_t keine negativen Werte enthalten soll).

+0

Zeit vor der Epochen? Warum? :) –

+7

Weil die Welt nicht 1970 erstellt wurde. – Neutrino

+0

Dies ist keine passende Antwort für Stack Überlauf und sollte entfernt werden. – xaxxon