2009-05-24 36 views
35

Trong ứng dụng C# của tôi, tôi chuyển một biến chuỗi có định dạng yyyymmdd-yyyymmdd đại diện cho một từ và cho đến nay. Tôi muốn có thời gian bắt đầu và kết thúc cho những ngày này tương ứng. Hiện tại tôi có mã dưới đây nhưng đã tự hỏi liệu có nhiều giải pháp thanh lịch hơn không?Cách nhận thời gian bắt đầu và kết thúc trong một ngày

Vì vậy, đối PDR = 20.090.521-20.090.523 sẽ nhận được "20.090.521 00:00:00" và "20.090.523 23:59:59"

private void ValidateDatePeriod(string pdr, out DateTime startDate, 
           out DateTime endDate) 
{ 
    string[] dates = pdr.Split('-'); 

    if (dates.Length != 2) 
    { 
     throw new Exception("Date period is of incorrect format"); 
    } 

    if (dates[0].Length != 8 || dates[1].Length != 8) 
    { 
     throw new Exception("Split date periods are of incorrect format"); 
    } 

    startDate = DateTime.ParseExact(dates[0] + " 00:00:00", 
     "yyyyMMdd HH:mm:ss", null); 
    endDate = DateTime.ParseExact(dates[1] + "23:59:59", 
     "yyyyMMdd HH::mm:ss", null); 
} 
+0

Như những người khác đã nói, EndOfDay có lẽ là một cấu trúc không cần thiết và không chính xác, vì nó không có thời điểm xác định, ngoại trừ có lẽ StartOfDay của ngày mai. – user420667

Trả lời

13

Nếu bạn chỉ lo lắng về Net chính xác ...

startDate = DateTime.ParseExact(dates[0], "yyyyMMdd"); 
endDate = DateTime.ParseExact(dates[1], "yyyyMMdd").AddTicks(-1).AddDays(1); 

Bạn thực sự không cần phải nối các giá trị thêm vào chuỗi cho phần thời gian.


Là một phụ lục, nếu bạn đang sử dụng này cho một truy vấn chống lại, ví dụ, một cơ sở dữ liệu ...

startDate = DateTime.ParseExact(dates[0], "yyyyMMdd"); 
endDate = DateTime.ParseExact(dates[1], "yyyyMMdd").AddDays(1); 

Với một truy vấn của ...

WHERE "startDate" >= @startDate AND "endDate" < @endDate 

Sau đó, các vấn đề chính xác ghi nhận trong các ý kiến ​​sẽ không thực sự quan trọng. endDate trong trường hợp này sẽ không nằm trong phạm vi, nhưng ranh giới bên ngoài.

+0

NB: nếu bạn đang làm việc với một cơ sở dữ liệu, bạn có thể phải đọc bản in nhỏ về độ chính xác của cơ sở dữ liệu cho 'cuối ngày'. Ví dụ tôi nhấn là kiểu DateTime của SQL Server. Chính xác đến khoảng 3 mili giây để kết thúc ngày trở thành .Thêm một vài giây (-3) –

+2

@ChrisFCarroll Cá nhân, tôi thích sử dụng 'dtm> = start && dtm Tracker1

+0

Tôi nghĩ bạn đã khiến tôi nhận ra rằng 'cuối ngày' là một khái niệm không tồn tại, và do đó chúng tôi đang làm điều đó sai. Sử dụng '

9

Đối tượng DateTime có một tính chất gọi Date đó sẽ trở lại chỉ là phần ngày. (Phần thời gian được mặc định là 12:00 sáng).

Tôi khuyên bạn nên dùng giải pháp thanh lịch hơn (IMHO) nếu bạn muốn cho phép bất kỳ ngày giờ nào vào ngày cuối cùng, sau đó thêm 1 ngày vào ngày và so sánh để cho phép thời gian lớn hơn hoặc bằng ngày bắt đầu , nhưng hoàn toàn ít hơn ngày kết thúc (cộng thêm 1 ngày).

// Calling code. beginDateTime and endDateTime are already set. 
// beginDateTime and endDateTime are inclusive. 
// targetDateTime is the date you want to check. 
beginDateTime = beginDateTime.Date; 
endDateTime = endDateTime.Date.AddDays(1); 

if (beginDateTime <= targetDateTime && 
    targetDateTime < endDateTime) 
    // Do something. 
+0

Tôi muốn trả lại 2 datetimes từ phân tích cú pháp một chuỗi, vì vậy phương thức gọi có thể sử dụng những ngày này để truy vấn db của tôi. – David

+1

@Matt: lời khuyên của bạn đặc biệt là âm thanh nếu thời gian có thể có độ phân giải phụ thứ hai. –

4

Đó là khá nhiều những gì tôi sẽ làm gì, với một số thay đổi nhỏ (thực sự không có vấn đề lớn, chỉ soi mói):

  • Các TryParse()/TryParseExact() phương pháp nên được sử dụng mà trở false thay vì ném ngoại lệ .
  • FormatException là cụ thể hơn so Exception
  • Không cần phải kiểm tra Chiều dài == 8, vì ParseExact()/TryParseExact() sẽ làm điều này
  • "00:00:00""23:59:59" không cần thiết
  • trở true/false là bạn đã có thể phân tích cú pháp, thay vì ném một ngoại lệ (hãy nhớ kiểm tra giá trị được trả lại từ phương thức này!)

Mã:

private bool ValidateDatePeriod(string pdr, out DateTime startDate, 
         out DateTime endDate) 
{ 
    string[] dates = pdr.Split('-'); 

    if (dates.Length != 2) 
    { 
     return false; 
    } 

    // no need to check for Length == 8 because the following will do it anyway 
    // no need for "00:00:00" or "23:59:59" either, I prefer AddDays(1) 

    if(!DateTime.TryParseExact(dates[0], "yyyyMMdd", null, DateTimeStyles.None, out startDate)) 
     return false; 

    if(!DateTime.TryParseExact(dates[1], "yyyyMMdd", null, DateTimeStyles.None, out endDate)) 
     return false; 

    endDate = endDate.AddDays(1); 
    return true; 
} 
+0

cảm ơn cho các ý kiến. Điều tốt để biết tôi đã đi đúng hướng và biết ơn các tinh chỉnh – David

33

Bạn có thể xác định hai phương pháp khuyến nông ở đâu đó, trong một lớp tiện ích như vậy:

public static DateTime EndOfDay(this DateTime date) 
{ 
    return new DateTime(date.Year, date.Month, date.Day, 23, 59, 59, 999); 
} 

public static DateTime StartOfDay(this DateTime date) 
{ 
    return new DateTime(date.Year, date.Month, date.Day, 0, 0, 0, 0); 
} 

Và sau đó sử dụng chúng trong mã như vậy:

public DoSomething() 
{ 
    DateTime endOfThisDay = DateTime.Now.EndOfDay(); 
} 
+3

Câu trả lời hay, nhưng không chính xác. Vui lòng xem ảnh chụp màn hình mà tôi đã cung cấp để xem lý do. –

+1

Thật vậy. Sử dụng Anar Khalilov, nó tốt hơn. –

+0

http://stackoverflow.com/a/20565672/1775459 – Vadim

103

Tôi ngạc nhiên khi một incorrect answer xem như thế nào đã nhận được rất nhiều phiếu bầu hữu ích:

Wrong value

Phiên bản chính xác sẽ như sau:

public static DateTime StartOfDay(this DateTime theDate) 
{ 
    return theDate.Date; 
} 

public static DateTime EndOfDay(this DateTime theDate) 
{ 
    return theDate.Date.AddDays(1).AddTicks(-1); 
} 
+2

như đã đề cập bởi @Chris F Carroll, -1 đánh dấu có thể không chính xác. – liang

+2

@liang, ông đã đề cập: "AddTick (-1) chỉ hoạt động theo quy ước rằng không có khoảng thời gian nhỏ hơn một dấu". Có một thời gian nhỏ hơn inverval trong. NET? –

+3

Ông đưa ra ví dụ khi làm việc với cơ sở dữ liệu. Việc triển khai cơ sở dữ liệu khác nhau. Khi trong các kịch bản đó, -1 đánh dấu có thể không còn là kết thúc của ngày nữa. Ít nhất, không nên dựa vào để sử dụng so sánh bằng nhau. Trong cùng tinh thần của các số trôi nổi, bạn không thể nói số nổi lớn nhất nhỏ hơn số nguyên đáng tin cậy phụ thuộc vào chi tiết triển khai là gì. Thay vì/lớn hơn có lẽ tốt hơn. – liang

2

Tôi nghĩ chúng tôi đang làm sai. Không có thứ gì như cuối ngày. AddTick(-1) chỉ hoạt động theo quy ước rằng không có khoảng thời gian nào nhỏ hơn dấu tích. Phụ thuộc thực hiện là gì. Phải thừa nhận rằng những câu hỏi đi kèm với một thực hiện tham khảo, cụ thể là DateTime lớp .Net Framework, nhưng vẫn còn chúng ta nên thực hiện việc này như một đầu mối rằng chức năng, chúng tôi thực sự muốn không phải là EndOfDay() nhưng StartOfNextDay()

public static DateTime StartOfNextDay(this DateTime date) 
{ 
    return date.Date.AddDays(1); 
} 
+1

Tại sao chúng ta không làm điều đó AddSeconds (-1), thay vì Add Ticks? Thứ hai cuối cùng trong ngày là đủ chính xác cho hầu hết các trường hợp. – liang

2

tôi sử dụng sau trong C#

public static DateTime GetStartOfDay(DateTime dateTime) 
{ 
    return new DateTime(dateTime.Year, dateTime.Month, dateTime.Day, 0, 0, 0, 0); 
} 
public static DateTime GetEndOfDay(DateTime dateTime) 
{ 
    return new DateTime(dateTime.Year, dateTime.Month, dateTime.Day, 23, 59, 59, 999); 
} 

sau đó, trong MS SQL tôi làm như sau:

if datepart(ms, @dateEnd) = 0 
    set @dateEnd = dateadd(ms, -3, @dateEnd) 

Điều này sẽ dẫn MS SQL thời gian của 23: 59: 59,997 là thời gian tối đa trước khi trở thành ngày hôm sau.

Bạn chỉ có thể sử dụng:

new DateTime(dateTime.Year, dateTime.Month, dateTime.Day, 23, 59, 59, 999); 

nào sẽ làm việc trong MS SQL, nhưng điều này không phải là chính xác ở bên Net.

0

Đối với SQL Server (phiên bản 2008 R2 được thử nghiệm) phạm vi này hoạt động.

Stardate '2016/01/11 00: 00: 01,990' EndDate '2016/01/19 23: 59: 59,990'

Có vẻ như ve lớn rằng giây cuối cùng trong ngày và tự động tròn để ngày tiếp theo. Vì vậy, tôi kiểm tra và làm việc, tôi đã thực hiện một bảng giả với hai ngày để kiểm tra những giá trị là máy chủ sql bắt và chèn vào các thủ tục được lưu trữ các thông số.

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