El estándar C dice en 7.27.1 Componentes del tiempo:
La tm
estructura deberá contener al menos los siguientes miembros, en cualquier orden. La semántica de los miembros y sus rangos normales se expresan en los comentarios. 318)
int tm_sec; // seconds after the minute — [0, 60]
int tm_min; // minutes after the hour — [0, 59]
int tm_hour; // hours since midnight — [0, 23]
int tm_mday; // day of the month — [1, 31]
int tm_mon; // months since January — [0, 11]
int tm_year; // years since 1900
int tm_wday; // days since Sunday — [0, 6]
int tm_yday; // days since January 1 — [0, 365]
int tm_isdst; // Daylight Saving Time flag
(el énfasis es mío)
Es decir, las implementaciones pueden agregar miembros adicionales a tm
, como se encontró con glibc/time/bits/types/struct_tm.h
. La especificación POSIX tiene una redacción casi idéntica.
El resultado es que %Z
(o incluso %z
) no puede considerarse portátil en strftime
. La especificación para %Z
refleja esto:
%Z
se reemplaza por el nombre o la abreviatura de la zona horaria de la localidad, o por ningún carácter si no se puede determinar la zona horaria. [tm_isdst]
Es decir, a los vendedores se les permite levantar las manos y simplemente decir: "ninguna zona horaria era determinable, por lo que no estoy mostrando ningún carácter".
Mi opinión: la API de sincronización C es un desastre.
Estoy intentando mejorar las cosas para el próximo estándar C ++ 20 dentro de la <chrono>
biblioteca.
La especificación C ++ 20 cambia esto de "sin caracteres" a una excepción que se genera si la time_zone
abreviatura no está disponible:
http://eel.is/c++draft/time.format#3
A menos que se solicite explícitamente, el resultado de formatear un tipo crono no contiene la abreviatura de zona horaria ni la información de compensación de zona horaria. Si la información está disponible, los especificadores de conversión %Z
y %z
formatearán esta información (respectivamente). [ Nota: Si la información no está disponible y una %Z
o %z
indicador de conversión aparece en el formato de las especificaciones crono , una excepción de tipo format_error
se tira, como se describió anteriormente. - nota final ]
Excepto que el párrafo anterior no describe C strftime
, sino una nueva format
función que opera en std::chrono
tipos, no tm
. Además, hay un nuevo tipo: std::chrono::zoned_time
( http://eel.is/c++draft/time.zone.zonedtime ) que siempre tiene disponible la time_zone
abreviatura (y el desplazamiento) y puede formatearse con la format
función mencionada anteriormente .
Código de ejemplo:
#include <chrono>
#include <iostream>
int
main()
{
using namespace std;
using namespace std::chrono;
auto now = system_clock::now();
std::cout << format("%Z\n", zoned_time{current_zone(), now}); // HKT (or whatever)
std::cout << format("%Z\n", zoned_time{"Asia/Hong_Kong", now}); // HKT or HKST
std::cout << format("%Z\n", zoned_time{"Etc/UTC", now}); // UTC
std::cout << format("%Z\n", now); // UTC
}
(Descargo de responsabilidad: format
es probable que la sintaxis final de la cadena de formato en la función sea ligeramente diferente, pero la funcionalidad estará allí).
Si desea experimentar con una vista previa de esta biblioteca, es gratuita y de código abierto aquí: https://github.com/HowardHinnant/date
Se requiere alguna instalación: https://howardhinnant.github.io/date/tz.html#Installation
En esta vista previa, deberá usar el encabezado "date/tz.h"
, y los contenidos de la biblioteca están en namespace date
lugar de namespace std::chrono
.
La biblioteca de vista previa se puede usar con C ++ 11 o posterior.
zoned_time
tiene una plantilla std::chrono::duration
que especifica la precisión del punto de tiempo y se deduce en el código de ejemplo anterior utilizando la función CTAD de C ++ 17 . Si está utilizando esta biblioteca de vista previa en C ++ 11 o C ++ 14, la sintaxis se parecería más a:
cout << format("%Z\n", zoned_time<system_clock::duration>{current_zone(), now});
O hay una función auxiliar de fábrica no propuesta para la estandarización que hará la deducción por usted:
cout << format("%Z\n", make_zoned(current_zone(), now));
(#CTAD_eliminates_factory_functions)
tm
no contiene información de zona horaria.strftime
obtiene la zona horaria mediante el vudú detrás de escena. Si desea obtener la zona horaria en general, eso es un poco complicado. No existe ( actualmente ) una forma estándar de obtener una zona horaria. Afortunadamente Howard Hinnant es en ese trabajo ... .