Cara mencetak waktu dalam format: 2009‐08‐10 18: 17: 54.811

97

Apa metode terbaik untuk mencetak waktu dalam format C 2009‐08‐10 
18:17:54.811?

Dominic Bou-Samra
sumber

Jawaban:

109

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

Untuk bagian milidetik, lihat pertanyaan ini. Bagaimana mengukur waktu dalam milidetik menggunakan ANSI C?

Hamid Nazari
sumber
Ini jawaban yang lebih baik sekarang, dan alat peraga untuk mencari cara menangani bagian milidetik. Saya pikir buffer Anda sekarang sedikit lebih lama dari yang seharusnya.
Jack Kelly
16
Lebih baik lebih panjang daripada lebih pendek :-)
paxdiablo
Jawaban yang luar biasa. Saya bisa melakukan segala macam hal di PHP, tapi tahu itu semua sudah ada di C. Terima kasih.
Vijay Kumar Kanta
1
Mungkin baris tersebut time(&timer)seharusnya timer = time(NULL);, setidaknya untuk 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
6
Jawabannya pasti salah dalam setidaknya satu kasus (Linux) karena "struct tm" yang digunakan oleh localtime () tidak menyimpan informasi waktu di bawah detik. Sebaliknya "struct timeval" yang digunakan oleh gettimeofday () memiliki mikrodetik yang dibagi dengan 1000 akan menghasilkan milidetik. Semua suara positif itu benar-benar salah dan menyesatkan! Kecuali seseorang melaporkan di bawah arsitektur mana Anda mendapatkan detail waktu di bawah detik dengan "struct tm".
EnzoR
32

Jawaban di atas tidak sepenuhnya menjawab pertanyaan (khususnya bagian milidetik). Solusi saya untuk ini adalah menggunakan gettimeofday sebelum strftime. Perhatikan kehati-hatian untuk menghindari pembulatan milidetik ke "1000". Ini berdasarkan jawaban 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
sumber
gettimeofdaytidak tersedia pada implementasi Windows
Mendes
Harap tambahkan opsi '-lm' saat Anda membuatnya.
skysign
3
Saya rasa buffer [24] sudah cukup, alasannya seperti di bawah ini, YYYY: MM: DD HH: MM: SS.mmm + '\ 0', adalah 24.
skysign
@Mendes, mengapa menyebut Windows? Pertanyaannya adalah tentang bahasa C biasa. Ini adalah jawaban yang lebih baik (meskipun bukan yang benar), terlepas dari semua suara positif yang salah!
EnzoR
2
user3624334: Tidak, Anda tidak memahami kodenya. Hanya ada satu permintaan waktu. Saya berasumsi yang Anda maksud adalah panggilan localtime - itu hanya memformat ulang output dari gettimeofday.
Chris
12

time.hmendefinisikan sebuah strftimefungsi yang dapat memberi Anda representasi tekstual dari sebuah time_tpenggunaan seperti:

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

tapi itu tidak akan memberi Anda resolusi sub-detik karena itu tidak tersedia dari time_t. Ini menghasilkan:

2010-09-09 10:08:34.000

Jika Anda benar-benar dibatasi oleh spesifikasi dan tidak menginginkan spasi antara hari dan jam, hapus saja dari format string.

paxdiablo
sumber
1 untuk trik bijak untuk mengisi tampilan ke milidetik. Saya pernah memiliki pelanggan yang menginginkan saya melakukan itu, tetapi dengan angka bukan nol jadi sepertinya ada signifikansi di sana. Saya membujuknya untuk tidak melakukannya, tetapi setuju untuk memasukkan nol.
RBerteig
4
Seorang teman saya (bukan saya tentu saja) pernah menggunakan trik serupa - mereka menyimpan statika yang berisi detik terakhir dan "milidetik". Di mana yang kedua tidak berubah dari terakhir kali, mereka hanya menambahkan nilai acak antara 1 dan 200 hingga milidetik (pastikan itu tidak melewati 999 tentu saja - maks sebenarnya untuk rand () selalu min dari 200 setengah jarak menjadi 999). Jika yang kedua berubah, mereka hanya menyetel milidetik ke 0 sebelum penambahan. Bagus yang tampaknya acak tetapi milidetik yang diurutkan dengan benar dan pelanggan tidak lebih bijaksana :-)
paxdiablo
5

Kode berikut dicetak dengan presisi mikrodetik. Yang harus kita lakukan adalah penggunaan gettimeofdaydan strftimepada tv_secdan append tv_usecke string dibangun.

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

Anda dapat menggunakan strftime, tetapi struct tmtidak memiliki resolusi untuk beberapa detik. Saya tidak yakin apakah itu benar-benar diperlukan untuk tujuan Anda.

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
sumber
2

menipu:

    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);
Андрей Мельников
sumber
1
Harap jelaskan mengapa ini berhasil. dan apa yang sebenarnya sedang terjadi.
Raj Kamal
Semua sama seperti contoh di atas, tetapi hanya lebih efektif. `time_len + = snprintf (log_buff + time_len, sizeof log_buff-time_len," log var adalah =% s ", logvar); int ret = tulis (log_fd, log_buff, time_len); `
Андрей Мельников
Dari mana saya mengimpor gettimeofday?
AndreyP
1

Tidak ada solusi di halaman ini yang berfungsi untuk saya, saya mencampurnya dan membuatnya berfungsi dengan Windows dan Visual Studio 2019, Begini Caranya:

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

Hasil:

2020: 08: 02 06: 41: 59.107

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

PinnedObject
sumber