2013-05-22 37 views
11

Nếu tôi có một mảng các giá trị DateTime:Làm thế nào để tìm thấy một ngày trung bình/giờ trong mảng của DateTime giá trị

List<DateTime> arrayDateTimes; 

cách để tìm ra DateTime trung bình trong số đó là gì?

Ví dụ, nếu tôi có:

2003-May-21 15:00:00 
2003-May-21 19:00:00 
2003-May-21 20:00:00 

mức trung bình nên là:

2003-May-21 18:00:00 
+2

+1 đẹp câu hỏi. Xem http://42zone.blogspot.com/2011/09/c-how-to-calculate-multiple-datetime.html này, chỉ cần thử nghiệm và làm việc với hơn 38.000 ngày. – Habib

+0

lưu ý rằng một số câu trả lời bảo tồn thông tin múi giờ và những người khác không .. – Cel

Trả lời

9

Nếu bạn có danh sách lớn, bạn có thể sử dụng dưới phương pháp

var count = dates.Count; 
double temp = 0D; 
for (int i = 0; i < count; i++) 
{ 
    temp += dates[i].Ticks/(double)count; 
} 
var average = new DateTime((long)temp); 
+6

Nó sẽ ném ngoại lệ tràn với danh sách lớn. –

+0

** ngày [i] .Quick/count ** sẽ trả về 0 nếu đếm> Ticks – Uzzy

+0

Console.WriteLine (ticks/(ticks + 1)); Console.WriteLine (ve/long.MaxValue); Điều gì sẽ được in? – Uzzy

0
class Program 
{ 
    static void Main(string[] args) 
    { 
     List<DateTime> dates = new List<DateTime>(){ 
     new DateTime(2003, 5, 21, 16, 0, 0), new DateTime(2003, 5, 21, 17, 0, 0), 
     new DateTime(2003, 5, 21, 18, 0, 0), new DateTime(2003, 5, 21, 19, 0, 0), 
     new DateTime(2003, 5, 21, 20, 0, 0), new DateTime(2003, 5, 21, 16, 0, 0), 
     new DateTime(2003, 5, 21, 17, 0, 0), new DateTime(2003, 5, 21, 18, 0, 0), 
     new DateTime(2003, 5, 21, 19, 0, 0), new DateTime(2003, 5, 21, 20, 0, 0), 
     new DateTime(2003, 5, 21, 16, 0, 0), new DateTime(2003, 5, 21, 17, 0, 0), 
     new DateTime(2003, 5, 21, 18, 0, 0), new DateTime(2003, 5, 21, 19, 0, 0), 
     new DateTime(2003, 5, 21, 20, 0, 0), new DateTime(2003, 5, 21, 16, 0, 0), 
     new DateTime(2003, 5, 21, 18, 0, 0), new DateTime(2003, 5, 21, 19, 0, 0), 
     new DateTime(2003, 5, 21, 20, 0, 0), new DateTime(2003, 5, 21, 16, 0, 0), 
     new DateTime(2003, 5, 21, 18, 0, 0), new DateTime(2003, 5, 21, 19, 0, 0), 
     new DateTime(2003, 5, 21, 20, 0, 0), new DateTime(2003, 5, 21, 16, 0, 0), 
     new DateTime(2003, 5, 21, 18, 0, 0), new DateTime(2003, 5, 21, 19, 0, 0), 
     new DateTime(2003, 5, 21, 20, 0, 0), new DateTime(2003, 5, 21, 16, 0, 0), 
     new DateTime(2003, 5, 21, 18, 0, 0), new DateTime(2003, 5, 21, 19, 0, 0), 
     new DateTime(2003, 5, 21, 20, 0, 0), new DateTime(2003, 5, 21, 16, 0, 0), 
     new DateTime(2003, 5, 21, 18, 0, 0), new DateTime(2003, 5, 21, 19, 0, 0), 
     new DateTime(2003, 5, 21, 20, 0, 0), new DateTime(2003, 5, 21, 16, 0, 0), 
     new DateTime(2003, 5, 21, 18, 0, 0), new DateTime(2003, 5, 21, 19, 0, 0), 
     new DateTime(2003, 5, 21, 20, 0, 0), new DateTime(2003, 5, 21, 16, 0, 0), 
    }; 

     var averageDate = dates.Average(); 

     Console.WriteLine(averageDate); 

     Console.ReadKey(); 
    } 

} 

