Ausgabe von Datum und Uhrzeit in C ++ mit std :: chrono

74

Ich habe alten Code aktualisiert und versucht, nach Möglichkeit auf c ++ 11 zu aktualisieren. Mit dem folgenden Code habe ich Uhrzeit und Datum in meinem Programm angezeigt

#include <iostream>
#include <string>
#include <stdio.h>
#include <time.h>

const std::string return_current_time_and_date() const
{
    time_t now = time(0);
    struct tm tstruct;
    char buf[80];
    tstruct = *localtime(&now);
    strftime(buf, sizeof(buf), "%Y-%m-%d %X", &tstruct);
    return buf;
}

Ich möchte die aktuelle Uhrzeit und das aktuelle Datum in einem ähnlichen Format mit std :: chrono (oder ähnlichem) ausgeben, bin mir aber nicht sicher, wie ich das machen soll. Jede Hilfe wäre sehr dankbar. Vielen Dank

const_ref
quelle
Bitte schauen Sie nach, ob bereits eine solche Frage gestellt wurde, und wenn nicht, fragen Sie.
Legends2k
4
Mit C ++ 11 werden Sie nicht viel besser. Bei Chrono geht es mehr um das Timing (wie lange hat etwas gedauert) als um Dinge vom Typ Tageszeit. Sie können sich jedoch die Boost Date Time ansehen. Es verfügt über eine robustere Funktion für Datum und Uhrzeit.
Nathan Ernst
Datum und Uhrzeit mit Chrono und Ausgabe abrufen? Siehe das erste Beispiel .
Dyp
2
@DyP Das sieht vielversprechend aus, aber ich muss einen String von der Funktion zurückgeben und bin mir nicht sicher, wie ich das mit std :: put_time
const_ref machen soll.

Antworten:

102

Die <chrono>Bibliothek befasst sich nur mit Zeit und nicht mit Datumsangaben, mit Ausnahme system_clockderjenigen, in die die Zeitpunkte konvertiert werden können time_t. Die Verwendung <chrono>für Datumsangaben wird die Dinge also nicht wesentlich verbessern. Hoffentlich bekommen wir so etwas wie chrono::datein nicht allzu ferner Zukunft.

Das heißt, Sie können <chrono>auf folgende Weise verwenden:

#include <chrono>  // chrono::system_clock
#include <ctime>   // localtime
#include <sstream> // stringstream
#include <iomanip> // put_time
#include <string>  // string

std::string return_current_time_and_date()
{
    auto now = std::chrono::system_clock::now();
    auto in_time_t = std::chrono::system_clock::to_time_t(now);

    std::stringstream ss;
    ss << std::put_time(std::localtime(&in_time_t), "%Y-%m-%d %X");
    return ss.str();
}

Beachten Sie, dass dies zu std::localtimeDatenrennen führen kann. localtime_roder ähnliche Funktionen sind möglicherweise auf Ihren Plattformen verfügbar.

Aktualisieren:

Mit einer neuen Version von Howard Hinnant des aktuellen Bibliothek Sie schreiben können:

#include "date.h"
#include <chrono>
#include <string>
#include <sstream>

std::string return_current_time_and_date() {
  auto now = std::chrono::system_clock::now();
  auto today = date::floor<days>(now);

  std::stringstream ss;
  ss << today << ' ' << date::make_time(now - today) << " UTC";
  return ss.str();
}

Dies wird so etwas wie "2015-07-24 05: 15: 34.043473124 UTC" ausdrucken.


Unabhängig davon ist die Rückgabe von constObjekten mit C ++ 11 unerwünscht geworden. const Rückgabewerte können nicht verschoben werden. Ich habe auch die nachfolgende Konstante entfernt, da die nachgestellte Konstante nur für Elementfunktionen gültig ist und diese Funktion kein Mitglied sein muss.

bames53
quelle
8
Beachten Sie, dass einige alte Compiler dies möglicherweise nicht erkennen std::put_time. Nachdem ich versucht hatte, meinen Code unter std::put_timeCentOS 7 mit g ++ zu kompilieren , schlug dies fehl. Status der std::put_timeUnterstützung in GCC stackoverflow.com/q/14136833/4694036
LETs
1
Gibt es eine C ++ - Funktion ähnlich wie std :: put_time, aber um einen String zurückzugeben?
Nick
@Nick Nein. Mit der C-Funktion strftimekönnen Sie einen Puffer mit einer C-Zeichenfolge füllen. Die veraltete Funktion asctimegibt eine C-Zeichenfolge in einem festen Zeitformat zurück.
Bames53
danke, nun, ich denke du kannst put_time mit string stream machen
Nick
2
Wenn Sie nicht verwenden , funktioniert using namespace date;das << todaynicht.
Orwellophile
13

Ein Beispiel:

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

std::string getTimeStr(){
    std::time_t now = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());

    std::string s(30, '\0');
    std::strftime(&s[0], s.size(), "%Y-%m-%d %H:%M:%S", std::localtime(&now));
    return s;
}
int main(){

    std::cout<<getTimeStr()<<std::endl;
    return 0;

}

Ausgabe wie folgt:

Geben Sie hier die Bildbeschreibung ein

Jayhello
quelle
1
NICHT THREAD SAFE siehe Daten Rennen
Dawid Drozd
Downvote: Die aktuelle Antwort gibt eine 30 Zeichen lange Zeichenfolge mit vielen Nullzeichen am Ende zurück. Wenn Sie versuchen, etwas damit zu verketten, funktioniert es nicht. Ich habe eine Bearbeitung vorgeschlagen, damit es funktioniert, aber sie wurde von Django-Programmierern abgelehnt ...
Den-Jason
5

