Trabalho Avançado com Datas e Horas em C++: chrono, time_t e Parsing

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Introdução: Por que o trabalho padrão com tempo em C++ se tornou mais complexo (e melhor)

Por muito tempo, o trabalho com datas e horas em C++ se resumia ao uso de funções de <ctime>: time(), localtime(), strftime(). Isso era suficiente para tarefas simples, mas com o aumento da complexidade dos projetos (sistemas distribuídos, servidores de alta carga, aplicações financeiras), tornaram-se necessárias ferramentas mais precisas, seguras e convenientes.

O padrão C++11 nos presenteou com a biblioteca <chrono>, que resolve problemas de estouro, confusão com unidades de medida e dependência de plataforma. O C++20 deu um passo importante, adicionando suporte a fusos horários, tipos de calendário e formatação via std::format. Neste artigo, exploraremos técnicas avançadas que vão além da simples obtenção da hora atual.



1. Biblioteca chrono: de milissegundos a nanossegundos e calendários

O núcleo de std::chrono são três componentes: relógio (clock), duração (duration) e ponto no tempo (time_point). Em nível avançado, é importante saber escolher o relógio correto e trabalhar com aritmética de tempo.



1.1. Escolha do relógio: system_clock, steady_clock, high_resolution_clock

  • system_clock — representa o tempo do sistema (calendário). Pode ser ajustado pelo usuário ou por serviço de sincronização (NTP). Usado para exibir data ao usuário.
  • steady_clock — relógio monotônico. Nunca é ajustado para trás (no rollback). Ideal para medir intervalos (temporizadores, perfilamento).
  • high_resolution_clock — relógio com o menor tick possível. Na maioria das plataformas, é sinônimo de steady_clock.

Dica avançada: Nunca use high_resolution_clock para perfilamento se precisar de estabilidade. Use steady_clock.



1.2. Trabalhando com duration e time_point

Trabalho avançado implica não apenas medir tempo, mas converter entre unidades, fazer aritmética e usar tipos personalizados.

#include <iostream>#include <chrono>#include <thread>

int main() { using namespace std::chrono_literals; // para sufixos ms, s, us

// Criação avançada de duration auto work_time = 2h + 30min + 15s; // 2 horas 30 minutos 15 segundos std::cout << "Tempo de trabalho em segundos: " << work_time.count() << " s";

// Conversão com arredondamento (duration_cast) auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(work_time); std::cout << "Em milissegundos: " << ms.count() << " ms";

// Medição do tempo de execução de uma função auto start = std::chrono::steady_clock::now(); std::this_thread::sleep_for(100ms); // simulação de trabalho auto end = std::chrono::steady_clock::now(); auto elapsed = std::chrono::duration_cast<std::chrono::microseconds>(end - start); std::cout << "Função executou em: " << elapsed.count() << " µs";

return 0;}


1.3. Tipos de calendário (C++20)

C++20 adicionou year_month_day, year_month, weekday e outros. Isso permite manipular datas com segurança, sem trabalhar com números brutos.

#include <iostream>#include <chrono>

int main() { using namespace std::chrono;

// Criação de data auto date = 2023y / October / 15d; // 15 de outubro de 2023 std::cout << "Data: " << date << '';

// Adição de dias auto next_week = date + days(7); std::cout << "Daqui a uma semana: " << next_week << '';

// Obtenção do dia da semana weekday wd{date}; std::cout << "Dia da semana: " << wd << '';

return 0;}


2. time_t e funções clássicas: quando ainda são úteis

Apesar do poder do <chrono>, time_t e funções de <ctime> ainda são amplamente usados para interoperabilidade com APIs C, bancos de dados e formatos de arquivo legados.



2.1. Convertendo entre time_t e chrono

Muitas vezes você precisa obter um time_t de um system_clock::time_point ou vice-versa.

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

int main() { // Obtendo time_point atual auto now = std::chrono::system_clock::now();

// Convertendo para time_t std::time_t tt = std::chrono::system_clock::to_time_t(now); std::cout << "Hora atual (time_t): " << std::ctime(&tt);

// Convertendo time_t de volta para time_point auto time_point = std::chrono::system_clock::from_time_t(tt);

return 0;}


2.2. Parsing de strings com strptime (POSIX)

Em sistemas POSIX (Linux, macOS), a função strptime() permite analisar strings de data de acordo com um formato especificado. Isso é útil para processar logs ou entrada do usuário.

#include <iostream>#include <ctime>

int main() { const char* date_str = "2023-10-15 14:30:00"; struct tm tm = {};

if (strptime(date_str, "%Y-%m-%d %H:%M:%S", &tm)) { std::time_t t = std::mktime(&tm); std::cout << "Timestamp Unix: " << t << ''; } else { std::cerr << "Falha ao analisar a string de data"; }

return 0;}


3. Fusos horários em C++20: trabalhando com time zones

Um dos recursos mais esperados do C++20 é o suporte a fusos horários através do cabeçalho <chrono>. Agora você pode converter entre fusos horários sem bibliotecas externas como Boost.



3.1. Obtendo a hora atual em um fuso horário específico

#include <iostream>#include <chrono>#include <format>

int main() { using namespace std::chrono;

auto now = system_clock::now();

// Convertendo para o fuso horário de São Paulo auto sp_time = zoned_time{"America/Sao_Paulo", now}; std::cout << "Hora em São Paulo: " << sp_time << '';

// Convertendo para o fuso horário de Tóquio auto tokyo_time = zoned_time{"Asia/Tokyo", now}; std::cout << "Hora em Tóquio: " << tokyo_time << '';

return 0;}


