Sự khác biệt giữa System.DateTime.Now và System.DateTime.Today


127

Bất cứ ai có thể giải thích sự khác biệt giữa System.DateTime.NowSystem.DateTime.Todaytrong C # .NET? Ưu và nhược điểm của mỗi nếu có thể.

Câu trả lời:


179

DateTime.Nowtrả về một DateTimegiá trị bao gồm ngày và giờ cục bộ của máy tính nơi mã đang chạy. Nó đã DateTimeKind.Localđược gán cho Kindtài sản của nó . Nó tương đương với việc gọi bất kỳ thứ nào sau đây:

  • DateTime.UtcNow.ToLocalTime()
  • DateTimeOffset.UtcNow.LocalDateTime
  • DateTimeOffset.Now.LocalDateTime
  • TimeZoneInfo.ConvertTime(DateTime.UtcNow, TimeZoneInfo.Local)
  • TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow, TimeZoneInfo.Local)

DateTime.Todaytrả về một DateTimegiá trị có cùng các thành phần năm, tháng và ngày như bất kỳ biểu thức nào ở trên, nhưng với các thành phần thời gian được đặt thành không. Nó cũng có DateTimeKind.Localtrong Kindtài sản của nó . Nó tương đương với bất kỳ điều nào sau đây:

  • 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

Lưu ý rằng bên trong, đồng hồ hệ thống là về UTC, vì vậy khi bạn gọi DateTime.Nownó trước tiên sẽ có thời gian UTC (thông qua GetSystemTimeAsFileTimechức năng trong API Win32) và sau đó nó chuyển đổi giá trị thành múi giờ địa phương. (Do đó DateTime.Now.ToUniversalTime()đắt hơn DateTime.UtcNow.)

Cũng lưu ý rằng DateTimeOffset.Now.DateTimesẽ có các giá trị tương tự DateTime.Now, nhưng nó sẽ có DateTimeKind.Unspecifiedhơn là DateTimeKind.Local- điều này có thể dẫn đến các lỗi khác tùy thuộc vào những gì bạn làm với nó.

Vì vậy, câu trả lời đơn giản DateTime.Todaylà tương đương với DateTime.Now.Date.
Nhưng IMHO - Bạn không nên sử dụng một trong những thứ này hoặc bất kỳ thứ nào tương đương ở trên.

Khi bạn yêu cầu DateTime.Now, bạn đang yêu cầu giá trị của đồng hồ lịch địa phương của máy tính mà mã đang chạy. Nhưng những gì bạn nhận lại không có bất kỳ thông tin nào về đồng hồ đó! Điều tốt nhất mà bạn nhận được là điều đó DateTime.Now.Kind == DateTimeKind.Local. Nhưng đó là địa phương của ai? Thông tin đó sẽ bị mất ngay khi bạn làm bất cứ điều gì với giá trị, chẳng hạn như lưu trữ nó trong cơ sở dữ liệu, hiển thị trên màn hình hoặc truyền nó bằng dịch vụ web.

Nếu múi giờ địa phương của bạn tuân theo bất kỳ quy tắc tiết kiệm ánh sáng ban ngày nào, bạn sẽ không lấy lại thông tin đó DateTime.Now. Trong những thời điểm mơ hồ, chẳng hạn như trong quá trình chuyển đổi "dự phòng", bạn sẽ không biết thời điểm nào trong hai thời điểm có thể tương ứng với giá trị bạn đã truy xuất DateTime.Now. Ví dụ: giả sử múi giờ hệ thống của bạn được đặt thành Mountain Time (US & Canada)và bạn yêu cầu DateTime.Nowvào đầu giờ ngày 3 tháng 11 năm 2013. Kết quả 2013-11-03 01:00:00có ý nghĩa gì? Có hai khoảnh khắc của thời gian tức thời được biểu thị bằng cùng thời gian lịch này. Nếu tôi gửi giá trị này cho người khác, họ sẽ không biết tôi muốn nói gì. Đặc biệt nếu họ ở trong một múi giờ nơi các quy tắc khác nhau.

Điều tốt nhất bạn có thể làm là sử dụng DateTimeOffsetthay thế:

// This will always be unambiguous.
DateTimeOffset now = DateTimeOffset.Now;

Bây giờ với cùng một kịch bản tôi đã mô tả ở trên, tôi nhận được giá trị 2013-11-03 01:00:00 -0600trước khi chuyển đổi hoặc 2013-11-03 01:00:00 -0700sau khi chuyển đổi. Bất cứ ai nhìn vào những giá trị này đều có thể nói tôi muốn nói gì.

Tôi đã viết một bài blog về chủ đề này. Vui lòng đọc - Trường hợp chống lại DateTime . Bây giờ .

Ngoài ra, có một số nơi trên thế giới này (chẳng hạn như Brazil), nơi quá trình "chuyển tiếp mùa xuân" diễn ra chính xác vào lúc nửa đêm. Đồng hồ đi từ 23:59 đến 01:00. Điều này có nghĩa là giá trị bạn nhận được DateTime.Todayvào ngày đó, không tồn tại! Ngay cả khi bạn sử dụng DateTimeOffset.Now.Date, bạn cũng nhận được kết quả tương tự, và bạn vẫn gặp vấn đề này. Đó là bởi vì theo truyền thống, không có thứ gọi là Dateđối tượng trong .Net. Vì vậy, bất kể bạn có được giá trị như thế nào, một khi bạn bỏ thời gian - bạn phải nhớ rằng nó không thực sự đại diện cho "nửa đêm", mặc dù đó là giá trị bạn đang làm việc.

