Bất cứ ai có thể giải thích sự khác biệt giữa System.DateTime.Now
và System.DateTime.Today
trong C # .NET? Ưu và nhược điểm của mỗi nếu có thể.
Bất cứ ai có thể giải thích sự khác biệt giữa System.DateTime.Now
và System.DateTime.Today
trong C # .NET? Ưu và nhược điểm của mỗi nếu có thể.
Câu trả lời:
DateTime.Now
trả về một DateTime
giá 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 Kind
tà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.Today
trả về một DateTime
giá 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.Local
trong Kind
tà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.Now
nó trước tiên sẽ có thời gian UTC (thông qua GetSystemTimeAsFileTime
chứ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.DateTime
sẽ có các giá trị tương tự DateTime.Now
, nhưng nó sẽ có DateTimeKind.Unspecified
hơ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.Today
là 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.Now
vào đầu giờ ngày 3 tháng 11 năm 2013. Kết quả 2013-11-03 01:00:00
có ý 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 DateTimeOffset
thay 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 -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 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.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 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 LocalDate
lớ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);
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ư 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 thông số kỹ thuật hoặc tên trường, thì DateTimeOffset.UtcNow
có 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.
DateTime.Now.Date
.
Thời gian. .Now
bao gồm 09:23:12 hoặc bất cứ điều gì; .Today
chỉ là phần ngày (lúc 00:00:00 ngày hôm đó).
Vì vậ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
về cơ bản giống như .Now.Date
UtcNow
trừ 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.)
Tài DateTime.Now
sả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.Today
tí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.Today
tà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;
}
}
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
và
DateTime.Now đại diện cho ngày và giờ hệ thống hiện tại
(v=VS.100)
.
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);
}
}
DateTime.Today
là DateTime.Now
vớ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.Ticks
là 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 Kind
tài sản là DateTimeKind.Local
nó ngầ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.
DateTime.UtcNow
thay vìDateTimeOffset.Now
?