Header <time.h> menyediakan fungsi dan tipe untuk mengukur waktu serta memformatnya menjadi string yang dapat dibaca manusia. Tipe utamanya adalah time_t (jumlah detik sejak Unix epoch 1970-01-01) dan struct tm (tanggal kalender terurai menjadi field tahun, bulan, hari, jam, menit, detik). Selain wall-clock time (waktu nyata), header ini juga menyediakan clock() untuk mengukur CPU time yang dipakai program. Pada chapter ini kita akan meninjau cara mengambil waktu saat ini, menguraikannya ke struct tm, memformat dengan strftime, dan mengukur durasi eksekusi.

Mengambil Waktu Saat Ini: time, ctime, localtime, gmtime #

Fungsi time(NULL) mengembalikan time_t berisi jumlah detik sejak Unix epoch. Fungsi ctime mengkonversi time_t langsung ke string pendek. Untuk kontrol penuh, kita konversi time_t ke struct tm lewat localtime (waktu lokal sesuai timezone sistem) atau gmtime (waktu UTC).

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

int main(void) {
    /* Pakai timestamp tetap agar output reproducible: 1 Jan 2024 00:00:00 UTC */
    time_t ts = 1704067200;   /* 2024-01-01 00:00:00 UTC */

    /* ctime: format string pendek dari time_t */
    char *s = ctime(&ts);
    printf("Timestamp        = %lld (detik sejak epoch)\n", (long long)ts);
    printf("ctime(&ts)       = %s", s);   /* sudah ada \n */

    /* localtime: konversi ke struct tm (waktu lokal) */
    struct tm *lokal = localtime(&ts);
    if (lokal == NULL) { perror("localtime"); return 1; }

    /* gmtime: konversi ke UTC */
    struct tm *utc = gmtime(&ts);
    if (utc == NULL) { perror("gmtime"); return 1; }

    printf("Lokal: %04d-%02d-%02d %02d:%02d:%02d\n",
           lokal->tm_year + 1900, lokal->tm_mon + 1, lokal->tm_mday,
           lokal->tm_hour, lokal->tm_min, lokal->tm_sec);
    printf("UTC  : %04d-%02d-%02d %02d:%02d:%02d\n",
           utc->tm_year + 1900, utc->tm_mon + 1, utc->tm_mday,
           utc->tm_hour, utc->tm_min, utc->tm_sec);

    /* Akses field struct tm satu per satu */
    printf("\nField tm_wday = %d (0=Minggu, 1=Senin, ..., 6=Sabtu)\n", utc->tm_wday);
    printf("Field tm_yday = %d (hari ke- dalam tahun, mulai dari 0)\n", utc->tm_yday);
    printf("Field tm_isdst= %d (0=bukan DST, >0=ya, <0=tidak diketahui)\n", utc->tm_isdst);

    return 0;
}

Output yang Dihasilkan:

text
Timestamp        = 1704067200 (detik sejak epoch)
ctime(&ts)       = Mon Jan  1 00:00:00 2024
Lokal: 2024-01-01 00:00:00
UTC  : 2024-01-01 00:00:00

Field tm_wday = 1 (0=Minggu, 1=Senin, ..., 6=Sabtu)
Field tm_yday = 0 (hari ke- dalam tahun, mulai dari 0)
Field tm_isdst= 0 (0=bukan DST, >0=ya, <0=tidak diketahui)

Mari kita telaah baris-baris kode di atas:

  1. Baris 6 (time_t ts = 1704067200;): timestamp tetap 1704067200 merepresentasikan 2024-01-01 00:00:00 UTC. Pada program nyata, ganti dengan time(NULL) yang mengambil waktu saat ini—di sini kita pakai nilai tetap agar output buku ini reproducible.
  2. Baris 9 (char *s = ctime(&ts);): ctime mengembalikan pointer ke string statis berformat "Www Mmm dd HH:MM:SS YYYY\n". String ini tidak aman untuk thread karena memori internalnya ditimpa pada pemanggilan berikutnya—gunakan ctime_r (POSIX) untuk versi reentrant.
  3. Baris 13 (struct tm *lokal = localtime(&ts);): mengembalikan pointer ke struct tm statis internal. Field tm_year diisi tahun sejak 1900 (jadi 2024 ditulis 124), tm_mon dimulai dari 0 (Januari = 0), tm_mday dimulai dari 1. Karena itu kita tambahkan 1900 ke tm_year dan 1 ke tm_mon saat mencetak.
  4. Baris 19 (struct tm *utc = gmtime(&ts);): identik dengan localtime tetapi selalu mengkonversi ke UTC. Bila timezone sistem adalah UTC, kedua fungsi memberi hasil yang sama persis—seperti output di atas.
  5. Baris 28-30 (tm_wday, tm_yday, tm_isdst): tm_wday adalah hari dalam minggu (0=Minggu, 6=Sabtu). tm_yday adalah hari ke- dalam tahun, mulai dari 0. tm_isdst menandakan Daylight Saving Time: positif bila aktif, 0 bila tidak, negatif bila tidak diketahui.

