Cómo imprimir la hora en formato: 2009‐08‐10 18: 17: 54.811

96

¿Cuál es el mejor método para imprimir la hora en C en el formato 2009‐08‐10 
18:17:54.811?

Dominic Bou-Samra
fuente

Respuestas:

108

Utilice 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 milisegundos, eche un vistazo a esta pregunta. ¿Cómo medir el tiempo en milisegundos usando ANSI C?

Hamid Nazari
fuente
Es una respuesta aún mejor ahora, y apoyos para buscar cómo manejar la parte de milisegundos. Sin embargo, creo que su búfer ahora es un poco más largo de lo necesario.
Jack Kelly
14
Mejor ser más largo que más corto :-)
paxdiablo
Excelente respuesta. Podía hacer todo tipo de cosas en PHP, pero sabía que ya estaba todo en C. Gracias.
Vijay Kumar Kanta
1
Quizás la línea time(&timer)debería ser mejor timer = time(NULL);, al 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
La respuesta es definitivamente incorrecta en al menos un caso (Linux) ya que "struct tm" usado por localtime () no contiene ninguna información de tiempo por debajo de los segundos. En cambio, "struct timeval" usado por gettimeofday () tiene microsegundos que, divididos por 1000, producirán los milisegundos. ¡Todos esos votos a favor son realmente incorrectos y engañosos! A menos que alguien informe bajo qué arquitectura obtienes detalles de tiempo debajo del segundo con "struct tm".
EnzoR
30

Las respuestas anteriores no responden completamente a la pregunta (específicamente la parte milisegunda). Mi solución a esto es usar gettimeofday antes de strftime. Tenga cuidado de no redondear milisegundos a "1000". Esto se basa en la respuesta 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
fuente
gettimeofdayno está disponible en implementaciones de Windows
Mendes
Agregue las opciones '-lm' cuando lo compile.
skysign
3
Creo que el búfer [24] es suficiente, la razón es como la siguiente, AAAA: MM: DD HH: MM: SS.mmm + '\ 0', es 24.
skysign
@Mendes, ¿por qué mencionar Windows? La pregunta es sobre el lenguaje C simple. Esta es una mejor respuesta (aunque no la correcta), ¡a pesar de todos esos votos a favor incorrectos!
EnzoR
2
user3624334: No, no entiende el código. Solo hay una solicitud de tiempo. Supongo que te refieres a la llamada localtime, simplemente reformatea la salida de gettimeofday.
Chris
12

time.hdefine una strftimefunción que puede darte una representación textual de un 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;
}

pero eso no le dará una resolución inferior a un segundo, ya que no está disponible en a time_t. Produce:

2010-09-09 10:08:34.000

Si está realmente limitado por las especificaciones y no desea el espacio entre el día y la hora, simplemente elimínelo de la cadena de formato.

paxdiablo
fuente
+1 para el truco conveniente para llenar la pantalla al milisegundo. Una vez tuve un cliente que quería que hiciera eso, pero con dígitos distintos de cero, por lo que parecía que había significado allí. Lo convencí de que no lo hiciera, pero acepté poner ceros.
RBerteig
4
Un amigo mío (no yo, por supuesto) usó una vez un truco similar: mantuvieron estática que contiene el último segundo y el "milisegundo". Donde el segundo no había cambiado desde la última vez, simplemente agregaron un valor aleatorio entre 1 y 200 en milisegundos (asegurándose de que no pasara de 999, por supuesto; el máximo real para el rand () siempre fue el mínimo de 200 y la mitad de la distancia hasta 999). Donde el segundo cambió, simplemente establecieron milisegundos en 0 antes de agregar. Agradable milisegundos aparentemente aleatorios pero secuenciados correctamente y el cliente no se dio cuenta :-)
paxdiablo
5

El siguiente código se imprime con precisión de microsegundos. Todo lo que tenemos que hacer es uso gettimeofdayy strftimeen tv_secy añadir tv_useca la cadena construida.

#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
fuente
2

Podría usar strftime, pero struct tmno tiene resolución por partes de segundos. No estoy seguro de si eso es absolutamente necesario para sus 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
fuente
2

truco:

    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);
Андрей Мельников
fuente
1
Explique por qué funciona esto. y qué está pasando exactamente.
Raj Kamal
Lo mismo que en los ejemplos anteriores, pero solo de manera más efectiva. `time_len + = snprintf (log_buff + time_len, sizeof log_buff-time_len," log var es =% s ", logvar); int ret = escribir (log_fd, log_buff, time_len); `
Андрей Мельников
¿De dónde importo gettimeofday?
AndreyP
1

Ninguna de las soluciones en esta página funcionó para mí, las mezclé y las hice funcionar con Windows y Visual Studio 2019, aquí se explica cómo:

#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

Objeto fijado
fuente