System.DateTime mewakili sebuah tanggal dan waktu dalam sehari, dari tahun 1 sampai tahun 9999, dengan presisi 100 nanodetik (satu "tick"). System.TimeSpan mewakili sebuah durasi: selisih antara dua nilai DateTime. Keduanya adalah tipe value yang immutable (struct), jadi setiap operasi mengembalikan nilai baru.
Output:
2026-09-24 00:00:00
2026-09-24 14:30:00
14:30:05.250
2026 9 24
14:30
Thursday
267
2026-09-24 00:00
14:30:00
Setiap contoh di halaman ini mencetak tanggal dengan format string yang eksplisit. ToString() default mengikuti culture saat ini (9/24/2026 2:30:00 PM di AS, 24.09.2026 14:30:00 di Jerman), jadi output-nya bergantung pada mesin. Kode format-nya ada di format DateTime.
Tanggal yang tidak valid melempar exception: new DateTime(2026, 2, 30) memunculkan ArgumentOutOfRangeException, begitu juga bulan 13 atau jam 24.
Now, UtcNow, dan Today
Tiga property static membaca jam:
Contoh output:
Now: 2026-09-24 18:20:41 (Local)
UtcNow: 2026-09-24 16:20:41 (Utc)
Today: 2026-09-24 00:00:00
Di contoh ini, zona waktu lokalnya dua jam lebih cepat dari UTC, jadi dua baris pertama berselisih dua jam; di mesin yang diatur ke UTC, keduanya sama. Property Kind mencatat apakah sebuah nilai Local, Utc, atau Unspecified (default untuk tanggal yang kamu buat sendiri). Pakai DateTime.UtcNow untuk apa pun yang kamu simpan, catat di log, bandingkan, atau kirim ke sistem lain: nilainya tidak melompat saat daylight saving time dimulai atau berakhir, dan artinya sama, momen yang sama, di setiap server. Konversi ke waktu lokal hanya saat menampilkan nilai ke manusia.
Untuk mengukur berapa lama kode berjalan, pakai System.Diagnostics.Stopwatch alih-alih mengurangkan dua nilai DateTime.Now; resolusinya jauh lebih halus dan tidak terpengaruh penyesuaian jam.
Menambah dan mengurangi waktu
AddDays, AddHours, AddMinutes, AddSeconds, AddMonths, dan AddYears mengembalikan DateTime baru. Berikan angka negatif untuk mundur. Karena DateTime immutable, hasilnya harus di-assign:
Output:
2026-01-31
2026-02-03 09:00
2026-01-30 21:00
2026-02-28
2027-01-31
10:30
29
True
AddMonths menyesuaikan ke hari terakhir bulan itu saat tanggalnya tidak ada: 31 Januari ditambah satu bulan adalah 28 Februari (atau 29 di tahun kabisat), bukan 3 Maret. Karena itu, menambah satu bulan dua kali dan menambah dua bulan sekaligus bisa menghasilkan tanggal yang berbeda.
Mengurangkan tanggal: TimeSpan
Mengurangkan satu DateTime dari yang lain menghasilkan TimeSpan:
Output:
3.20:30:00
Days: 3, Hours: 20, Minutes: 30
TotalDays: 3.85
TotalHours: 92.5
TotalMinutes: 5550
Nights: 4
Inilah bagian API yang paling sering salah dipahami. Days, Hours, Minutes, dan Seconds adalah komponen dari rentangnya (3 hari, 20 jam, 30 menit). TotalDays, TotalHours, dan TotalMinutes adalah seluruh durasi dalam satu satuan, sebagai double. "Berapa jam tamu itu menginap?" dijawab dengan TotalHours (92,5), bukan Hours (20).
Baris terakhir menunjukkan hal yang berkaitan: 3,85 hari telah berlalu, tetapi tamu itu menginap 4 malam. Membandingkan bagian .Date menghitung hari kalender, dan biasanya itulah yang dibutuhkan untuk penagihan dan tampilan "berapa hari lagi".
Membuat dan memformat nilai TimeSpan
Output:
02:15:00
01:30:00
1.12:00:00
True
03:45:00
True
02:15
36h 0m
00:00:00
TimeSpan mendukung +, -, perbandingan, Duration() (nilai mutlak), dan Negate(). Format custom seperti @"hh\:mm" butuh backslash sebelum karakter literal, dan hh di sana hanya menampilkan komponen jam (0 sampai 23), jadi untuk durasi lebih dari sehari, susun teksnya dari TotalHours seperti di baris kedua dari terakhir.
Membandingkan tanggal
DateTime mendukung ==, !=, <, >, <=, dan >=, ditambah CompareTo dan DateTime.Compare. Untuk membandingkan tanggalnya saja dan mengabaikan waktunya, bandingkan property .Date:
Output:
True
True
1
True
2026-09-01
Untuk "apakah timestamp ini masih di tanggal 30 September?", bandingkan dengan awal hari berikutnya memakai <, seperti di atas. Menulis check <= end akan mengecualikan semua yang lewat dari tengah malam di hari terakhir, karena end adalah 2026-09-30 00:00:00.
Perbandingan hanya melihat tick-nya, bukan Kind: nilai Local dan nilai Utc yang tercetak sama dianggap sama, meskipun keduanya momen yang berbeda. Satu alasan lagi untuk menyimpan waktu dalam UTC.
Hari dalam seminggu dan awal minggu
DayOfWeek adalah enum dari Sunday (0) sampai Saturday (6). Aritmetika padanya bisa dipakai untuk mencari hari kerja dan batas minggu:
Output:
Thursday
4
Weekend: False
Week starts 2026-09-21 (Monday)
Next Friday: 2026-09-25
2026-09-01 to 2026-09-30
Nama hari yang dicetak oleh DayOfWeek.ToString() selalu dalam bahasa Inggris. Untuk nama yang dilokalkan, format tanggalnya dengan "dddd" dan sebuah culture.
Parsing tanggal dari string
Kalau kamu tahu format input-nya, pakai ParseExact atau TryParseExact dengan CultureInfo.InvariantCulture. Format string-nya memakai kode yang sama dengan saat memformat:
Output:
2026-09-24 00:00
2026-09-24 18:05
'2026-02-28' -> Saturday, February 28
'2026-02-30' -> invalid
'28.02.2026' -> invalid
'' -> invalid
2026-02-28
2026-09-24 10:00 Utc
DateTime.Parse(text) tanpa format mencoba menebak dengan culture saat ini. "03/04/2026" adalah 4 Maret di mesin AS dan 3 April di mesin Inggris, dan tanggal yang berhasil di-parse di laptopmu bisa melempar FormatException di server. Simpan Parse untuk input yang diketik pengguna lokal; pakai ParseExact dengan invariant culture untuk file, API, dan database. ParseExact melempar FormatException saat teksnya tidak cocok; TryParseExact mengembalikan false sebagai gantinya.
Menghitung umur
Mengurangkan tanggal lahir lalu membaginya dengan 365 itu salah di sekitar hari ulang tahun dan tahun kabisat. Bandingkan tahunnya, lalu koreksi kalau ulang tahun tahun ini belum terjadi:
Output:
36
35
18
70 days to go
DateTimeOffset
DateTime tidak mencatat zona waktunya selain lewat flag Kind yang samar. DateTimeOffset menyimpan nilainya bersama offset dari UTC, jadi selalu menunjukkan satu momen yang tepat:
Output:
2026-09-24 14:00 +02:00
2026-09-24 12:00
2026-09-24 12:30
00:30:00
21:00 +09:00
Pakai DateTimeOffset (atau nilai DateTime dalam UTC) untuk timestamp: kapan sebuah pesanan dibuat, kapan sebuah pesan dikirim. Database dan serializer JSON menanganinya dengan baik. Untuk mengonversi antarzona waktu bernama dengan aturan daylight saving, pakai TimeZoneInfo.ConvertTime; ID zonanya berbeda per sistem operasi di versi .NET yang lebih lama ("Europe/Paris" di Linux, "Romance Standard Time" di Windows), dan .NET 6 ke atas menerima keduanya.
DateOnly dan TimeOnly (.NET 6 ke atas)
Banyak nilai berupa tanggal tanpa waktu (ulang tahun, tanggal jatuh tempo) atau waktu tanpa tanggal (jam buka). .NET 6 menambahkan dua tipe untuk itu:
// .NET 6 and later
DateOnly birthday = new DateOnly(1990, 9, 24);
DateOnly due = DateOnly.FromDateTime(DateTime.Today).AddDays(14);
int daysLeft = due.DayNumber - DateOnly.FromDateTime(DateTime.Today).DayNumber;
TimeOnly opens = new TimeOnly(9, 0);
TimeOnly closes = new TimeOnly(17, 30);
bool isOpen = TimeOnly.FromDateTime(DateTime.Now).IsBetween(opens, closes);
Kedua tipe ini menghilangkan sekelompok bug, saat waktu atau zona waktu yang nyasar menggeser tanggal sebanyak satu hari. Kode lama, dan kode yang menargetkan .NET Framework atau Unity, memakai DateTime dengan waktu yang dibiarkan di tengah malam.
Kesalahan umum
- Membuang hasil dari
AddDays.DateTimeimmutable; assign nilai yang dikembalikan. - Memakai
Hoursalih-alihTotalHours. Komponen versus seluruh durasi. - Menyimpan
DateTime.Now. Simpan UTC dan konversi untuk ditampilkan. - Memanggil
ToString()tanpa format di log, file, atau test, saat output-nya bergantung pada culture mesin. - Mem-parse data mesin dengan
DateTime.Parse. PakaiParseExactdan invariant culture. - Tertukar antara
mmdanMMdi format string (menit dan bulan). Lihat format DateTime.
Pertanyaan yang sering diajukan
Apa bedanya DateTime.Now dan DateTime.UtcNow?
DateTime.Now adalah waktu saat ini di zona waktu lokal komputer, dengan Kind bernilai Local. DateTime.UtcNow adalah waktu saat ini dalam UTC, dengan Kind bernilai Utc, dan juga lebih cepat karena melewati konversi zona waktu. Simpan dan bandingkan timestamp dalam UTC, dan konversi ke waktu lokal hanya untuk ditampilkan.
Bagaimana cara mendapatkan selisih dua tanggal di C#?
Kurangkan keduanya: TimeSpan gap = end - start;. Lalu baca gap.TotalDays, gap.TotalHours, atau gap.TotalMinutes untuk seluruh durasinya sebagai double, atau gap.Days untuk bagian hari penuhnya. Untuk bulan atau tahun kalender, tidak ada property bawaan, karena panjang setiap bulan berbeda; bandingkan sendiri field tahun dan bulannya.
Apa bedanya TimeSpan.Hours dan TotalHours?
Hours hanyalah komponen jamnya, dari 0 sampai 23, setelah hari penuh dikeluarkan. TotalHours adalah seluruh durasi yang dinyatakan dalam jam, sebagai double. Untuk rentang 1 hari 3 jam, Hours bernilai 3 dan TotalHours bernilai 27. Memakai Hours padahal yang dimaksud TotalHours adalah bug yang sangat umum.
Bagaimana cara mem-parse string tanggal di C#?
Kalau kamu tahu format-nya, pakai DateTime.ParseExact(text, "yyyy-MM-dd", CultureInfo.InvariantCulture), atau DateTime.TryParseExact supaya mendapat false, bukan FormatException, saat input-nya salah. DateTime.Parse menebak format-nya dari culture saat ini, jadi 03/04/2026 berarti 4 Maret di AS dan 3 April di Inggris.
Kenapa AddDays tidak mengubah DateTime saya?
DateTime adalah tipe value yang immutable. AddDays, AddHours, dan method lainnya mengembalikan DateTime baru dan membiarkan yang asli tidak berubah, jadi kamu harus meng-assign hasilnya: due = due.AddDays(7);.
Kapan sebaiknya pakai DateTimeOffset alih-alih DateTime?
Pakai DateTimeOffset untuk timestamp yang harus menunjukkan satu momen yang tepat, seperti kapan sebuah pesanan dibuat atau kapan sebuah entri log ditulis, terutama kalau datanya berpindah antarserver dan antarzona waktu. Tipe ini menyimpan offset dari UTC bersama nilainya. DateTime sudah cukup untuk timestamp yang hanya UTC dan untuk tanggal yang zona waktunya tidak penting.