Como imprimir a hora no formato: 2009-08-10 18: 17: 54.811

95

Qual é o melhor método para imprimir a hora em C no formato 2009‐08‐10 
18:17:54.811?

Dominic Bou-Samra
fonte

Respostas:

107

Use strftime () .

#include <stdio.h>
#include <time.h>

int main()
{
    time_t timer;
    char buffer[26];
    struct tm* tm_info;

    timer = time(NULL);
    tm_info = localtime(&timer);

    strftime(buffer, 26, "%Y-%m-%d %H:%M:%S", tm_info);
    puts(buffer);

    return 0;
}

Por parte dos milissegundos, dê uma olhada nesta pergunta. Como medir o tempo em milissegundos usando ANSI C?

Hamid Nazari
fonte
É uma resposta ainda melhor agora, e adereços para descobrir como lidar com a parte do milissegundo. Eu acho que seu buffer agora é um pouco mais longo do que o necessário.
Jack Kelly,
14
Melhor ser mais longo do que mais curto :-)
paxdiablo
Excelente resposta. Eu poderia fazer todo tipo de coisa em PHP, mas sabia que já estava tudo lá no C. Obrigado.
Vijay Kumar Kanta
1
Talvez a linha time(&timer)deva ser timer = time(NULL);, pelo menos para Linux. The tloc argument is obsolescent and should always be NULL in new code. When tloc is NULL, the call cannot fail.
Antonin Décimo
5
A resposta está definitivamente errada em pelo menos um caso (Linux), pois "struct tm" usado por localtime () não contém nenhuma informação de tempo abaixo dos segundos. Em vez disso, "struct timeval" usado por gettimeofday () tem microssegundos que, dividido por 1000, resultará em milissegundos. Todos esses votos positivos estão realmente errados e enganosos! A menos que alguém informe sob qual arquitetura você obtém detalhes de tempo abaixo do segundo com "struct tm".
EnzoR
30

As respostas acima não respondem totalmente à pergunta (especificamente a parte dos milissegundos). Minha solução para isso é usar gettimeofday antes de strftime. Observe o cuidado para evitar arredondar milissegundos para "1000". Isso é baseado na resposta de Hamid Nazari.

#include <stdio.h>
#include <sys/time.h>
#include <time.h>
#include <math.h>

int main() {
  char buffer[26];
  int millisec;
  struct tm* tm_info;
  struct timeval tv;

  gettimeofday(&tv, NULL);

  millisec = lrint(tv.tv_usec/1000.0); // Round to nearest millisec
  if (millisec>=1000) { // Allow for rounding up to nearest second
    millisec -=1000;
    tv.tv_sec++;
  }

  tm_info = localtime(&tv.tv_sec);

  strftime(buffer, 26, "%Y:%m:%d %H:%M:%S", tm_info);
  printf("%s.%03d\n", buffer, millisec);

  return 0;
}
Chris
fonte
gettimeofdaynão está disponível em implementações do Windows
Mendes
Adicione as opções '-lm' ao criá-lo.
skysign
3
Acho que o buffer [24] é o suficiente, a razão é como abaixo, AAAA: MM: DD HH: MM: SS.mmm + '\ 0', é 24.
skysign
@Mendes, por que mencionar o Windows? A questão é sobre a linguagem C simples. Esta é uma resposta melhor (embora não seja a certa), apesar de todos os votos positivos errados!
EnzoR
2
user3624334: Não, você não entende o código. Existe apenas um pedido de tempo. Presumo que você se refira à chamada localtime - ela apenas reformata a saída de gettimeofday.
Chris
12

time.hdefine uma strftimefunção que pode fornecer uma representação textual de um time_tusando algo como:

#include <stdio.h>
#include <time.h>
int main (void) {
    char buff[100];
    time_t now = time (0);
    strftime (buff, 100, "%Y-%m-%d %H:%M:%S.000", localtime (&now));
    printf ("%s\n", buff);
    return 0;
}

mas isso não dará a você uma resolução inferior a um segundo, pois não está disponível em a time_t. Ele produz:

2010-09-09 10:08:34.000

Se você estiver realmente limitado pelas especificações e não quiser o espaço entre o dia e a hora, apenas remova-o da string de formato.

