2011-11-10 9 views
13

Czy istnieje jakiś matematyczny sposób na przycięcie DateTime do dokładnej godziny, dnia lub tak? Podobne do rundy od dziesiętnej do int.Wycinanie/zaokrąglanie DataTime do całości, np. Godzina/dzień?

Period.Day
Jeśli oryginalna wartość była 2011-01-01 13:00:00, kończy się w 2011-01-01 00:00:00

jeśli Period.Hour
Jeśli oryginalna wartość była 2011-03-11 13:32:00, kończy się w 2011-03-11 13:00:00

myślę o coś jak poniżej. To oczywiście działa dobrze, ale ta -platka jest później iterowana. Lepiej, gdybym mógł obliczyć bezpośrednio w tej iteracji zamiast własnej. Ale someType nie można umieścić w tej iteracji (zależy to od someType).

if (someType == Period.Day) 
    range.ForEach(d => d.time = new DateTime(d.time.Year, d.time.Month, d.time.Day,0,0,0)); 
if (someType == Period.Hour) 
    range.ForEach(d => d.time = new DateTime(d.time.Year, d.time.Month, d.time.Day, d.time.Hour, 0, 0)); 
+1

Twoje przykłady nie zaokrąglić do najbliższego.Obcinają/zaokrąglają. – CodesInChaos

+0

Zastąpić 'ForEach' za pomocą' Select'? –

+0

@CodeInChaos Masz całkowitą rację. Zmienię tytuł, ponieważ jest zwodniczy. – Independent

Odpowiedz

14

zaokrąglenie w dół do jednego dnia jest równoważna time.Date, zaokrąglanie do najbliższego (w górę na środkowym) jest po prostu (time + 12hours).Date.

Zaokrąglanie do pełnej godziny Nie mogę wymyślić kodu, który będzie ładniejszy niż Twój. Aby zaokrąglić do najbliższej godziny, możesz zastosować swój kod do time + 30mins.

Nie ma chyba szybszego sposobu zaokrąglania do najbliższej godziny:

const Int64 HourInTicks=...; 
Int64 timeInTicks=time.Ticks; 
Int64 trucatedToHour=timeInTicks-timeInTicks%HourInTicks; 

Ale ja tego uniknąć, chyba że naprawdę potrzebują wydajności, co jest mało prawdopodobne.

(My zaokrąglenie do najbliższej może mieć problemy w dniach gdzie zrównoważyć czas lokalny zmian jeśli używasz czasu lokalnego)

+0

Tak, bardzo mała różnica w wydajności między tymi dobrymi odpowiedziami tutaj. W końcu przejdę do najbardziej czytelnej i klarownej drogi (ponieważ sama funkcjonalność jest trochę niejasna). Prowadzę foreach, ale przez "sprytny (data, okres)" - metoda i zaraz po źródle danych. Co oznacza, że ​​cała procedura jest już wykonana przez tę pętlę. – Independent

12

Aby zaokrąglić w dół do dnia można użyć DateTime.Date Property.
Aby zaokrąglić w dół do godziny obawiam musisz użyć tego, co zrobiłeś w swoim przykład czy coś jak:

d.Date.AddHours(d.Hour) 
0

Odpowiedź Is there a better way in C# to round a DateTime to the nearest 5 seconds? zawiera doskonałą generic DateTime zaokrąglania podejście.

Edit: Ta odpowiedź była przed zaktualizowanego tytułu zapytania i jest algorytm zaokrąglanie do najbliższego nie zaokrąglenie w dół.

+0

Och, spojrzałem na to (i tylko na zaakceptowaną odpowiedź). Miła funkcja od Matt W. To rozwiązuje moje pytanie całkowicie wraz z niewielką modyfikacją. RoundOff z TimeSpan.FromTicks (X). Dostaję kleszcze od Period.Miesiąc/Period.Days i whola, połączenie jest ogólne! Chociaż nie zapewnia żadnej wydajności z mojej własnej próbki, która wykonała podwójną iterację. Rozwijające się są czasem tak nieobliczalne .. :) – Independent

+0

Twoja odpowiedź jest w porządku! – Independent

2

Zrobię, co następuje:

private static readonly DateTime Epoch = new DateTime(1970, 1, 1); 
public static DateTime Round(this DateTime d, Period p) 
{ 
    var ts = d - Epoch; 

    if (p == Period.Hour) 
    { 
     var hours = (long)ts.TotalHours; 
     return Epoch.AddHours(hours); 
    } 
    else if (p == Period.Days) 
    { 
     var days = (long)ts.TotalDays; 
     return Epoch.AddDays(days); 
    } 
    // ... 
} 
1

wierzę następujący kod C# będzie zaokrąglić wartość DateTime do najbliższej minuty, i myślę, że będzie łatwo uogólnić go zaokrąglić do innych jednostek.

//round to nearest minute; add 30 seconds for rounding to nearest minute 
effectiveDateTime = effectiveDateTime.AddSeconds(30); 
TimeSpan timeComponent = effectiveDateTime.TimeOfDay; 
effectiveDateTime = effectiveDateTime.Date; 
effectiveDateTime = effectiveDateTime.AddHours(timeComponent.Hours). 
    AddMinutes(timeComponent.Minutes); 
1

Nie wiem, czy to podejście jest skuteczne, ale wygląda całkiem miłe użyciu format string (w tym przypadku cięcia aż do godziny):

var date = DateTime.UtcNow; 
var cutDownDate = Convert.ToDateTime(date.ToString("yyyy-MM-dd hh")); 
Powiązane problemy