2011-07-01 42 views

Trả lời

120

DateTime.Now trả về một giá trị DateTime đó bao gồm các ngày trong nước và thời gian của máy tính nơi đang chạy. Nó có DateTimeKind.Local được gán cho thuộc tính Kind của nó.Nó tương đương với gọi bất cứ điều 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.Today trả về một giá trị DateTime có cùng một năm, tháng, và các thành phần 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 0. Nó cũng có DateTimeKind.Local trong thuộc tính Kind của nó. Nó tương đương với bất kỳ những điều 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 nội bộ, đồng hồ hệ thống là về UTC, vì vậy khi bạn gọi DateTime.Now nó lần đầu tiên nhận được thời gian UTC (thông qua hàm GetSystemTimeAsFileTime trong API Win32) và sau đó nó chuyển đổi giá trị thành múi giờ địa phương. (Vì vậy DateTime.Now.ToUniversalTime() đắt hơn DateTime.UtcNow.)

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

Vì vậy, câu trả lời đơn giản là DateTime.Today tương đương với DateTime.Now.Date.
Nhưng IMHO - Bạn không nên sử dụng một trong hai thứ này hoặc bất kỳ điều 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 được trở lại không có bất kỳ thông tin về đồng hồ đó! Điều tốt nhất bạn nhận được là DateTime.Now.Kind == DateTimeKind.Local. Nhưng có địa phương là nó? Thông tin đó sẽ bị mất ngay sau 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ị nó 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 không nhận được thông tin đó từ DateTime.Now. Trong thời gian không rõ ràng, chẳng hạn như trong quá trình chuyển đổi "thu nhỏ", bạn sẽ không biết thời điểm nào trong hai khoảnh khắc có thể tương ứng với giá trị bạn đã truy xuất bằng 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.Now vào đầu giờ ngày 3 tháng 11 năm 2013. Kết quả có nghĩa là gì 2013-11-03 01:00:00? Có hai khoảnh khắc của thời gian tức thời được biểu thị bằng cùng một ngày giờ. Nếu tôi gửi giá trị này cho người khác, họ sẽ không biết tôi có ý gì. Đặc biệt là 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 sẽ được sử dụng thay vì DateTimeOffset:

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

Bây giờ cho 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 -0600 trước khi chuyển đổi, hoặc 2013-11-03 01:00:00 -0700 sau khi chuyển đổi. Bất cứ ai nhìn vào những giá trị này đều có thể nói những gì tôi muốn nói.

Tôi đã viết một bài đăng trên blog về chủ đề này. Vui lòng đọc - The Case Against DateTime.Now.

Ngoài ra, có một số địa điểm trên thế giới này (chẳng hạn như Brazil), nơi quá trình chuyển đổi "mùa xuân" diễn ra chính xác vào 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 cho DateTime.Today và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 sự cố này. Đó là bởi vì theo truyền thống, không có những thứ như đối tượng Date trong .Net. Vì vậy, bất kể bạn có được giá trị như thế nào, một khi bạn loại 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 có 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. Lớp LocalDate thể hiện đúng ngày không có thời gian. Bạn có thể lấy ngày hiện tại cho bất kỳ múi giờ nào, bao gồm múi giờ 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 Giờ Noda, bây giờ có một tùy chọn khác. Tôi đã đóng góp việc triển khai đối tượng chỉ có ngày vào dự án .Net CoreFX Lab. Bạn có thể tìm đối tượng gói System.Time trong nguồn cấp dữ liệu MyGet của họ. Khi bổ sung vào dự án của bạn, bạn sẽ tìm thấy bạn có thể làm bất cứ điều nào sau đây:

using System; 
... 

Date localDate = Date.Today; 

Date utcDate = Date.UtcToday; 

Date tzSpecificDate = Date.TodayInTimeZone(anyTimeZoneInfoObject); 
+7

Điều gì về việc sử dụng 'DateTime.UtcNow' thay vì' DateTimeOffset.Now'? –

+5

'DateTime.UtcNow' là có thể chấp nhận được nếu bạn có thể truyền đạt trong ứng dụng của bạn hoặc chỉ ra rằng giá trị là UTC. (Tôi thích thực sự gọi trường hoặc thuộc tính giống như 'MyDateUtc' thay 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 tên spec hoặc field, thì 'DateTimeOffset.UtcNow 'có thể được sử dụng để đảm bảo bù trừ zero được chuyển tải với các giá trị ngày tháng và thời gian. –

+0

Chúng không bằng nhau. Hôm nay có thời gian là 00:00:00. –

78

Thời gian. .Now bao gồm các 09:23:12 hoặc bất cứ điều gì; .Today chỉ là ngày tháng (vào lúc 00:00:00 vào ngày đó).

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

.Today là cơ bản giống như .Now.Date

+25

...và sử dụng 'UtcNow' trừ khi bạn * thực sự * muốn múi giờ địa phương của hệ thống. (Cụ thể, trên một ứng dụng web hầu như luôn là lựa chọn sai.) –

9

DateTime.Today đại diện cho ngày hệ thống hiện tại với phần thiết lập thời gian để 00:00:00

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

+2

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

+0

quyền của bạn tôi đã thay đổi các liên kết –

+3

@megaperlz: Bạn hiện đang liên kết tới 4.0 thay vì vLatest. Các liên kết VLatest có thể được thực hiện bằng cách xóa '(v = VS.100)'. – Brian

20

Thuộc tính DateTime.Now trả về ngày và giờ hiện tại, ví dụ 2011-07-01 10:09.45310.

Thuộc tính DateTime.Today trả về ngày hiện tại với thời gian được đặt thành 0, ví dụ 2011-07-01 00:00.00000.

Thuộc tính DateTime.Today thực sự được thực hiện để trở DateTime.Now.Date:

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

ví dụ rất đơn giản với sự khác biệt rõ ràng – Cherry

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 
6

tôi nghĩ thêm những liên kết này -

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

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

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

Nếu thuộc tính KindDateTimeKind.Localngầm định bao gồm thông tin múi giờ của máy tính cục bộ. Khi gửi qua dịch vụ web .net, giá trị Ngày giờ 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áy tính ở múi giờ khác vẫn có thể biết chính xác thời gian được giới thiệu.

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

Bạn thường bắt đầu gặp sự cố 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.

Các vấn đề liên quan