Zeitzonen in C++20: Online-Klassen

Heute fahre ich damit fort, die Funktionalität der Zeitzonen der C++20 Chrono-Erweiterung vorzustellen.

In Pocket speichern vorlesen Druckansicht
Globus vor Weltkarte

(Bild: Triff / Shutterstock.com)

Lesezeit: 3 Min.
Von
  • Rainer Grimm

Dieser Artikel ist der Achte in meiner detaillierten Reise durch die Chrono-Erweiterung in C++20:

Modernes C++ – Rainer Grimm

Rainer Grimm ist seit vielen Jahren als Softwarearchitekt, Team- und Schulungsleiter tätig. Er schreibt gerne Artikel zu den Programmiersprachen C++, Python und Haskell, spricht aber auch gerne und häufig auf Fachkonferenzen. Auf seinem Blog Modernes C++ beschäftigt er sich intensiv mit seiner Leidenschaft C++.

Das Programm onlineClass.cpp beantwortet die folgende Frage: Wie spät ist es in bestimmten Zeitzonen, wenn ich einen Online-Kurs um 7 Uhr, 13 Uhr oder 17 Uhr Ortszeit (Deutschland) beginne?

Der Online-Kurs soll am 1. Februar 2021 beginnen und 4 Stunden dauern. Wegen der Sommerzeit ist das Kalenderdatum wichtig, um die richtige Antwort zu erhalten.

#include <chrono>
#include <algorithm>
#include <iomanip>
#include <iostream>

using namespace std::chrono_literals;

template <typename ZonedTime>
auto getMinutes(const ZonedTime& zonedTime) {                               // (1)              
    return std::chrono::floor<std::chrono::minutes>(zonedTime.get_local_time());
}

void printStartEndTimes(const std::chrono::local_days& localDay,           // (2) 
                        const std::chrono::hours& h, 
                        const std::chrono::hours& durationClass,
                        const std::initializer_list<std::string>& timeZones ) {
    
    std::chrono::zoned_time startDate{std::chrono::current_zone(), localDay + h}; // (4)  
    std::chrono::zoned_time endDate{std::chrono::current_zone(), 
                                    localDay + h + durationClass};
    std::cout << std::format("Local time: [{}, {}]\n", getMinutes(startDate), getMinutes(endDate));
                                                                                
    auto longestStringSize = std::max(timeZones, [](const std::string& a,  // (5) 
                       const std::string& b) { return a.size() < b.size(); }).size();

    std::string formatTimeZones = "  {0:<{3}} [{1}, {2}]\n";              // (7) 
    for (auto timeZone: timeZones) {                                      // (6) 
        std::cout << std::vformat(formatTimeZones, std::make_format_args(timeZone, 
                                                            getMinutes(std::chrono::zoned_time(timeZone, startDate)),
                                                            getMinutes(std::chrono::zoned_time(timeZone, endDate)),
                                                            longestStringSize + 1));                             
    }
 }

int main() {

    using namespace std::string_literals;
    
    std::cout << '\n';

    constexpr auto classDay{std::chrono::year(2021)/2/1};
    constexpr auto durationClass = 4h;
    auto timeZones = {"America/Los_Angeles"s, "America/Denver"s, 
                      "America/New_York"s, "Europe/London"s, 
                      "Europe/Minsk"s, "Europe/Moscow"s, 
                      "Asia/Kolkata"s, "Asia/Novosibirsk"s, 
                      "Asia/Singapore"s, "Australia/Perth"s, 
                      "Australia/Sydney"s};

    for (auto startTime: {7h, 13h, 17h}) {                              // (3) 
        printStartEndTimes(std::chrono::local_days{classDay}, startTime, 
                           durationClass, timeZones);
        std::cout << '\n';
    }

    std::cout << '\n';

}

Bevor ich auf die Funktionen getMinutes (Zeile 1) und printStartEndTimes (Zeile 2) eingehe, möchte ich noch ein paar Worte über die main-Funktion verlieren. Die main-Funktion legt den Tag des Unterrichts, die Dauer des Unterrichts und alle Zeitzonen fest. Schließlich durchläuft die range-based for-Schleife (Zeile 3) alle möglichen Startpunkte für einen Online-Kurs. Alle notwendigen Informationen werden dank dieser Funktion dargestellt (Zeile 2).

Die wenigen Zeilen, die mit Zeile (4) beginnen, berechnen das startDate und endDate meiner Schulung, indem sie die Start- und Unterrichtsdauer zum Kalenderdatum addieren. Beide Werte werden mithilfe der Funktion getMinutes (Zeile 1) angezeigt. std::floor<std::chrono::minutes>(zonedTime.get_local_time()) holt den gespeicherten Zeitpunkt aus der std::chrono::zoned_time und schneidet den Wert auf die Minutenauflösung ab. Um die Ausgabe des Programms richtig auszurichten, bestimmt Zeile (5) die Größe des längsten aller Zeitzonennamen. Zeile (6) iteriert durch alle Zeitzonen und zeigt den Namen dieser sowie den Beginn und das Ende jeder Online-Klasse an. Ein paar Kalenderdaten überschreiten sogar die Tagesgrenzen.

Der Formatstring in Zeile 7 " {0:<{3}} [{1}, {2}]\n" verdient ein paar Worte. Dieser lValue erfordert die Funktionen std::vformat und std::make_format_args. Die Zahl im Formatstring steht für die Position in den Argumenten. Die {3} ist ein Platzhalter für den längsten Zeitzonennamen.

Chrono I/O besteht aus dem Lesen und Schreiben der Chronotypen. Die verschiedenen Datentypen unterstützen das unformatierte Schreiben und das formatierte Schreiben mit der neuen Formatierungsbibliothek. Diese Bibliothek verfügt auch über die Funktion std::chrono::parse(), die das Lesen aus einem Stream sehr leistungsfähig macht. ()