Comment imprimer l'heure au format: 2009‐08‐10 18: 17: 54.811

96

Quelle est la meilleure méthode pour imprimer l'heure en C au format 2009‐08‐10 
18:17:54.811?

Dominique Bou-Samra
la source

Réponses:

107

Utilisez 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;
}

Pour une partie des millisecondes, jetez un œil à cette question. Comment mesurer le temps en millisecondes en utilisant ANSI C?

Hamid Nazari
la source
C'est une réponse encore meilleure maintenant, et des accessoires pour rechercher comment gérer la partie milliseconde. Je pense que votre tampon est maintenant un peu plus long que nécessaire.
Jack Kelly
14
Mieux vaut être plus long que plus court :-)
paxdiablo
Superbe réponse. Je pouvais faire toutes sortes de choses en PHP, mais je savais que tout était déjà là dans C. THanks.
Vijay Kumar Kanta
1
Peut-être que la ligne time(&timer)devrait plutôt être timer = time(NULL);, du moins pour 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 réponse est définitivement fausse dans au moins un cas (Linux) car "struct tm" utilisé par localtime () ne contient aucune information temporelle en dessous des secondes. Au lieu de cela, "struct timeval" utilisé par gettimeofday () a des microsecondes qui, divisées par 1000, donneront les millisecondes. Tous ces votes positifs sont vraiment faux et trompeurs! À moins que quelqu'un ne rapporte sous quelle architecture vous obtenez les détails de l'heure sous la seconde avec "struct tm".
EnzoR
30

Les réponses ci-dessus ne répondent pas entièrement à la question (en particulier la partie millisec). Ma solution consiste à utiliser gettimeofday avant strftime. Faites attention à ne pas arrondir le millisec à "1000". Ceci est basé sur la réponse 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
la source
gettimeofdayn'est pas disponible sur les implémentations Windows
Mendes
Veuillez ajouter les options '-lm' lorsque vous le construisez.
skysign
3
Je pense que le tampon [24] est suffisant, la raison est comme ci-dessous, AAAA: MM: JJ HH: MM: SS.mmm + '\ 0', est 24.
skysign
@Mendes, pourquoi mentionner Windows? La question concerne le langage C clair. C'est une meilleure réponse (mais pas la bonne), malgré tous ces faux votes positifs!
EnzoR
2
user3624334: Non, vous ne comprenez pas le code. Il n'y a qu'une seule demande de temps. Je suppose que vous voulez dire l'appel localtime - il reformate simplement la sortie de gettimeofday.
Chris
12

time.hdéfinit une strftimefonction qui peut vous donner une représentation textuelle d'un en time_tutilisant quelque chose comme:

#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;
}

mais cela ne vous donnera pas une résolution inférieure à la seconde car elle n'est pas disponible à partir d'un fichier time_t. Il sort:

2010-09-09 10:08:34.000

Si vous êtes vraiment contraint par les spécifications et que vous ne voulez pas d'espace entre le jour et l'heure, supprimez-le simplement de la chaîne de format.

paxdiablo
la source
+1 pour l'astuce pratique pour remplir l'affichage à la milliseconde. Une fois, j'ai eu un client qui voulait que je fasse cela, mais avec des chiffres différents de zéro, il semblait donc qu'il y avait là une signification. Je l'ai dissuadé mais j'ai accepté de mettre des zéros.
RBerteig
4
Un de mes amis (pas moi bien sûr) a déjà utilisé une astuce similaire - ils ont gardé des statiques contenant la dernière seconde et la "milliseconde". Là où la seconde n'avait pas changé depuis la dernière fois, ils ont simplement ajouté une valeur aléatoire entre 1 et 200 à millisecondes (en s'assurant que cela ne dépassait pas 999 bien sûr - le maximum réel pour le rand () était toujours le min de 200 et la moitié de la distance à 999). Là où le second a changé, ils ont juste mis millisec à 0 avant l'ajout. Belle millisecondes apparemment aléatoire mais correctement séquencée et le client n'était pas le plus sage :-)
paxdiablo
5

Le code suivant s'imprime avec une précision de l'ordre de la microseconde. Tout ce que nous avons à faire est d'utiliser gettimeofdayand strftimeon tv_secet d'ajouter tv_usecà la chaîne construite.

#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
la source
2

Vous pouvez utiliser strftime, mais struct tmn'a pas de résolution pendant des parties de secondes. Je ne sais pas si c'est absolument nécessaire à vos fins.

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
la source
2

tour:

    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);
Андрей Мельников
la source
1
Veuillez expliquer pourquoi cela fonctionne. et ce qui se passe exactement.
Raj Kamal
Tout de même que les exemples ci-dessus, mais seulement de manière plus efficace. `time_len + = snprintf (log_buff + time_len, sizeof log_buff-time_len," log var is =% s ", logvar); int ret = écriture (log_fd, log_buff, time_len); `
Андрей Мельников
D'où dois-je importer gettimeofday?
AndreyP
1

Aucune des solutions de cette page n'a fonctionné pour moi, je les ai mélangées et les ai faites fonctionner avec Windows et Visual Studio 2019, voici comment:

#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;
}

Résultat :

2020: 08: 02 06: 41: 59.107

2020: 08: 02 06: 41: 59.196

PinnedObject
la source