Holen Sie sich Unix-Zeitstempel mit C ++

71

Wie bekomme ich einen uintUnix-Zeitstempel in C ++? Ich habe ein bisschen gegoogelt und es scheint, dass die meisten Methoden nach komplizierteren Wegen suchen, um die Zeit darzustellen. Kann ich es nicht einfach als bekommen uint?

2rs2ts
quelle

Antworten:

90

In C ++ 20 wurde eine Garantie eingeführt, die time_since_epochsich auf die UNIX-Epoche bezieht , und cppreference.com gibt ein Beispiel, das ich auf den relevanten Code destilliert und in Einheiten von Sekunden anstatt in Stunden geändert habe:

#include <iostream>
#include <chrono>
 
int main()
{
    const auto p1 = std::chrono::system_clock::now();
 
    std::cout << "seconds since epoch: "
              << std::chrono::duration_cast<std::chrono::seconds>(
                   p1.time_since_epoch()).count() << '\n';
}

Die Verwendung von C ++ 17 oder früher time()ist die einfachste Funktion - Sekunden seit Epoche, die für Linux und UNIX zumindest die UNIX-Epoche wäre. Linux Manpage hier .

Die oben verlinkte cppreference-Seite gibt dieses Beispiel :

#include <ctime>
#include <iostream>
 
int main()
{
    std::time_t result = std::time(nullptr);
    std::cout << std::asctime(std::localtime(&result))
              << result << " seconds since the Epoch\n";
}
Tony Delroy
quelle
4
"Epoch" ist natürlich das Unix-Eproch unter Unix und Linux, aber das ist nicht universell.
MSalters
43
#include<iostream>
#include<ctime>

int main()
{
    std::time_t t = std::time(0);  // t is an integer type
    std::cout << t << " seconds since 01-Jan-1970\n";
    return 0;
}
wilhelmtell
quelle
1
Dies setzt voraus, dass std::time()Sie seit 1970 Sekunden haben. Dies gilt für viele Systeme (POSIX und Windows, glaube ich), wird jedoch vom Sprachstandard nicht garantiert.
Keith Thompson
17

Der häufigste Rat ist falsch, man kann sich nicht einfach darauf verlassen time(). Das ist für eine relative Timing verwendet: ISO C ++ nicht spezifiziert , dass 1970-01-01T00:00Zisttime_t(0)

Schlimmer ist, dass man es auch nicht leicht herausfinden kann. Sicher, Sie können das Kalenderdatum von time_t(0)mit finden gmtime, aber was werden Sie tun, wenn das so ist 2000-01-01T00:00Z? Wie viele Sekunden waren zwischen 1970-01-01T00:00Zund 2000-01-01T00:00Z? Aufgrund von Schaltsekunden ist es sicherlich kein Vielfaches von 60.

MSalters
quelle
1
"Wie bekomme ich einen Uint-Unix-Zeitstempel in C ++?" - wie gesagt - Sie können gmtime()später anrufen , um eine lesbare Darstellung dessen zu erhalten, was dieser Zeitstempel codiert. Welche in der Frage angeforderte Funktionalität time()wird unabhängig vom Referenzdatum oder der Eignung für Intervallberechnungen nicht erfüllt ?
Tony Delroy
3
Um einen UNIX- Zeitstempel auf einem Nicht-UNIX-System zu erhalten, müssen Sie den Unterschied (in Sekunden) zwischen der lokalen Epoche und kennen 1970-01-01T00:00Z. Es gibt einfach keine Methode, die das macht.
MSalters
Aus irgendeinem Grund hatte ich den Eindruck, dass die Frage nach Code auf einem UNIX-Computer (oder Linux usw.) lautete, aber jetzt sehe ich, woher Sie kommen. Neugierig: Haben Sie ein System gefunden, bei dem time_t (0) nicht 1970-01-01T00: 00Z war? Es wäre nur ein paar Minuten Arbeit, um einen Offset auf einem bestimmten System zu berechnen (nehmen Sie die Nicht-UNIX-Zeit_t (0) und erhalten Sie eine Zeit_t dafür auf einem UNIX-System), aber danke, dass Sie Ihr Anliegen erklärt haben.
Tony Delroy
6
Für VS seine UNIX-Zeit; MSDN-Status: Die Zeitfunktion gibt die Anzahl der Sekunden zurück, die seit Mitternacht (00:00:00), 1. Januar 1970, koordinierte Weltzeit (UTC), gemäß der Systemuhr vergangen sind. msdn.microsoft.com/en-us/library/1f4c8f33.aspx
Oliver
2
@ TonyD: IBM Systeme sind anscheinend eine Ausnahme. Keine wirkliche Überraschung, da sie lange vor dem 1.1.1970 im Computergeschäft tätig waren.
MSalters
8