Nếu bạn thực sự muốn một giải pháp hoàn toàn chính xác cho vấn đề này, cách tiếp cận tốt nhất là sử dụng NodaTime . Các LocalDatelớp đại diện đúng một ngày mà không có thời gian. Bạn có thể nhận được ngày hiện tại cho bất kỳ múi giờ nào, bao gồm múi giờ của hệ thống địa phương:

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;

Nếu bạn không muốn sử dụng Noda Time, giờ đây có một tùy chọn khác. Tôi đã đóng góp việc triển khai một đối tượng chỉ có ngày cho dự án .Net CoreFX Lab . Bạn có thể tìm thấy System.Timeđối tượng gói trong nguồn cấp MyGet của họ. Sau khi thêm vào dự án của bạn, bạn sẽ thấy bạn có thể thực hiện bất kỳ thao tác nào sau đây:

using System;
...

Date localDate = Date.Today;

Date utcDate = Date.UtcToday;

Date tzSpecificDate = Date.TodayInTimeZone(anyTimeZoneInfoObject);

9
Điều gì về việc sử dụng DateTime.UtcNowthay vì DateTimeOffset.Now?
Samuel Liew

5
DateTime.UtcNowđược chấp nhận nếu bạn có thể truyền đạt trong ứng dụng của mình hoặc thông báo rằng giá trị đó nằm trong UTC. (Tôi thực sự muốn gọi trường hoặc thuộc tính một cái gì đó giống như MyDateUtcthay vì chỉ MyDate- nhưng đó chỉ là đóng băng trên bánh.) Nếu bạn không thể truyền đạt nó trong thông số kỹ thuật hoặc tên trường, thì DateTimeOffset.UtcNowcó thể được sử dụng để đảm bảo độ lệch bằng không được truyền đạt với các giá trị ngày và thời gian.
Matt Johnson-Pint

Họ không bằng nhau. Hôm nay có thời gian là 00:00:00.
James Wilkins

@JamesWilkins - Không chắc chắn những gì bạn đang nhận được. Cũng vậy DateTime.Now.Date.
Matt Johnson-Pint

@MattJohnson Câu hỏi là hỏi sự khác biệt giữa DateTime.Today và DateTime.Now, không phải DateTime.Today và DateTime.Now.Date.
David Anderson

85

Thời gian. .Nowbao gồm 09:23:12 hoặc bất cứ điều gì; .Todaychỉ là phần ngày (lúc 00:00:00 ngày hôm đó).

Vì vậy, sử dụng .Nownếu bạn muốn bao gồm thời gian, và .Todaynếu bạn chỉ muốn ngày!

.Today về cơ bản giống như .Now.Date


27
... và sử dụng UtcNowtrừ khi bạn thực sự muốn múi giờ địa phương của hệ thống. (Đặc biệt, trên một ứng dụng web hầu như luôn luôn là lựa chọn sai.)
Jon Skeet

22

Tài DateTime.Nowsản trả về ngày và thời gian hiện tại, ví dụ 2011-07-01 10:09.45310.

Ví dụ, thuộc DateTime.Todaytính trả về ngày hiện tại với các giá trị thời gian được đặt thành 0, chẳng hạn 2011-07-01 00:00.00000.

Các DateTime.Todaytài sản thực sự được thực hiện để trả lại DateTime.Now.Date:

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

9

DateTime.Today đại diện cho ngày hệ thống hiện tại với phần thời gian được đặt thành 00:00:00

DateTime.Now đại diện cho ngày và giờ hệ thống hiện tại


2
chỉ là một quan sát ... tài liệu 1.1 ít chi tiết hơn tài liệu 4.0; có lẽ tốt hơn để liên kết đến vLatest?
Marc Gravell

3
@megaperlz: Bây giờ bạn đang liên kết với 4.0 chứ không phải vLatest. Liên kết VLatest có thể được thực hiện bằng cách xóa (v=VS.100).
Brian

6

Tôi nghĩ đến việc thêm các liên kết này -

Quay trở lại câu hỏi ban đầu, Sử dụng Reflector tôi đã giải thích sự khác biệt trong mã

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

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

1

DateTime.TodayDateTime.Nowvới thời gian được đặt thành không.

Điều quan trọng cần lưu ý là có sự khác biệt giữa giá trị DateTime, đại diện cho số lượng đánh dấu đã trôi qua kể từ nửa đêm ngày 1 tháng 1 năm 0000 và biểu diễn chuỗi của giá trị DateTime đó, biểu thị giá trị ngày và thời gian trong một định dạng dành riêng cho văn hóa: https://msdn.microsoft.com/en-us/l Library / system.datetime.now% 28v = vs.110% 29.aspx

DateTime.Now.Tickslà thời gian thực tế được lưu trữ bởi .net (về cơ bản là thời gian UTC), phần còn lại chỉ là các biểu diễn (rất quan trọng cho mục đích hiển thị).

Nếu Kindtài sản là DateTimeKind.Localngầm bao gồm các thông tin múi giờ của máy tính cục bộ. Khi gửi qua dịch vụ web .net, các giá trị DateTime theo mặc định được tuần tự hóa với thông tin múi giờ được bao gồm, ví dụ 2008-10-31T15: 07: 38,6875000-05: 00 và một máy tính ở múi giờ khác vẫn có thể biết chính xác thời gian là gì được đề cập đến.

Vì vậy, sử dụng DateTime.Now và DateTime.Today là hoàn toàn OK.

Bạn thường bắt đầu gặp rắc rối khi bạn bắt đầu nhầm lẫn biểu diễn chuỗi với giá trị thực và cố gắng "sửa" DateTime, khi nó không bị hỏng.


-1

DateTime.Now.ToShortDateString() sẽ chỉ hiển thị phần ngày

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.