2009-09-08 33 views
94

Tôi muốn làm tròn ngày/giờ đến khoảng thời gian gần nhất cho một ứng dụng biểu đồ. Tôi muốn một chữ ký phương pháp khuyến nông như sau để làm tròn có thể đạt được đối với bất kỳ mức độ chính xác:Làm tròn đối tượng DateTime

static DateTime Round(this DateTime date, TimeSpan span); 

Ý tưởng là nếu tôi vượt qua trong một khoảng thời gian mười phút, nó sẽ tròn đến gần nhất khoảng mười phút. Tôi không thể có được đầu của tôi xung quanh việc thực hiện và hy vọng một trong các bạn sẽ có văn bản hoặc sử dụng một cái gì đó tương tự trước đây.

Tôi nghĩ rằng sàn, trần hoặc gần nhất là tốt.

Bất kỳ ý tưởng nào?

Edit: Nhờ @tvanfosson & @ShuggyCoUk, việc thực hiện trông như thế này:

public static class DateExtensions { 
    public static DateTime Round(this DateTime date, TimeSpan span) { 
     long ticks = (date.Ticks + (span.Ticks/2) + 1)/ span.Ticks; 
     return new DateTime(ticks * span.Ticks); 
    } 
    public static DateTime Floor(this DateTime date, TimeSpan span) { 
     long ticks = (date.Ticks/span.Ticks); 
     return new DateTime(ticks * span.Ticks); 
    } 
    public static DateTime Ceil(this DateTime date, TimeSpan span) { 
     long ticks = (date.Ticks + span.Ticks - 1)/span.Ticks; 
     return new DateTime(ticks * span.Ticks); 
    } 
} 

Và được gọi là như vậy:

DateTime nearestHour = DateTime.Now.Round(new TimeSpan(1,0,0)); 
DateTime minuteCeiling = DateTime.Now.Ceil(new TimeSpan(0,1,0)); 
DateTime weekFloor = DateTime.Now.Floor(new TimeSpan(7,0,0,0)); 
... 

Cheers!

+1

Một số việc triển khai ở đây có thể giúp quá: http://stackoverflow.com/questions/766626/is-there- a-tốt-way-in-c-to-round-a-datetime-to-the-gần-5-giây –

+1

có thể trùng lặp của [Có cách nào tốt hơn để cắt một DateTime thành một độ chính xác cụ thể không?] (http: //stackoverflow.com/questions/152774/is-there-a-better-way-to-trim-a-datetime-to-a-specific-precision) –

+1

Đừng quên thêm DateTimeKind ban đầu vào ngày tạo mới được tạo : DateTime mới (ticks * span.Ticks, date.Kind); –

Trả lời

112

Tầng

long ticks = date.Ticks/span.Ticks; 

return new DateTime(ticks * span.Ticks); 

Round (lên trên trung điểm)

long ticks = (date.Ticks + (span.Ticks/2) + 1)/ span.Ticks; 

return new DateTime(ticks * span.Ticks); 

trần

long ticks = (date.Ticks + span.Ticks - 1)/ span.Ticks; 

return new DateTime(ticks * span.Ticks); 
2

Chỉ cần sử dụng các Ticks, sử dụng để chia, sàn/ceil/làm tròn giá trị và nhân lại.

10

Bạn cũng nên rõ ràng nếu bạn muốn làm tròn đến:

  1. là bắt đầu, kết thúc hoặc giữa khoảng thời gian
    • bắt đầu là dễ nhất và thường được mong đợi nhưng bạn phải rõ ràng trong thông số ban đầu của mình.
  2. Cách bạn muốn các trường hợp đường viền tròn.
    • thường chỉ là vấn đề nếu bạn làm tròn đến giữa thay vì kết thúc.
    • Kể từ khi làm tròn đến giữa là một nỗ lực tại một câu trả lời tự do miễn phí, bạn cần phải sử dụng một cái gì đó giống như Bankers Rounding kỹ thuật làm tròn một nửa thậm chí để thực sự không bị thiên vị.

Nó là khá khả năng là bạn thực sự chỉ quan tâm đến điểm đầu tiên nhưng trong những câu hỏi 'đơn giản' hành vi kết quả có thể có đến nay đạt hậu quả khi bạn sử dụng nó trong thế giới thực (thường vào khoảng thời gian tiếp giáp với số không)

bìa giải pháp của tvanfosson tất cả các trường hợp được liệt kê trong 1. Ví dụ về điểm giữa là thiên vị lên trên. Đó là nghi ngờ rằng đây sẽ là một vấn đề trong thời gian làm tròn liên quan.

28

Điều này sẽ cho phép bạn làm tròn theo bất kỳ khoảng thời gian nào đã cho.Nó cũng nhanh hơn một chút so với chia và sau đó nhân bọ ve.

private static DateTime Floor(DateTime dateTime, TimeSpan interval) 
{ 
    return dateTime.AddTicks(-(dateTime.Ticks % interval.Ticks)); 
} 

private static DateTime Ceiling(DateTime dateTime, TimeSpan interval) 
{ 
    var overflow = dateTime.Ticks % interval.Ticks; 

    return overflow == 0 ? dateTime : dateTime.AddTicks(interval.Ticks - overflow); 
} 

private static DateTime Round(DateTime dateTime, TimeSpan interval) 
{ 
    var halfIntervalTicks = (interval.Ticks + 1) >> 1; 

    return dateTime.AddTicks(halfIntervalTicks - ((dateTime.Ticks + halfIntervalTicks) % interval.Ticks)); 
} 
-3

Nếu bạn chỉ muốn làm tròn lên Giờ đến giá trị gia tăng trần

Console.WriteLine(DateTime.Now.ToString("M/d/yyyy hh:00:00")); 
+0

OP đã yêu cầu DateTime làm đối tượng trả về. –

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