Die Boost C++ Bibliotheken

Ortsunabhängige Zeitpunkte

Während mit boost::gregorian::date ein Datum erstellt werden kann, kann boost::posix_time::ptime verwendet werden, um einen ortsunabhängigen Zeitpunkt zu definieren. boost::posix_time::ptime greift hierzu auf boost::gregorian::date zu, speichert darüber hinaus aber eine Uhrzeit.

Um boost::posix_time::ptime verwenden zu können, müssen Sie die Headerdatei boost/date_time/posix_time/posix_time.hpp einbinden.

Beispiel 36.10. boost::posix_time::ptime in Aktion
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/date_time/gregorian/gregorian.hpp>
#include <iostream>

using namespace boost::posix_time;
using namespace boost::gregorian;

int main()
{
  ptime pt{date{2014, 5, 12}, time_duration{12, 0, 0}};
  date d = pt.date();
  std::cout << d << '\n';
  time_duration td = pt.time_of_day();
  std::cout << td << '\n';
}

Sie initialisieren ein Objekt vom Typ boost::posix_time::ptime, indem Sie dem Konstruktor als ersten Parameter ein Datum vom Typ boost::gregorian::date und als zweiten Parameter einen Zeitraum vom Typ boost::posix_time::time_duration übergeben. Die drei Parameter, die dem Konstruktor von boost::posix_time::time_duration übergeben werden, bestimmen die Uhrzeit. Im Beispiel 36.10 wird ein Zeitpunkt für exakt 12 Uhr mittags am 12. Mai 2014 definiert.

Über die beiden Methoden date() und time_of_day(), die im Beispiel 36.10 verwendet werden, können Sie das Datum und die Uhrzeit abfragen.

So wie der Standardkonstruktor von boost::gregorian::date ein ungültiges Datum erstellt, ist ein Zeitpunkt vom Typ boost::posix_time::ptime ungültig, wenn der Standardkonstruktor ausgeführt wird. Sie können auch explizit einen ungültigen Zeitpunkt erstellen, indem Sie boost::date_time::not_a_date_time als einzigen Parameter an den Konstruktor von boost::posix_time::ptime übergeben.

So wie Kalenderdaten vom Typ boost::gregorian::date über den Aufruf von Methoden anderer Objekte und freistehender Funktionen erzeugt werden können, bietet Boost.DateTime entsprechende Objekte und freistehende Funktionen zum Erzeugen von Zeitpunkten an.

Beispiel 36.11. Einen Zeitpunkt von einer Uhr oder einem String erhalten
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/date_time/gregorian/gregorian.hpp>
#include <iostream>

using namespace boost::posix_time;

int main()
{
  ptime pt = second_clock::universal_time();
  std::cout << pt.date() << '\n';
  std::cout << pt.time_of_day() << '\n';

  pt = from_iso_string("20140512T120000");
  std::cout << pt.date() << '\n';
  std::cout << pt.time_of_day() << '\n';
}

Die Klasse boost::posix_time::second_clock repräsentiert eine Uhr, die die aktuelle Zeit zurückgibt. Die Methode universal_time(), die im Beispiel 36.11 aufgerufen wird, gibt die UTC-Uhrzeit zurück. Wenn Sie nicht die Weltzeit verwenden möchten, sondern die aktuelle Zeit in der Zeitzone, in der Sie sich befinden, rufen Sie local_time() auf.

Boost.DateTime bietet eine weitere Klasse boost::posix_time::microsec_clock an, die die aktuelle Uhrzeit einschließlich Mikrosekunden zurückgibt. Wenn Sie eine höhere Auflösung benötigen, können Sie diese Klasse verwenden.

Freistehende Funktionen wie boost::posix_time::from_iso_string() können verwendet werden, um einen Zeitpunkt von einem String in ein Objekt vom Typ boost::posix_time::ptime umzuwandeln. Die Funktion boost::posix_time::from_iso_string() setzt dabei voraus, dass der Zeitpunkt im String im ISO 8601-Format gespeichert ist.

Beispiel 36.12. Zeiträume mit boost::posix_time::time_duration erstellen
#include <boost/date_time/posix_time/posix_time.hpp>
#include <iostream>

using namespace boost::posix_time;

int main()
{
  time_duration td{16, 30, 0};
  std::cout << td.hours() << '\n';
  std::cout << td.minutes() << '\n';
  std::cout << td.seconds() << '\n';
  std::cout << td.total_seconds() << '\n';
}

Neben boost::posix_time::ptime bietet Boost.DateTime auch eine Klasse boost::posix_time::time_duration an, um einen Zeitraum zu beschreiben. Sie haben diese Klasse bereits gesehen, da der Konstruktor von boost::posix_time::ptime als zweiten Parameter ein Objekt vom Typ boost::posix_time::time_duration erwartet. Sie können die Klasse boost::posix_time::time_duration aber auch ohne boost::posix_time::ptime verwenden.

Während Sie mit hours(), minutes() und seconds() die Werte erhalten, die als Parameter dem Konstruktor übergeben wurden, können Sie mit Methoden wie total_seconds() auf einfache Weise zusätzliche Informationen erhalten. So gibt Ihnen total_seconds() die Anzahl aller Sekunden zurück.