public static class Extensions 
{ 
    public static long Average(this IEnumerable<long> longs) 
    { 
     long count = longs.Count(); 

     long mean = 0; 

     foreach (var val in longs) 
     { 
      mean += val/count; 
     } 

     return mean; 
    } 

    public static DateTime Average(this IEnumerable<DateTime> dates) 
    { 
     return new DateTime(dates.Select(x => x.Ticks).Average()); 
    } 
} 
+0

Tôi rõ ràng không làm điều đó với 3 giá trị :) Phương pháp của bạn sẽ tràn với khoảng 20 ngày. – c00000fd

+0

@ c00000fd: 40 giờ dữ liệu và một phương thức mở rộng sau, không còn tràn nữa. –

+1

Vâng, cảm ơn. Mặc dù nó đã được đề xuất bởi @Damith ở trên. – c00000fd

5

Điều này không nên tràn, nó giả định datetim es được đặt hàng mặc dù:

var first = dates.First().Ticks; 
var average = new DateTime(first + (long) dates.Average(d => d.Ticks - first)); 

Trên thực tế tràn với danh sách lớn hơn và khoảng trống lớn hơn. Tôi nghĩ bạn có thể sử dụng giây để có dải số tốt hơn. (một lần nữa, được sắp xếp đầu tiên) Ngoài ra, đây có thể không phải là phương pháp hiệu quả nhất, nhưng vẫn hoàn thành với 10 triệu ngày tương đối nhanh cho tôi. Bạn không chắc chắn có dễ đọc hay không, YYMV.

var first = dates.First(); 
var average = first.AddSeconds(dates.Average(d => (d - first).TotalSeconds)); 
+0

Tôi không chắc chắn tôi làm theo. Ticks có kiểu dài. Một dấu tích trong tương lai, trừ dấu tích trong quá khứ, sẽ cho một số lượng tương đối nhỏ và không bao giờ có khả năng bị tràn. – neouser99

+0

Hmm. Vâng, bạn có thể có một điểm. Hãy để tôi kiểm tra ... – c00000fd

+0

Tôi nghĩ rằng đó là lựa chọn khá tốt. Cần phải kiểm tra để chắc chắn :) –

0

Nguồn: Lấy từ Here và sửa đổi một chút.

List<DateTime> dates = new List<DateTime>(); 
//Add dates 
for (int i = 1; i <= 28; i++) //days 
    for (int j = 1; j <= 12; j++) //month 
     for (int k = 1900; k <= 2013; k++) //year 
      dates.Add(new DateTime(k, j, i, 1, 2, 3)); //over 38000 dates 

Sau đó, bạn có thể làm:

var averageDateTime = DateTime 
          .MinValue 
          .AddSeconds 
          ((dates 
           .Sum(r => (r - DateTime.MinValue).TotalSeconds)) 
            /dates.Count); 
Console.WriteLine(averageDateTime.ToString("yyyy-MMM-dd HH:mm:ss")); 

Output trong: 1956-Dec-29 06:09:25

Nguyên mã từ bài viết giống như:

double totalSec = 0; 
for (int i = 0; i < dates.Count; i++) 
{ 
    TimeSpan ts = dates[i].Subtract(DateTime.MinValue); 
    totalSec += ts.TotalSeconds; 
} 
double averageSec = totalSec/dates.Count; 
DateTime averageDateTime = DateTime.MinValue.AddSeconds(averageSec); 
1

Mã:

var count = dates.Count; 
double temp = 0D; 
for (int i = 0; i < count; i++) 
{ 
    temp += dates[i].Ticks/(double)count; 
} 
var average = new DateTime((long)temp); 

là sai. Trung bình = (x1 + x2 + ... xN)/N không (x1/N + x2/N + ... xN/N)

Hãy thử:

var avg=new DateTime((long)dates.Select(d => d.Ticks).Average()); 
Các vấn đề liên quan