2012-10-11 8 views

risposta

48

Se system_clock, questa classe ha la conversione time_t.

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

risultato esempio:

Thu Oct 11 19:10:24 2012 

EDIT: Ma, time_t non contiene frazioni di secondo. Il modo alternativo è utilizzare la funzione time_point :: time_since_epoch(). Questa funzione restituisce la durata da epoca. L'esempio seguente è il frazionario della seconda risoluzione di milli.

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

risultato esempio:

Thu Oct 11 19:10:24 2012 

925 
+0

E, come aggiungere alla stringa di output i secondi frazionari? –

+0

time_t non contiene fractional seconds. Aggiungo altro codice di esempio –

+0

Grazie! ora le risposte sono migliori e più vicine a ciò che l'op stava chiedendo. –

6

In generale, non si può fare questo in qualsiasi modo semplice. time_point è essenzialmente solo un duration da un'epoca specifica per l'orologio.

Se si dispone di un std::chrono::system_clock::time_point, quindi è possibile utilizzare per convertire il std::chrono::system_clock::to_time_ttime_point ad un time_t, e quindi utilizzare le normali funzioni C, come ctime o strftime formattarlo. codice


Esempio:

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

Il problema con questa soluzione è std :: localtime non essendo thread-safe. – minexew

23

codice Autogiustificativo consegue che prima crea un std::tm corrispondente al 2012/10/10 00:38:40, converte che a un std::chrono::system_clock::time_point, aggiunge 0.123456 secondi, e poi lo stampa riconvertendolo in un std::tm. Come gestire i secondi frazionari è nell'ultimo passaggio.

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

per me questo uscite:

10-10-2012 12:38:40.123456 

tuo std::chrono::system_clock::time_point può o non può essere sufficientemente preciso per bloccare microsecondi.

Aggiornamento

Un modo più semplice è quello di utilizzare solo this date library. Il codice semplifica fino a (in C++ 14 letterali di durata):

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

quali uscite:

2012-10-10 12:38:40.123456 

Si può saltare il static_assert se non è necessario dimostrare che il tipo di t è un std::chrono::time_point.

Se l'uscita non è di vostro gradimento, per esempio, si sarebbe davvero come gg-mm-aaaa ordinamento, si potrebbe:

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

che dà esattamente la potenza richiesta:

10-10-2012 12:38:40.123456 

Aggiornamento

Ecco come formattare ordinatamente l'UTC tempo corrente con precisione millisecondi:

#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())); 
} 

che ha appena uscita per me:

2016-10-17 16:36:02.975 

C++ 17 vi permetterà di sostituire time_point_cast<milliseconds> con floor<milliseconds>. Fino ad allora date::floor è disponibile in "date.h".

std::cout << date::format("%F %T\n", date::floor<milliseconds>(system_clock::now())); 
+3

Questo è in fase di proposta al comitato per gli standard C++: https://howardhinnant.github.io/date/d0355r1.html –

1

questo ha lavorato per me per un formato simile YYYY.MM.DD-HH.MM.SS.fff. Il tentativo di rendere questo codice in grado di accettare qualsiasi formato stringa sarà come reinventare la ruota (cioè ci sono funzioni per tutto questo 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

In realtà, quando c'è solo 1 MS, si ottiene un risultato errato poiché to_String() converte quello lungo (ms.count (()). è necessario convertire i millicecondi con uno sprintf_s. –

2

avrei messo questo in un commento alla risposta accettata, dato che è in cui essa appartiene, ma non posso. Così, proprio nel caso qualcuno ottiene risultati inattendibili, questo potrebbe essere il motivo.

stare attenti la risposta accettata, non riesce se il time_point è prima dell'epoca.

Questa riga di codice:

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

produrrà valori imprevisti se ms.count() è negativo (poiché size_t non è pensato per contenere valori negativi).

+7

perché il mondo non è stato creato nel 1970. – Neutrino

+0

Questa non è una risposta appropriata per lo stack overflow e dovrebbe essere rimosso. – xaxxon

Problemi correlati