paxdiablo
fonte
+1 para o truque de expediente para preencher a tela em milissegundos. Tive um cliente uma vez que queria que eu fizesse isso, mas com dígitos diferentes de zero, então parecia que havia significado nisso. Eu o convenci do contrário, mas concordei em colocar zeros.
RBerteig,
4
Um amigo meu (não eu, claro) certa vez usou um truque semelhante - eles mantinham a estática contendo o último segundo e "milissegundo". Onde o segundo não mudou desde a última vez, eles apenas adicionaram um valor aleatório entre 1 e 200 a milissegundos (certificando-se de que não passou de 999 é claro - o máximo real para o rand () foi sempre o mínimo de 200 e metade da distância para 999). Onde o segundo mudou, eles apenas definiram milissegundos para 0 antes de adicionar. Agradável, aparentemente aleatório, mas corretamente sequenciado em milissegundos, e o cliente nem percebeu :-)
paxdiablo
5

O código a seguir é impresso com precisão de microssegundos. Tudo o que temos a fazer é uso gettimeofdaye strftimesobre tv_sece anexar tv_usecpara a cadeia construída.

#include <stdio.h>
#include <time.h>
#include <sys/time.h>
int main(void) {
    struct timeval tmnow;
    struct tm *tm;
    char buf[30], usec_buf[6];
    gettimeofday(&tmnow, NULL);
    tm = localtime(&tmnow.tv_sec);
    strftime(buf,30,"%Y:%m:%dT%H:%M:%S", tm);
    strcat(buf,".");
    sprintf(usec_buf,"%dZ",(int)tmnow.tv_usec);
    strcat(buf,usec_buf);
    printf("%s",buf);
    return 0;
}
Nataraj
fonte
2

Você poderia usar strftime, mas struct tmnão tem resolução por alguns segundos. Não tenho certeza se isso é absolutamente necessário para seus propósitos.

struct tm tm;
/* Set tm to the correct time */
char s[20]; /* strlen("2009-08-10 18:17:54") + 1 */
strftime(s, 20, "%F %H:%M:%S", &tm);
Jack Kelly
fonte
2

truque:

    int time_len = 0, n;
    struct tm *tm_info;
    struct timeval tv;

    gettimeofday(&tv, NULL);
    tm_info = localtime(&tv.tv_sec);
    time_len+=strftime(log_buff, sizeof log_buff, "%y%m%d %H:%M:%S", tm_info);
    time_len+=snprintf(log_buff+time_len,sizeof log_buff-time_len,".%03ld ",tv.tv_usec/1000);
Андрей Мельников
fonte
1
Explique por que isso funciona. e o que exatamente está acontecendo.
Raj Kamal
Todos iguais aos exemplos acima, mas apenas de forma mais eficaz. `time_len + = snprintf (log_buff + time_len, sizeof log_buff-time_len," log var é =% s ", logvar); int ret = escrever (log_fd, log_buff, time_len); `
Андрей Мельников
De onde eu importo gettimeofday?
AndreyP
1

Nenhuma das soluções nesta página funcionou para mim, eu as misturei e as fiz funcionar com Windows e Visual Studio 2019, Veja como:

#include <Windows.h>
#include <time.h> 
#include <chrono>

static int gettimeofday(struct timeval* tp, struct timezone* tzp) {
    namespace sc = std::chrono;
    sc::system_clock::duration d = sc::system_clock::now().time_since_epoch();
    sc::seconds s = sc::duration_cast<sc::seconds>(d);
    tp->tv_sec = s.count();
    tp->tv_usec = sc::duration_cast<sc::microseconds>(d - s).count();
    return 0;
}

static char* getFormattedTime() {
    static char buffer[26];

    // For Miliseconds
    int millisec;
    struct tm* tm_info;
    struct timeval tv;

    // For Time
    time_t rawtime;
    struct tm* timeinfo;

    gettimeofday(&tv, NULL);

    millisec = lrint(tv.tv_usec / 1000.0);
    if (millisec >= 1000) 
    {
        millisec -= 1000;
        tv.tv_sec++;
    }

    time(&rawtime);
    timeinfo = localtime(&rawtime);

    strftime(buffer, 26, "%Y:%m:%d %H:%M:%S", timeinfo);
    sprintf_s(buffer, 26, "%s.%03d", buffer, millisec);

    return buffer;
}

Resultado:

2020: 08: 02 06: 41: 59.107

2020: 08: 02 06: 41: 59,196

PinnedObject
fonte