Jak wydrukować godzinę w formacie: 2009-08-10 18:17: 54.811

97

Jaka jest najlepsza metoda drukowania czasu w C w formacie 2009‐08‐10 
18:17:54.811?

Dominic Bou-Samra
źródło

Odpowiedzi:

109

Użyj 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;
}

Przez część milisekund spójrz na to pytanie. Jak mierzyć czas w milisekundach za pomocą ANSI C?

Hamid Nazari
źródło
Teraz jest to jeszcze lepsza odpowiedź i podpowiada, jak poradzić sobie z częścią milisekundową. Myślę, że twój bufor jest teraz trochę dłuższy niż powinien.
Jack Kelly,
16
Lepiej być dłuższym niż niższym :-)
paxdiablo
Doskonała odpowiedź. W PHP mogłem robić różne rzeczy, ale wiedziałem, że to wszystko jest już w C. Dzięki.
Vijay Kumar Kanta
1
Być może linia time(&timer)powinna raczej być timer = time(NULL);, przynajmniej dla Linuksa. The tloc argument is obsolescent and should always be NULL in new code. When tloc is NULL, the call cannot fail.
Antonin Décimo
6
Odpowiedź jest zdecydowanie błędna w co najmniej jednym przypadku (Linux), ponieważ "struct tm" używany przez localtime () nie zawiera żadnych informacji o czasie poniżej sekund. Zamiast "struct timeval" używane przez gettimeofday () ma mikrosekundy, które podzielone przez 1000 da milisekundy. Wszystkie te głosy za są naprawdę błędne i mylące! Chyba że ktoś zgłosi, w której architekturze otrzymujesz szczegóły czasu poniżej sekundy za pomocą "struct tm".
EnzoR
32

Powyższe odpowiedzi nie odpowiadają w pełni na pytanie (konkretnie część milisekowa). Moim rozwiązaniem jest użycie gettimeofday przed strftime. Zwróć uwagę, aby uniknąć zaokrąglania milisek do „1000”. Jest to oparte na odpowiedzi Hamida Nazariego.

#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
źródło
gettimeofdaynie jest dostępne w implementacjach systemu Windows
Mendes
Podczas budowania dodaj opcje „-lm”.
skysign
3
Myślę, że bufor [24] wystarczy, powód jest jak poniżej, RRRR: MM: DD HH: MM: SS.mmm + '\ 0', to 24.
skysign
@Mendes, dlaczego wspominasz o systemie Windows? Pytanie dotyczy prostego języka C. To lepsza odpowiedź (choć nie właściwa), pomimo tych wszystkich złych głosów za!
EnzoR
2
user3624334: Nie, nie rozumiesz kodu. Jest tylko jedna prośba o czas. Zakładam, że masz na myśli wywołanie czasu lokalnego - po prostu ponownie formatuje dane wyjściowe z gettimeofday.
Chris
12

time.hdefiniuje strftimefunkcję, która może dać tekstową reprezentację time_tużycia czegoś takiego jak:

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

ale to nie zapewni rozdzielczości poniżej sekundy, ponieważ nie jest dostępna z pliku time_t. Wyprowadza:

2010-09-09 10:08:34.000

Jeśli naprawdę jesteś ograniczony specyfikacjami i nie chcesz odstępu między dniem a godziną, po prostu usuń go z ciągu formatu.

paxdiablo
źródło
+1 za wygodną sztuczkę polegającą na wypełnieniu wyświetlacza z dokładnością do milisekundy. Miałem kiedyś klienta, który chciał, żebym to zrobił, ale z cyframi niezerowymi, więc wyglądało na to, że ma to znaczenie. Odmówiłem mu tego, ale zgodziłem się wstawić zera.
RBerteig
4
Mój przyjaciel (oczywiście nie ja) użył kiedyś podobnej sztuczki - trzymali statykę zawierającą ostatnią sekundę i „milisekundę”. Tam, gdzie sekunda nie zmieniła się od ostatniego razu, po prostu dodali losową wartość między 1 a 200 do milisek (upewniając się, że nie przekroczyła 999 - rzeczywiste maksimum dla rand () było zawsze min 200 i połowę odległości do 999). Tam, gdzie zmieniła się druga, po prostu ustawili milisek na 0 przed dodaniem. Ładne, pozornie przypadkowe, ale odpowiednio sekwencjonowane milisekundy, a klient nie był mądrzejszy :-)
paxdiablo
5

Poniższy kod jest drukowany z dokładnością do mikrosekund. Wszystko co musimy zrobić, to użyć gettimeofdayi strftimena tv_seci dołączyć tv_usecdo skonstruowanego łańcucha.

#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
źródło
2

Możesz użyć strftime, ale struct tmnie ma rozdzielczości dla części sekund. Nie jestem pewien, czy jest to absolutnie wymagane do twoich celów.

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
źródło
2

sztuczka:

    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);
Андрей Мельников
źródło
1
Opisz, dlaczego to działa. i co dokładnie się dzieje.
Raj Kamal
Wszystko to samo, co w powyższych przykładach, ale tylko skuteczniej. `time_len + = snprintf (log_buff + time_len, sizeof log_buff-time_len," log var is =% s ", logvar); int ret = write (log_fd, log_buff, time_len); `
Андрей Мельников
Skąd mogę zaimportować gettimeofday?
AndreyP
1

Żadne z rozwiązań na tej stronie nie działało dla mnie, pomieszałem je i sprawiłem, że działały z Windows i Visual Studio 2019, oto jak:

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

Wynik:

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

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

PinnedObject
źródło