Perbedaan antara System.DateTime.Now dan System.DateTime.Today

127

Adakah yang bisa menjelaskan perbedaan antara System.DateTime.Nowdan System.DateTime.Todaydi C # .NET? Pro dan kontra dari masing-masing jika memungkinkan.

Samuel Liew
sumber

Jawaban:

179

DateTime.Nowmengembalikan DateTimenilai yang terdiri dari tanggal dan waktu lokal komputer tempat kode dijalankan. Itu telah DateTimeKind.Localditugaskan ke Kindpropertinya. 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.Todaymengembalikan DateTimenilai 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.Localdi Kindproperti. 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.Nowpertama mendapatkan waktu UTC (melalui GetSystemTimeAsFileTimefungsi 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.DateTimeakan memiliki nilai yang mirip dengan DateTime.Now, tetapi akan memiliki DateTimeKind.Unspecifieddaripada DateTimeKind.Local- yang dapat menyebabkan kesalahan lain tergantung pada apa yang Anda lakukan dengannya.

Jadi, jawaban sederhana adalah yang DateTime.Todaysetara 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.Nowpada 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 -0600sebelum transisi, atau 2013-11-03 01:00:00 -0700setelah 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.Todaypada 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 Dateobjek 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 LocalDatekelas 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.Timeobjek 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);
Matt Johnson-Pint
sumber
9
Bagaimana dengan penggunaan DateTime.UtcNowbukan DateTimeOffset.Now?
Samuel Liew
5
DateTime.UtcNowdapat diterima jika Anda dapat menyampaikan dalam aplikasi Anda atau spec bahwa nilainya dalam UTC. (Saya suka benar-benar memanggil bidang atau properti seperti MyDateUtcbukan hanya MyDate- tetapi itu hanya lapisan gula pada kue.) Jika Anda tidak dapat menyampaikannya dalam spesifikasi atau nama bidang, maka DateTimeOffset.UtcNowdapat digunakan untuk memastikan nol offset akan disampaikan dengan nilai tanggal dan waktu.
Matt Johnson-Pint
Mereka tidak setara. Hari ini memiliki waktu seperti 00:00:00.
James Wilkins
@ JamesWilkins - Tidak yakin apa yang Anda maksud. Begitu juga DateTime.Now.Date.
Matt Johnson-Pint
@MattJohnson Pertanyaannya adalah menanyakan perbedaan antara DateTime.Today dan DateTime.Sekarang, bukan DateTime.Today dan DateTime.Now.Date.
David Anderson
85

Waktu. .Nowtermasuk 09:23:12 atau apa pun; .Todayadalah bagian tanggal saja (pukul 00:00:00 pada hari itu).

Jadi gunakan .Nowjika Anda ingin memasukkan waktu, dan .Todayjika Anda hanya ingin kencan!

.Today pada dasarnya sama dengan .Now.Date

Marc Gravell
sumber
27
... dan gunakan UtcNowkecuali Anda benar - benar menginginkan sistem zona waktu lokal. (Khususnya, pada aplikasi web yang hampir selalu merupakan pilihan yang salah.)
Jon Skeet
22

The DateTime.Nowproperti mengembalikan tanggal dan waktu, misalnya 2011-07-01 10:09.45310.

The DateTime.Todayproperti mengembalikan tanggal dengan compnents waktu diatur ke nol, misalnya 2011-07-01 00:00.00000.

The DateTime.Todayproperti sebenarnya diimplementasikan terhadap return DateTime.Now.Date:

public static DateTime Today {
  get {
    DateTime now = DateTime.Now;
    return now.Date;
  }
}
Guffa
sumber
9

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

daniel.herken
sumber
2
hanya sebuah pengamatan ... dokumentasi 1.1 jauh lebih tidak terperinci daripada dokumentasi 4.0; mungkin lebih baik menautkan ke vLatest?
Marc Gravell
3
@megaperlz: Anda sekarang terhubung ke 4.0 daripada vLatest. Tautan VLatest dapat dibuat dengan menghapus tautan (v=VS.100).
Brian
6

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);
          }
        }
dekdev
sumber
5
DateTime dt = new DateTime();// gives 01/01/0001 12:00:00 AM
DateTime dt = DateTime.Now;// gives today date with current time
DateTime dt = DateTime.Today;// gives today date and 12:00:00 AM time
deepi
sumber
1

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.Ticksadalah waktu aktual yang disimpan oleh .net (pada dasarnya waktu UTC), sisanya hanya merupakan representasi (yang penting untuk tujuan tampilan).

Jika Kindproperti DateTimeKind.Localitu 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.

Kobus
sumber
-1

DateTime.Now.ToShortDateString() hanya akan menampilkan bagian tanggal

sunnyca99
sumber