2013-05-22 3 views
11

zu finden Wenn ich ein Array von Datetime-Werte haben:Wie eine durchschnittliche Datum/Uhrzeit in der Anordnung von Datums- und Uhrzeitwerten

List<DateTime> arrayDateTimes; 

Was ist der Weg, um die durchschnittliche Datetime unter ihnen zu finden?

Zum Beispiel, wenn ich habe:

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

die durchschnittliche sein sollte:

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

+1 schöne Frage. Siehe http://42zone.blogspot.com/2011/09/c-how-to-calculate-multiple-datetime.html, habe es gerade getestet und arbeite mit über 38.000 Daten. – Habib

+0

beachten Sie, dass einige Antworten Zeitzone Informationen erhalten und andere nicht .. – Cel

Antwort

9

Wenn Sie große Liste haben Sie unter Methode

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

Es wird Überlauf Ausnahme mit großen Liste werfen. –

+0

** Daten [i] .Ticks/Anzahl ** gibt 0 zurück, wenn Anzahl> Ticks – Uzzy

+0

Console.WriteLine (Ticks/(Ticks + 1)); Console.WriteLine (ticks/long.MaxValue); Was würde gedruckt werden? – 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

Ich mache es offensichtlich nicht mit 3 Werten :) Ihre Methode wird mit ungefähr 20 Daten überlaufen. – c00000fd

+0

@ c00000fd: 40 Datumsangaben und eine Erweiterungsmethode nach, es gibt keinen Überlauf mehr. –

+1

Ja, danke. Obwohl es bereits von @Damith oben vorgeschlagen wurde. – c00000fd

5

verwenden können Dies sollte nicht überlaufen, es übernimmt das Datum Es sind jedoch bestellt:

Die oben genannten tatsächlich überläuft mit größeren Listen und größere Lücken. Ich denke, Sie könnten Sekunden für bessere Bereich verwenden. (wieder, zuerst sortiert) Auch dies ist vielleicht nicht die performanteste Methode, aber immer noch mit 10M Daten relativ schnell für mich abgeschlossen. Nicht sicher, ob es leichter zu lesen ist oder nicht, YYMV.

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

Ich bin mir nicht sicher, ob ich folge. Zecken sind vom Typ lang. Ein zukünftiger Tick, abzüglich eines vergangenen Ticks, ergibt eine relativ kleine Anzahl und sollte niemals die Möglichkeit haben, zu überlaufen. – neouser99

+0

Hmm. Ja, vielleicht hast du Recht. Lassen Sie mich überprüfen ... – c00000fd

+0

Ich denke, es ist eine ziemlich gute Option. Müssen testen, um sicher zu sein :) –

0

Quelle: Entnommen Here und ein wenig modifiziert.

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 

Dann können Sie tun:

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

Ausgabe in: 1956-Dec-29 06:09:25

Ursprünglich war der Code aus dem Artikel wie:

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

Der Code:

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

ist falsch. Durchschnitt = (x1 + x2 + ... xN)/N nicht (x1/N + x2/N + ... xN/N)

Versuchen:

var avg=new DateTime((long)dates.Select(d => d.Ticks).Average()); 
Verwandte Themen