Operações com Tempo em C++

por Fabio A. Mazzarino

A versão C++11 da linguagem C++ incluiu um novo conjunto de classes, funções e tipos para manipulação de tempo. O namespace std::chrono contém algumas ferramentas que trazem para a linguagem C++ o que até então somente estava disponível através do header <time.h> do C.

A lista de classes declaradas nesse namespace:

  • std::chrono::duration – expressa uma diferença de tempo
  • std::chrono::time_point – expressa um tempo específico relativo a epoch.
  • std::chrono::system_clock – acesso ao relógio do sistema
  • std::chrono::steady_clock – ferramentas para calcular intervalos de tempo
  • std::chrono::high_resolution_clock – acesso ao relógio do sistema em alta resolução de tempo

Foram definidos também um conjunto de std::ratio:

  • std::chrono::hours – expressão de tempo em horas
  • std::chrono::minutes – expressão de tempo em minutos
  • std::chrono::seconds – expressão de tempo em segundos
  • std::chrono::miliseconds – expressão de tempo em milisegundo
  • std::chrono::microseconds – expressão de tempo em microssegundos
  • std::chrono::nonoseconds – expressão de tempo em nanossegundos

E ainda as funções de conversão:

  • std::chrono::duration_cast – conversão entre medidas de tempo
  • std::chrono::time_point_cast – conversão entre timestamps

Obs.: Não foram incluidas as funcionalidades adicionados no C++20 propositalmente. Infelizmente isso inclui as funções de calendário, que poderão ser abordadas num futuro próximo.

Mas chega de lero-lero, e vamos colocar a mão na massa com um exemplo usando aritmética de tempo usando .

#include <chrono>
#include <ctime>
#include <iostream>
int main() {
    std::chrono::system_clock::time_point now = std::chrono::system_clock::now();
    std::chrono::hours anhour(1);
    std::chrono::hours twodays(24 * 2);
    std::chrono::system_clock::time_point anhourago = now - anhour;
    std::chrono::system_clock::time_point tomorrow = now + twodays;
    // infelizmente ainda dependemos do time.h
    ::time_t tt = std::chrono::system_clock::to_time_t(anhourago);
    std::cout << "An hour ago: " << ::ctime(&tt);
    tt = std::chrono::system_clock::to_time_t(tomorrow);
    std::cout << "Tomorrow:    " << ::ctime(&tt);
}

Vai retornar a saída:

An hour ago: Wed Jul 29 10:26:43 2020
Tomorrow:    Fri Jul 31 11:26:43 2020

Note como utilizamos a aritmética do tipo time_point, é realmente muito simples. Vamos testar também duration com steady_clock.

#include <chrono>
#include <iomanip>
#include <iostream>
#include <unistd.h>
long fib(unsigned n) {
    if (n == 0)
        return 0;
    if (n == 1)
        return 1;
    return fib(n - 2) + fib(n - 1);
}
int main() {
    for (int ct = 0; ct <= 50; ct++) {
        std::chrono::steady_clock::time_point t1 = std::chrono::steady_clock::now();
        long result = fib(ct);
        std::chrono::steady_clock::time_point t2 = std::chrono::steady_clock::now();
        std::chrono::duration<double> dt = 
            std::chrono::duration_cast<std::chrono::duration<double> >(t2 - t1);
        std::cout << "dt(" << ct << "): " <<
            std::fixed << std::setprecision(6) << dt.count() * 1000 << " ms" << std::endl;
   }
}

No exemplo acima calculamos várias vezes a mesma função, e medimos o tempo de execução, com precisão maior que milissegundos.

O namespace chrono ficou muito mais completo com C++20, mas são poucas as plataformas que suportam essa versão. Em breve vamos poder abordar esse assunto com novas funções e muito mais facilidade.