3.2. Diferença entre fusos horários e horário de verão

O sistema de fusos horários do C++20 leva em conta automaticamente o horário de verão (DST). Você pode obter informações sobre o deslocamento atual.

#include <iostream>#include <chrono>

int main() { using namespace std::chrono;

auto now = system_clock::now(); auto tz = locate_zone("America/New_York"); auto info = tz->get_info(now);

std::cout << "Deslocamento atual: " << info.offset << ''; std::cout << "Abreviação: " << info.abbrev << ''; std::cout << "Está em horário de verão? " << (info.save != minutes{0} ? "Sim" : "Não") << '';

return 0;}


4. Formatação de data e hora com std::format (C++20)

O C++20 introduziu std::format, que oferece uma maneira poderosa e flexível de formatar datas e horas. Você pode usar especificadores de formato semelhantes ao Python ou ao strftime.



4.1. Exemplos básicos de formatação

#include <iostream>#include <chrono>#include <format>

int main() { using namespace std::chrono;

auto now = system_clock::now();

// Formatando data e hora std::cout << std::format("Data: {:%Y-%m-%d}", now); std::cout << std::format("Hora: {:%H:%M:%S}", now); std::cout << std::format("Data e hora completas: {:%c}", now);

// Formatando com fuso horário auto sp_time = zoned_time{"America/Sao_Paulo", now}; std::cout << std::format("Hora em São Paulo: {:%Y-%m-%d %H:%M:%S %Z}", sp_time);

return 0;}


4.2. Especificadores de formato personalizados

Você pode criar formatos complexos combinando especificadores. Aqui estão alguns dos mais úteis:

  • %Y — ano com 4 dígitos
  • %m — mês com 2 dígitos (01-12)
  • %d — dia do mês com 2 dígitos (01-31)
  • %H — hora no formato 24h (00-23)
  • %M — minutos (00-59)
  • %S — segundos (00-59)
  • %Z — abreviação do fuso horário
  • %z — deslocamento do fuso horário no formato ISO 8601


5. Temporizadores de alta precisão e perfilamento

Para medir o desempenho do código com alta precisão, use steady_clock e duration_cast. Evite clock() e gettimeofday().



5.1. Medindo o tempo de execução de uma função

#include <iostream>#include <chrono>

void expensive_function() { // Simula trabalho pesado volatile int sum = 0; for (int i = 0; i < 1000000; ++i) { sum += i; }}

int main() { auto start = std::chrono::steady_clock::now(); expensive_function(); auto end = std::chrono::steady_clock::now();

auto diff = end - start; auto ns = std::chrono::duration_cast<std::chrono::nanoseconds>(diff); auto us = std::chrono::duration_cast<std::chrono::microseconds>(diff); auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(diff);

std::cout << "Tempo de execução:"; std::cout << " Nanossegundos: " << ns.count() << ''; std::cout << " Microssegundos: " << us.count() << ''; std::cout << " Milissegundos: " << ms.count() << '';

return 0;}


5.2. Criando um temporizador de intervalo simples

Às vezes você precisa executar uma ação em intervalos regulares. Use steady_clock e sleep_until para precisão.

#include <iostream>#include <chrono>#include <thread>

int main() { using namespace std::chrono_literals;

auto next = std::chrono::steady_clock::now(); const auto interval = 500ms; // 500 milissegundos

for (int i = 0; i < 5; ++i) { next += interval; std::this_thread::sleep_until(next); std::cout << "Tick " << i+1 << ''; }

return 0;}


6. Parsing avançado de strings de data

Além do strptime, o C++20 oferece std::chrono::parse para analisar strings de data de forma segura e flexível.



6.1. Usando std::chrono::parse

#include <iostream>#include <chrono>#include <sstream>

int main() { std::string date_str = "2023-10-15 14:30:00"; std::chrono::sys_seconds tp; std::istringstream iss(date_str);

if (iss >> std::chrono::parse("%Y-%m-%d %H:%M:%S", tp)) { std::cout << "Timestamp analisado: " << tp << ''; } else { std::cerr << "Falha ao analisar a string"; }

return 0;}


6.2. Tratamento de erros e formatos flexíveis

std::chrono::parse suporta muitos especificadores de formato e pode lidar com espaços em branco opcionais. Você também pode analisar datas com fusos horários.

#include <iostream>#include <chrono>#include <sstream>

int main() { std::string date_str = "2023-10-15T14:30:00-03:00"; std::chrono::sys_seconds tp; std::istringstream iss(date_str);

if (iss >> std::chrono::parse("%Y-%m-%dT%H:%M:%S%z", tp)) { std::cout << "Timestamp analisado: " << tp << ''; } else { std::cerr << "Falha ao analisar a string"; }

return 0;}


Conclusão

A biblioteca <chrono> do C++ moderno oferece ferramentas poderosas e seguras para trabalhar com tempo. Desde medições de alta precisão até manipulação de fusos horários e formatação flexível, você pode resolver problemas complexos sem recorrer a bibliotecas externas. Dominar esses recursos tornará seu código mais confiável, portátil e fácil de manter.

Comece a usar std::chrono hoje e eleve seu trabalho com tempo em C++ a um novo nível!

Blogs

Book Recommendations