Puede haber tantas maneras de representar fechas como el número de países o de idiomas. Algunas de las abreviaciones más ampliamente usadas son dd-mm-yy, mm-dd-yy, yy-mm-dd.

Hay varios ámbitos en los cuales es importante que se puedan interpretar fechas y horas sin ambigüedad; para este fin existe el estándar ISO 86011 con formato YYYY-MM-DD, aplicable para representar fechas del calendario gregoriano. Este estándar también incluye la representación de hora, extendiéndola a YYYY-MM-DD HH:mm:ss. También se puede usar la representación de hora local poniendo la letra T entre la fecha y la hora. Adicionalmente se puede representar la zona horaria UTC: hora local relativa a la UTC (Tiempo Universal Coordinado).

En total YYYY-MM-DDTHH:mm:ss Z corresponde a 2021-04-15T18:20:28-0500 donde año: 2021, mes: 04, día: 15, T: hora local, 18 horas (6 p.m.), 20 minutos, 28 segundos, con UTC: -0500.

Este formato incluye otros campos y aspectos adicionales no analizados acá.

Usando iostreams

Como casi todo en C++, hay múltiples maneras de resolver una tarea. La forma tradicional es usar iostreams con std::put_time para la visualización.
Para obtener los valores con std::time al estilo C:

#include <ctime>    // Para std::time
#include <iomanip>  // Para std::put_time
#include <iostream>

int main()
{
  const std::time_t now_time_t = std::time(nullptr);
  const std::tm     now_tm     = *(std::localtime(&now_time_t));
  std::cout << std::put_time(&now_tm, "%Y-%m-%dT%T%z");
  return 0;
}

O con std::chrono::system_clock al estilo C++:

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

using std::chrono::system_clock;

int main()
{
  const std::time_t now_time_t = system_clock::to_time_t(system_clock::now());
  const std::tm     now_tm     = *(std::localtime(&now_time_t));
  std::cout << std::put_time(&now_tm, "%Y-%m-%dT%T%z");
  return 0;
}

Donde la representación "%Y-%m-%d T %T%z" corresponde a YYYY-MM-DD T HH:mm:ss Z según los especificadores de std::put_time2.

std::put_time ISO 8601
%Y YYYY
%m MM
%d DD
%T HH:mm:ss
%z Z

Usando la biblioteca {fmt}

Una forma interesante de hacer esta misma representación es usar la biblioteca fmt (usando Conan como administrador de paquetes ) para poder hacer una manipulación thread-safe y más robusta.
Con std::time:

#include <fmt/chrono.h>

int main()
{
  const std::time_t now = std::time(nullptr);
  fmt::print("{:%Y-%m-%dT%H:%M:%S%z}\n", fmt::localtime(now));

  return 0;
}

Con std::chrono::system_clock y fmt se puede usar directamente std::chrono::time_point por lo cual no hace falta convertir el objeto a std::time_t; incluso se genera un binario de menor tamaño.

#include <fmt/chrono.h>

using std::chrono::system_clock;

int main()
{
  fmt::print("{0:%Y-%m-%d}T{0:%H:%M:%S%z}\n", 
             fmt::localtime(system_clock::now()));

  return 0;
}

En todos los casos el posible resultado, teniendo en cuenta la zona horaria (UTC-5), es:

2021-04-15T18:20:28-0500

Hora con mili segundos

Obtener los milisegundos con std::time_t es complejo y no vale la pena analizarlo ahora mismo; con std::chrono::time_point es un poco menos complejo:

#include <fmt/chrono.h>

using std::chrono::duration_cast;
using std::chrono::milliseconds;
using std::chrono::system_clock;
using std::chrono::time_point;

int main()
{
  const time_point<system_clock> time_now = system_clock::now();
  const auto now_ms = (duration_cast<milliseconds>(time_now.time_since_epoch()) % 1000).count();
  fmt::print("{0:%Y-%m-%dT%H:%M:%S}.{1}{0:%z}\n", fmt::localtime(time_now), now_ms);

  return 0;
}

Obteniendo:

2021-04-15T18:20:28.157-0500

La biblioteca spdlog

Es una biblioteca de registro de mensajes con un desempeño sobresaliente. Internamente usa a fmt y por defecto muestra los mensajes de registro con la fecha-hora en el formato ISO_8601. En este ejemplo se usa la referencia a la receta de conan spdlog/1.8.2, y su uso es el siguiente:

#include <spdlog/spdlog.h>

int main() 
{
  spdlog::info("Hola spdlog");

  return 0;
}

Con lo cual se obtiene:

[2021-04-15 18:20:28.157] [info] Hola spdlog

Fuentes


Deja un comentario