Adakah yang bisa menjelaskan perbedaan antara System.DateTime.Now
dan System.DateTime.Today
di C # .NET? Pro dan kontra dari masing-masing jika memungkinkan.
Adakah yang bisa menjelaskan perbedaan antara System.DateTime.Now
dan System.DateTime.Today
di C # .NET? Pro dan kontra dari masing-masing jika memungkinkan.
Jawaban:
DateTime.Now
mengembalikan DateTime
nilai yang terdiri dari tanggal dan waktu lokal komputer tempat kode dijalankan. Itu telah DateTimeKind.Local
ditugaskan ke Kind
propertinya. Ini sama dengan memanggil salah satu dari yang berikut:
DateTime.UtcNow.ToLocalTime()
DateTimeOffset.UtcNow.LocalDateTime
DateTimeOffset.Now.LocalDateTime
TimeZoneInfo.ConvertTime(DateTime.UtcNow, TimeZoneInfo.Local)
TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow, TimeZoneInfo.Local)
DateTime.Today
mengembalikan DateTime
nilai yang memiliki komponen tahun, bulan, dan hari yang sama dengan ekspresi di atas, tetapi dengan komponen waktu yang disetel ke nol. Itu juga ada DateTimeKind.Local
di Kind
properti. Ini setara dengan salah satu dari yang berikut:
DateTime.Now.Date
DateTime.UtcNow.ToLocalTime().Date
DateTimeOffset.UtcNow.LocalDateTime.Date
DateTimeOffset.Now.LocalDateTime.Date
TimeZoneInfo.ConvertTime(DateTime.UtcNow, TimeZoneInfo.Local).Date
TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow, TimeZoneInfo.Local).Date
Perhatikan bahwa secara internal, sistem jam dalam hal UTC, jadi ketika Anda menyebutnya DateTime.Now
pertama mendapatkan waktu UTC (melalui GetSystemTimeAsFileTime
fungsi di Win32 API) dan kemudian mengonversi nilai ke zona waktu lokal. (Karena DateTime.Now.ToUniversalTime()
itu lebih mahal daripada DateTime.UtcNow
.)
Perhatikan juga bahwa DateTimeOffset.Now.DateTime
akan memiliki nilai yang mirip dengan DateTime.Now
, tetapi akan memiliki DateTimeKind.Unspecified
daripada DateTimeKind.Local
- yang dapat menyebabkan kesalahan lain tergantung pada apa yang Anda lakukan dengannya.
Jadi, jawaban sederhana adalah yang DateTime.Today
setara dengan DateTime.Now.Date
.
Tapi IMHO - Anda tidak boleh menggunakan salah satu dari ini, atau yang setara di atas.
Ketika Anda meminta DateTime.Now
, Anda meminta nilai jam kalender lokal dari komputer tempat kode berjalan. Tetapi apa yang Anda dapatkan tidak memiliki informasi tentang jam itu! Yang terbaik yang Anda dapatkan adalah itu DateTime.Now.Kind == DateTimeKind.Local
. Tapi milik siapa itu? Informasi itu hilang begitu Anda melakukan sesuatu dengan nilainya, seperti menyimpannya dalam database, menampilkannya di layar, atau mengirimkannya menggunakan layanan web.
Jika zona waktu lokal Anda mengikuti aturan penghematan siang hari, Anda tidak mendapatkan informasi itu kembali DateTime.Now
. Dalam waktu yang ambigu, seperti selama transisi "mundur", Anda tidak akan tahu yang mana dari dua momen yang sesuai dengan nilai yang Anda ambil DateTime.Now
. Misalnya, katakan zona waktu sistem Anda diatur ke Mountain Time (US & Canada)
dan Anda meminta DateTime.Now
pada jam-jam awal 3 November 2013. Apa artinya hasilnya 2013-11-03 01:00:00
? Ada dua momen waktu instan yang diwakili oleh kalender yang sama ini. Jika saya mengirim nilai ini kepada orang lain, mereka tidak akan tahu yang mana yang saya maksud. Terutama jika mereka berada di zona waktu di mana aturannya berbeda.
Hal terbaik yang dapat Anda lakukan adalah menggunakan DateTimeOffset
:
// This will always be unambiguous.
DateTimeOffset now = DateTimeOffset.Now;
Sekarang untuk skenario yang sama yang saya jelaskan di atas, saya mendapatkan nilai 2013-11-03 01:00:00 -0600
sebelum transisi, atau 2013-11-03 01:00:00 -0700
setelah transisi. Siapa pun yang melihat nilai-nilai ini dapat mengatakan apa yang saya maksud.
Saya menulis posting blog tentang hal ini. Silakan baca - Kasus Terhadap DateTime . Sekarang.
Juga, ada beberapa tempat di dunia ini (seperti Brasil) di mana transisi "semi-maju" terjadi tepat di Midnight. Jam mulai dari 23:59 hingga 01:00. Ini berarti bahwa nilai yang Anda dapatkan DateTime.Today
pada tanggal itu, tidak ada! Bahkan jika Anda menggunakan DateTimeOffset.Now.Date
, Anda mendapatkan hasil yang sama, dan Anda masih memiliki masalah ini. Itu karena secara tradisional, tidak ada yang namanya Date
objek di .Net. Jadi, terlepas dari bagaimana Anda mendapatkan nilai, setelah Anda menanggalkan waktu - Anda harus ingat bahwa itu tidak benar-benar mewakili "tengah malam", meskipun itulah nilai yang Anda kerjakan.
Jika Anda benar-benar menginginkan solusi yang sepenuhnya benar untuk masalah ini, pendekatan terbaik adalah menggunakan NodaTime . The LocalDate
kelas benar merupakan tanggal tanpa waktu. Anda bisa mendapatkan tanggal saat ini untuk zona waktu apa pun, termasuk zona waktu sistem lokal:
using NodaTime;
...
Instant now = SystemClock.Instance.Now;
DateTimeZone zone1 = DateTimeZoneProviders.Tzdb.GetSystemDefault();
LocalDate todayInTheSystemZone = now.InZone(zone1).Date;
DateTimeZone zone2 = DateTimeZoneProviders.Tzdb["America/New_York"];
LocalDate todayInTheOtherZone = now.InZone(zone2).Date;
Jika Anda tidak ingin menggunakan Waktu Noda, sekarang ada opsi lain. Saya telah berkontribusi implementasi objek hanya tanggal untuk proyek .Net CoreFX Lab . Anda dapat menemukan System.Time
objek paket di umpan MyGet mereka. Setelah ditambahkan ke proyek Anda, Anda akan menemukan bahwa Anda dapat melakukan salah satu dari yang berikut:
using System;
...
Date localDate = Date.Today;
Date utcDate = Date.UtcToday;
Date tzSpecificDate = Date.TodayInTimeZone(anyTimeZoneInfoObject);
DateTime.UtcNow
dapat diterima jika Anda dapat menyampaikan dalam aplikasi Anda atau spec bahwa nilainya dalam UTC. (Saya suka benar-benar memanggil bidang atau properti seperti MyDateUtc
bukan hanya MyDate
- tetapi itu hanya lapisan gula pada kue.) Jika Anda tidak dapat menyampaikannya dalam spesifikasi atau nama bidang, maka DateTimeOffset.UtcNow
dapat digunakan untuk memastikan nol offset akan disampaikan dengan nilai tanggal dan waktu.
DateTime.Now.Date
.
Waktu. .Now
termasuk 09:23:12 atau apa pun; .Today
adalah bagian tanggal saja (pukul 00:00:00 pada hari itu).
Jadi gunakan .Now
jika Anda ingin memasukkan waktu, dan .Today
jika Anda hanya ingin kencan!
.Today
pada dasarnya sama dengan .Now.Date
UtcNow
kecuali Anda benar - benar menginginkan sistem zona waktu lokal. (Khususnya, pada aplikasi web yang hampir selalu merupakan pilihan yang salah.)
The DateTime.Now
properti mengembalikan tanggal dan waktu, misalnya 2011-07-01 10:09.45310
.
The DateTime.Today
properti mengembalikan tanggal dengan compnents waktu diatur ke nol, misalnya 2011-07-01 00:00.00000
.
The DateTime.Today
properti sebenarnya diimplementasikan terhadap return DateTime.Now.Date
:
public static DateTime Today {
get {
DateTime now = DateTime.Now;
return now.Date;
}
}
DateTime.Today mewakili tanggal sistem saat ini dengan bagian waktu diatur ke 00:00:00
dan
DateTime. Sekarang mewakili tanggal dan waktu sistem saat ini
(v=VS.100)
.
Saya berpikir untuk Menambahkan tautan ini -
Kembali ke pertanyaan awal, Menggunakan Reflektor saya telah menjelaskan perbedaan dalam kode
public static DateTime Today
{
get
{
return DateTime.Now.Date; // It returns the date part of Now
//Date Property
// returns same date as this instance, and the time value set to 12:00:00 midnight (00:00:00)
}
}
private const long TicksPerMillisecond = 10000L;
private const long TicksPerDay = 864000000000L;
private const int MillisPerDay = 86400000;
public DateTime Date
{
get
{
long internalTicks = this.InternalTicks; // Date this instance is converted to Ticks
return new DateTime((ulong) (internalTicks - internalTicks % 864000000000L) | this.InternalKind);
// Modulo of TicksPerDay is subtracted - which brings the time to Midnight time
}
}
public static DateTime Now
{
get
{
/* this is why I guess Jon Skeet is recommending to use UtcNow as you can see in one of the above comment*/
DateTime utcNow = DateTime.UtcNow;
/* After this i guess it is Timezone conversion */
bool isAmbiguousLocalDst = false;
long ticks1 = TimeZoneInfo.GetDateTimeNowUtcOffsetFromUtc(utcNow, out isAmbiguousLocalDst).Ticks;
long ticks2 = utcNow.Ticks + ticks1;
if (ticks2 > 3155378975999999999L)
return new DateTime(3155378975999999999L, DateTimeKind.Local);
if (ticks2 < 0L)
return new DateTime(0L, DateTimeKind.Local);
else
return new DateTime(ticks2, DateTimeKind.Local, isAmbiguousLocalDst);
}
}
DateTime.Today
adalah DateTime.Now
dengan waktu yang disetel ke nol.
Penting untuk dicatat bahwa ada perbedaan antara nilai DateTime, yang mewakili jumlah kutu yang telah berlalu sejak tengah malam 1 Januari 0000, dan representasi string dari nilai DateTime itu, yang menyatakan nilai tanggal dan waktu dalam suatu format spesifik budaya: https://msdn.microsoft.com/en-us/library/system.datetime.now%28v=vs.110%29.aspx
DateTime.Now.Ticks
adalah waktu aktual yang disimpan oleh .net (pada dasarnya waktu UTC), sisanya hanya merupakan representasi (yang penting untuk tujuan tampilan).
Jika Kind
properti DateTimeKind.Local
itu secara implisit termasuk informasi zona waktu komputer lokal. Saat mengirim melalui layanan web .net, nilai DateTime secara default diserialisasi dengan informasi zona waktu, misalnya 2008-10-31T15: 07: 38.6875000-05: 00, dan komputer di zona waktu lain masih dapat mengetahui persis jam berapa dirujuk.
Jadi, menggunakan DateTime.Now dan DateTime.Today tidak masalah.
Anda biasanya mulai mengalami masalah ketika Anda mulai membingungkan representasi string dengan nilai aktual dan mencoba untuk "memperbaiki" DateTime, ketika tidak rusak.
DateTime.UtcNow
bukanDateTimeOffset.Now
?