Da dies das erste Ergebnis bei Google ist und es noch keine C ++ 20-Antwort gibt, gehen Sie wie folgt vor, um std :: chrono zu verwenden:

#include <chrono>

//...

using namespace std::chrono;
int64_t timestamp = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();

In Versionen von C ++ vor 20 ist die Epoche von system_clock als Unix-Epoche eine De-facto-Konvention, die jedoch nicht standardisiert ist. Wenn Sie nicht mit C ++ 20 arbeiten, erfolgt die Verwendung auf eigenes Risiko.

Tharwen
quelle
3
Die Epoche wird offiziell in C ++ 20 anerkannt: eel.is/c++draft/time.clock.system.overview
Howard Hinnant
6
#include <iostream>
#include <sys/time.h>

using namespace std;

int main ()
{
  unsigned long int sec= time(NULL);
  cout<<sec<<endl;
}
Anijhaw
quelle
time()Gibt ein Ergebnis vom Typ zurück time_t, das im Prinzip entweder vorzeichenbehaftet, vorzeichenlos oder sogar Gleitkomma sein kann. Warum das Ergebnis in a speichern long int? Und warum <sys/time.h>eher als den Standard verwenden <time.h>?
Keith Thompson
Ich verstehe, aber ich denke, in jedem posix-kompatiblen Betriebssystem sind beide time.h & sys / time.h vorhanden. Sie haben auch völlig Recht, dass time_t auch ein negativer Wert sein kann, da er als Sekunden dargestellt wird, die vom 1970-01-01T00: 00Z vergangen sind.
Anijhaw
4

Ich habe eine globale Definition mit weiteren Informationen erstellt:

#include <iostream>
#include <ctime>
#include <iomanip>

#define __FILENAME__ (__builtin_strrchr(__FILE__, '/') ? __builtin_strrchr(__FILE__, '/') + 1 : __FILE__)    // only show filename and not it's path (less clutter)
#define INFO std::cout << std::put_time(std::localtime(&time_now), "%y-%m-%d %OH:%OM:%OS") << " [INFO] " << __FILENAME__ << "(" << __FUNCTION__ << ":" << __LINE__ << ") >> "
#define ERROR std::cout << std::put_time(std::localtime(&time_now), "%y-%m-%d %OH:%OM:%OS") << " [ERROR] " << __FILENAME__ << "(" << __FUNCTION__ << ":" << __LINE__ << ") >> "

static std::time_t time_now = std::time(nullptr);

Verwenden Sie es so:

INFO << "Hello world" << std::endl;
ERROR << "Goodbye world" << std::endl;

Beispielausgabe:

16-06-23 21:33:19 [INFO] main.cpp(main:6) >> Hello world
16-06-23 21:33:19 [ERROR] main.cpp(main:7) >> Goodbye world

Fügen Sie diese Zeilen in Ihre Header-Datei ein. Ich finde das sehr nützlich zum Debuggen usw.

xinthose
quelle
Warum #defineund nicht eine Funktion? Funktion wäre flexibler,
überladbarer
3
@Troyseph Weil dann __FILE__``__FUNCTION__``__LINE__ nicht wie vorgesehen funktionieren würde. Dies ist ein Makro.
Xinthose
1
Fair genug! Schade, dass es keine modernere Alternative gibt =]
Troyseph