El estándar C dice en 7.27.1 Componentes del tiempo:
La tmestructura 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 %Zrefleja esto:
%Zse 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_zoneabreviatura 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 %Zy %zformatearán esta información (respectivamente). [ Nota: Si la información no está disponible y una %Zo %z
indicador de conversión aparece en el formato de las especificaciones crono , una excepción de tipo format_errorse tira, como se describió anteriormente. - nota final ]
Excepto que el párrafo anterior no describe C strftime, sino una nueva formatfunción que opera en std::chronotipos, 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_zoneabreviatura (y el desplazamiento) y puede formatearse con la formatfunció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: formates 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 datelugar de namespace std::chrono.
La biblioteca de vista previa se puede usar con C ++ 11 o posterior.
zoned_timetiene una plantilla std::chrono::durationque 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)
tmno contiene información de zona horaria.strftimeobtiene 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 ... .