O padrão C diz em 7.27.1 Componentes do tempo:
A tm
estrutura deve conter pelo menos os seguintes membros, em qualquer ordem. A semântica dos membros e seus intervalos normais são expressos nos comentários. 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
(ênfase é minha)
Ou seja, as implementações têm permissão para adicionar membros adicionais tm
, como você encontrou glibc/time/bits/types/struct_tm.h
. A especificação POSIX possui uma redação quase idêntica.
O resultado é que %Z
(ou mesmo %z
) não pode ser considerado portátil strftime
. A especificação para %Z
reflete isso:
%Z
é substituído pelo nome ou abreviação do fuso horário da localidade ou por nenhum caractere se nenhum fuso horário for determinável. [tm_isdst]
Ou seja, os fornecedores podem levantar as mãos e simplesmente dizer: "nenhum fuso horário era determinável; portanto, não estou produzindo nenhum caractere".
Minha opinião: a API de tempo C é uma bagunça.
Estou tentando melhorar as coisas para o próximo padrão C ++ 20 na <chrono>
biblioteca.
A especificação do C ++ 20 altera isso de "sem caracteres" para uma exceção sendo lançada se a time_zone
abreviação não estiver disponível:
http://eel.is/c++draft/time.format#3
A menos que seja solicitado explicitamente, o resultado da formatação de um tipo de cronômetro não contém abreviação de fuso horário e informações de deslocamento de fuso horário. Se as informações estiverem disponíveis, os especificadores de conversão %Z
e %z
formatarão essas informações (respectivamente). [ Nota: Se as informações não estiverem disponíveis e um
especificador de conversão %Z
ou %z
aparecer na especificação de formato de cronômetro , uma exceção do tipo format_error
será lançada, conforme descrito acima. - nota final ]
Exceto que o parágrafo acima não está descrevendo Cs strftime
, mas uma nova format
função que opera em std::chrono
tipos, não tm
. Além disso, existe um novo tipo: std::chrono::zoned_time
( http://eel.is/c++draft/time.zone.zonedtime ) que sempre tem a time_zone
abreviação (e deslocamento) disponível e pode ser formatada com a format
função mencionada anteriormente .
Código de exemplo:
#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
}
(Isenção de responsabilidade: a sintaxe final da string de formatação na format
função provavelmente será um pouco diferente, mas a funcionalidade estará lá.)
Se você deseja experimentar uma prévia desta biblioteca, ela é gratuita e de código aberto aqui: https://github.com/HowardHinnant/date
Alguma instalação é necessária: https://howardhinnant.github.io/date/tz.html#Installation
Nesta visualização, você precisará usar o cabeçalho "date/tz.h"
e o conteúdo da biblioteca está em namespace date
vez de namespace std::chrono
.
A biblioteca de visualização pode ser usada com C ++ 11 ou posterior.
zoned_time
é modelado em um std::chrono::duration
que especifica a precisão do ponto no tempo e é deduzido no código de exemplo acima, usando o recurso CTAD do C ++ 17 . Se você estiver usando esta biblioteca de visualização no C ++ 11 ou C ++ 14, a sintaxe seria mais parecida com:
cout << format("%Z\n", zoned_time<system_clock::duration>{current_zone(), now});
Ou existe uma função auxiliar de fábrica não proposta para padronização que fará a dedução para você:
cout << format("%Z\n", make_zoned(current_zone(), now));
(#CTAD_eliminates_factory_functions)
tm
não contém informações de fuso horário.strftime
obtém o fuso horário pelo vodu nos bastidores. Se você deseja obter o fuso horário em geral, isso é uma bagunça. Existe ( atualmente ) nenhuma maneira padrão para obter um fuso horário. Felizmente Howard Hinnant está em que trabalho ... .