Sie können dem Konstruktor von boost::posix_time::time_duration beliebige Werte übergeben. Es gibt also zum Beispiel keine Obergrenze von 24 Stunden.

So wie mit Kalenderdaten kann auch mit Zeitpunkten und Zeiträumen gerechnet werden.

Beispiel 36.13. Mit Zeitpunkten rechnen
#include <boost/date_time/posix_time/posix_time.hpp>
#include <iostream>

using namespace boost::posix_time;
using namespace boost::gregorian;

int main()
{
  ptime pt1{date{2014, 5, 12}, time_duration{12, 0, 0}};
  ptime pt2{date{2014, 5, 12}, time_duration{18, 30, 0}};
  time_duration td = pt2 - pt1;
  std::cout << td.hours() << '\n';
  std::cout << td.minutes() << '\n';
  std::cout << td.seconds() << '\n';
}

Wenn wie im Beispiel 36.13 zwei Zeitpunkte vom Typ boost::posix_time::ptime mit einem Minuszeichen verknüpft werden, erhalten Sie ein Objekt vom Typ boost::posix_time::time_duration, das den Zeitraum zwischen den beiden Zeitpunkten angibt.

Beispiel 36.14. Mit Zeiträumen rechnen
#include <boost/date_time/posix_time/posix_time.hpp>
#include <iostream>

using namespace boost::posix_time;
using namespace boost::gregorian;

int main()
{
  ptime pt1{date{2014, 5, 12}, time_duration{12, 0, 0}};
  time_duration td{6, 30, 0};
  ptime pt2 = pt1 + td;
  std::cout << pt2.time_of_day() << '\n';
}

Wie Sie am Beispiel 36.14 sehen, kann ein Zeitraum mit dem Pluszeichen auch zu einem Zeitpunkt hinzugefügt werden. In diesem Fall wird ein neuer Zeitpunkt erhalten. Obiges Programm gibt 18:30:00 auf die Standardausgabe aus.

Boost.DateTime verwendet für Kalenderdaten und beliebige Zeitpunkte die gleichen Konzepte. So wie es jeweils eine Klasse gibt, die einen Zeitpunkt und einen Zeitraum beschreibt, gibt es auch eine Klasse, die ein Zeitintervall repräsentiert. Für Kalenderdaten heißt diese Klasse boost::gregorian::date_period, für beliebige Zeitpunkte boost::posix_time::time_period. Und so wie der Konstruktor von boost::gregorian::date_period als Parameter zwei Kalenderdaten erwartet, müssen dem Konstruktor von boost::posix_time::time_period zwei Zeitpunkte übergeben werden.

Beispiel 36.15. Zeitintervalle mit boost::posix_time::time_period erstellen
#include <boost/date_time/posix_time/posix_time.hpp>
#include <iostream>

using namespace boost::posix_time;
using namespace boost::gregorian;

int main()
{
  ptime pt1{date{2014, 5, 12}, time_duration{12, 0, 0}};
  ptime pt2{date{2014, 5, 12}, time_duration{18, 30, 0}};
  time_period tp{pt1, pt2};
  std::cout.setf(std::ios::boolalpha);
  std::cout << tp.contains(pt1) << '\n';
  std::cout << tp.contains(pt2) << '\n';
}

Die Klasse boost::posix_time::time_period funktioniert genauso wie boost::gregorian::date_period. So wird unter anderem eine Methode contains() angeboten, die für jeden Zeitpunkt, der sich innerhalb des Zeitintervalls befindet, true zurückgibt. Da der Zeitpunkt, der dem Konstruktor von boost::posix_time::time_period als zweiter Parameter übergeben wurde, gerade nicht mehr zum Zeitintervall zählt, gibt Beispiel 36.15 beim zweiten Aufruf von contains() false zurück.

Neben contains() bietet boost::posix_time::time_period weitere Methoden an wie intersection(), um eine Schnittmenge zweier Zeitintervalle zu ermitteln, oder merge(), um zwei Zeitintervalle, die sich überschneiden, zu einem neuen Zeitintervall zu vereinigen.

Abschließend soll der Iterator boost::posix_time::time_iterator vorgestellt werden, mit dem über Zeitpunkte iteriert werden kann.

Beispiel 36.16. Mit Iteratoren auf Zeitpunkte zugreifen
#include <boost/date_time/local_time/local_time.hpp>
#include <iostream>

using namespace boost::posix_time;
using namespace boost::gregorian;

int main()
{
  ptime pt{date{2014, 5, 12}, time_duration{12, 0, 0}};
  time_iterator it{pt, time_duration{6, 30, 0}};
  std::cout << *++it << '\n';
  std::cout << *++it << '\n';
}

Im Beispiel 36.16 wird der Iterator it verwendet, um ausgehend vom Zeitpunkt pt jeweils sechseinhalb Stunden vorwärts zu springen. Da der Iterator zweimal inkrementiert wird, gibt das Programm entsprechend 2014-May-12 18:30:00 und 2014-May-13 01:00:00 aus.