Memformat Tanggal dengan strftime #

Fungsi strftime mengkonversi struct tm ke string dengan format yang dapat kita kustomisasi sepenuhnya. Kode format seperti %Y (tahun 4 digit), %m (bulan 2 digit), %d (hari 2 digit), %H (jam 24-jam), %M (menit), %S (detik) memungkinkan kita menyusun format tanggal untuk berbagai keperluan—dari ISO 8601 hingga format RFC email.

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

int main(void) {
    /* Gunakan timestamp tetap agar output reproducible: 1 Jan 2024 00:00:00 UTC */
    time_t ts = 1704067200;   /* 2024-01-01 00:00:00 UTC */
    struct tm *lokal = localtime(&ts);

    /* strftime: format struct tm ke string dengan format kompleks */
    char buf[128];
    strftime(buf, sizeof(buf), "%A, %d %B %Y %H:%M:%S", lokal);
    printf("Format panjang  : %s\n", buf);

    strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", lokal);
    printf("ISO 8601        : %s\n", buf);

    strftime(buf, sizeof(buf), "%d/%m/%y", lokal);
    printf("Tanggal singkat : %s\n", buf);

    strftime(buf, sizeof(buf), "%a, %d %b %Y %z", lokal);
    printf("Format RFC email: %s\n", buf);

    return 0;
}

Output yang Dihasilkan:

text
Format panjang  : Monday, 01 January 2024 00:00:00
ISO 8601        : 2024-01-01 00:00:00
Tanggal singkat : 01/01/24
Format RFC email: Mon, 01 Jan 2024 +0000

Daftar conversion specifier yang paling sering dipakai: %Y (tahun 4 digit), %y (tahun 2 digit), %m (bulan 01-12), %d (hari 01-31), %H (jam 00-23), %I (jam 01-12), %M (menit), %S (detik), %A (nama hari lengkap), %a (nama hari singkat), %B (nama bulan lengkap), %b (nama bulan singkat), %z (offset timezone dari UTC), %p (AM/PM). Fungsi strftime mengembalikan jumlah byte yang ditulis ke buffer; bila buffer terlalu kecil, return value adalah 0—kita harus memeriksa kondisi ini.

Mengukur Durasi dengan clock dan difftime #

Fungsi clock() mengembalikan CPU time yang dipakai program sejak dimulai—bukan wall-clock time. Untuk mengkonversi clock_t ke detik, bagi dengan CLOCKS_PER_SEC. Fungsi difftime(t2, t1) menghitung selisih t2 - t1 dalam detik sebagai double, bebas dari masalah representasi time_t yang bervariasi antar platform.

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

/* Fungsi sederhana yang memakan waktu CPU */
static void hitung_berat(void) {
    volatile double total = 0.0;
    for (long i = 1; i <= 10000000L; i++) {
        total += sqrt((double)i);
    }
    (void)total;   /* cegah unused warning */
}

int main(void) {
    /* clock(): ukur CPU time (bukan wall-clock time) */
    clock_t awal = clock();
    hitung_berat();
    clock_t akhir = clock();

    /* Konversi clock_t ke detik: bagi dengan CLOCKS_PER_SEC */
    double cpu_detik = (double)(akhir - awal) / CLOCKS_PER_SEC;
    printf("CPU time (clock): %.4f detik\n", cpu_detik);
    printf("CLOCKS_PER_SEC   = %ld\n", (long)CLOCKS_PER_SEC);

    /* difftime: selisih dua time_t dalam detik */
    time_t t1 = time(NULL);
    time_t t2 = t1 + 3600;   /* satu jam kemudian */
    double selisih = difftime(t2, t1);
    printf("difftime         = %.0f detik (= %.0f jam)\n",
           selisih, selisih / 3600);

    return 0;
}

Output yang Dihasilkan:

text
CPU time (clock): 0.0226 detik
CLOCKS_PER_SEC   = 1000000
difftime         = 3600 detik (= 1 jam)

Fungsi clock() mengukur processor time yang dipakai program—waktu CPU yang sebenarnya dihabiskan untuk eksekusi, bukan wall-clock time. Bila program banyak melakukan I/O atau menunggu, CPU time bisa jauh lebih kecil dari wall-clock time. Sebagai alternatif modern, POSIX menyediakan clock_gettime(CLOCK_MONOTONIC, ...) yang memberi resolusi nanodetik dan tidak dipengaruhi perubahan jam sistem. Untuk selisih waktu sederhana, difftime adalah cara portabel karena tidak semua platform menyimpan time_t sebagai integer detik—beberapa sistem legacy memakai representasi lain.