Um auch Millisekunden zu erhalten, verwende ich die chrono- und C-Funktion localtime_r, die threadsicher ist (im Gegensatz zu std :: localtime).

#include <iostream>
#include <chrono>
#include <ctime>
#include <time.h>
#include <iomanip>


int main() {
  std::chrono::system_clock::time_point now = std::chrono::system_clock::now();
  std::time_t currentTime = std::chrono::system_clock::to_time_t(now);
  std::chrono::milliseconds now2 = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch());
  struct tm currentLocalTime;
  localtime_r(&currentTime, &currentLocalTime);
  char timeBuffer[80];
  std::size_t charCount { std::strftime( timeBuffer, 80,
                                         "%D %T",
                                          &currentLocalTime)
                         };

  if (charCount == 0) return -1;

  std::cout << timeBuffer << "." << std::setfill('0') << std::setw(3) << now2.count() % 1000 << std::endl;
  return 0;
}

Für das Format: http://www.cplusplus.com/reference/ctime/strftime/

Rodolk
quelle
Da Sie iomanip bereits importieren, können Sie das Erstellen eines eigenen Puffers überspringen, indem Sie std :: put_time anstelle von std :: strftime verwenden.
Bloodgain
Sie können um eine halbe Sekunde erscheinen, da to_time_tsie abschneiden, aber auch runden können.
Ruslan
3

bames53-Lösungen sind gut, lassen sich aber auf meinem VS2017 nicht kompilieren. Die Lösung mit ctime wird nicht kompiliert, da die Ortszeit sehr veraltet ist. Der mit date.h wird nicht mit dem aktuellen Datum kompiliert. H Ich habe gerade github entfernt, obwohl die Dokumentation dies vorschreibt, da der heutige Tag nicht so gestreamt werden kann, wie er ist. Ich habe die Includes weggelassen, aber hier ist Code, der funktioniert:

void TimeTest()
{
    auto n = std::chrono::system_clock::now();
    auto in_time_t = std::chrono::system_clock::to_time_t(n);
    std::tm buf;
    localtime_s(&buf, &in_time_t);
    std::cout << std::put_time(&buf, "%Y-%m-%d %X") << std::endl;

}

// I just added date.h from this link's guthub to the project.
// https://howardhinnant.github.io/date/date.html
void TimeTest1() {
    auto now = std::chrono::system_clock::now();
    auto today =  floor<date::days>(std::chrono::system_clock::now());
    std::cout << date::year_month_day{ today } << ' ' << date::make_time(now - today) << std::endl;
}

// output is 
// 2018-04-08 21:19:49
// 2018-04-08 18:19:49.8408289

Fühlen Sie sich frei, die bames53-Lösung zu reparieren und meine zu löschen. Mein Text passt einfach nicht in einen Kommentar. Ich bin sicher, es kann viele Menschen vor Trauer retten.

Yaniv
quelle
1
Wenn Sie hinzufügen using date::operator<<;, können Sie streamen, todayohne es zu konvertieren year_month_day.
Howard Hinnant
Howard, vielen Dank, dass Sie diese Bibliothek geschrieben und geteilt haben. Auf den Punkt gebracht, würde ich lieber nie verwenden, da ich in meinen Tagen genug Fehler und Mehrdeutigkeiten durch Namespace-Kollisionen erlitten habe. Wenn wir genau sind, möchte ich auch darauf hinweisen, dass das erste Beispiel die Ortszeit ausgibt, während das zweite die Weltzeit ist.
Yaniv
1
Ich bin froh, dass ich helfen kann. usingsat Funktionsumfang sind ein guter Kompromiss, da Konflikte leichter zu kontrollieren sind, wenn sie auftreten. Mir ist klar, dass dies nicht perfekt ist, aber es ist das Beste, was für Stream-Einfügeoperatoren für std :: -Typen getan werden kann, die von Bibliotheken von Drittanbietern geschrieben wurden. Aber erst letzten Monat habe ich das C ++ - Komitee davon überzeugt, diesen Streaming-Operator namespace std::chronofür C ++ 20 einzusetzen, damit er von ADL gefunden wird. Dann wird es nicht mehr benötigt using.
Howard Hinnant
Gute Beobachtung, dass die Ausgabe UTC ist. Ebenfalls verfügbar ist eine übergeordnete Bibliothek, die Vorgänge mit Ortszeit bereitstellt. Dies kann mit der aktuellen lokalen Zeitzone Ihres Computers oder mit einer speziell festgelegten Zeitzone (z. B. "America / New_York") geschehen. Hier ist die Dokumentation für die Zeitzonenbibliothek .
Howard Hinnant
2

Sie können die Antwort von @ bames53 verbessern, indem Sie Boost lexical_cast anstelle von String-Stream-Manipulationen verwenden.

Folgendes mache ich:

#include <boost/lexical_cast.hpp>
#include <ctime>

std::string return_current_time_and_date() {
    auto current_time = std::time(0);
    return boost::lexical_cast<std::string>(std::put_time(std::gmtime(& current_time), "%Y-%m-%d %X"));
}
Xavier Lamorlette
quelle
auch ist iomanip benötigte en.cppreference.com/w/cpp/io/manip/put_time
poseid