2008-09-30 6 views
38

Was ist die beste Methode, um ein DateTime-Objekt auf eine bestimmte Genauigkeit zu trimmen? Zum Beispiel, wenn ich eine DateTime mit einem Wert von "2008-09-29 09:41:43" habe, aber ich möchte nur, dass die Genauigkeit auf die Minute genau ist, gibt es dann einen besseren Weg?Gibt es eine bessere Möglichkeit, eine DateTime auf eine bestimmte Genauigkeit zu trimmen?

private static DateTime TrimDateToMinute(DateTime date) 
{ 
    return new DateTime(
     date.Year, 
     date.Month, 
     date.Day, 
     date.Hour, 
     date.Minute, 
     0); 
} 

Was würde ich wirklich will, ist es variabel zu machen, damit ich seine Präzision auf die Sekunde, Minute, Stunde oder Tag einstellen könnte.

Antwort

71
static class Program 
{ 
    //using extension method: 
    static DateTime Trim(this DateTime date, long roundTicks) 
    { 
     return new DateTime(date.Ticks - date.Ticks % roundTicks, date.Kind); 
    } 

    //sample usage: 
    static void Main(string[] args) 
    { 
     Console.WriteLine(DateTime.Now); 
     Console.WriteLine(DateTime.Now.Trim(TimeSpan.TicksPerDay)); 
     Console.WriteLine(DateTime.Now.Trim(TimeSpan.TicksPerHour)); 
     Console.WriteLine(DateTime.Now.Trim(TimeSpan.TicksPerMillisecond)); 
     Console.WriteLine(DateTime.Now.Trim(TimeSpan.TicksPerMinute)); 
     Console.WriteLine(DateTime.Now.Trim(TimeSpan.TicksPerSecond)); 
     Console.ReadLine(); 
    } 

} 
+0

Ich mag das sehr und wenn ich das 3.5-Framework benutze, wäre dies der Weg, den ich nehmen würde, es sei denn, es gibt noch etwas Besseres da draußen. Leider benutze ich 2.0, daher muss ich bei der ersten Antwort bleiben. Vielen Dank! –

+8

Wenn Sie es als allgemeine Erweiterungsmethode verwenden, sollten Sie das DateTimeKind (Unspecified/Utc/Local) beibehalten: return new DateTime (date.Ticks - date.Ticks% roundTicks, date.Kind); – Joe

+0

... oder ein Einzeiler, der auch die Kind-Eigenschaft beibehält: d = d.AddTicks (- (d.Ticks + 30 * TimeSpan.TicksPerSecond)% TimeSpan.TicksPerMinute); – Joe

4

könnten Sie eine Aufzählung

public enum DateTimePrecision 
{ 
    Hour, Minute, Second 
} 

public static DateTime TrimDate(DateTime date, DateTimePrecision precision) 
{ 
    switch (precision) 
    { 
    case DateTimePrecision.Hour: 
     return new DateTime(date.Year, date.Month, date.Day, date.Hour, 0, 0); 
    case DateTimePrecision.Minute: 
     return new DateTime(date.Year, date.Month, date.Day, date.Hour, date.Minute, 0); 
    case DateTimePrecision.Second: 
     return new DateTime(date.Year, date.Month, date.Day, date.Hour, date.Minute, date.Second); 
    default: 
     break; 
    } 
} 

verwenden und nach Bedarf erweitern.

+0

Für Stunden und Minuten frage ich mich, ob Minuten und Sekunden abgerundet werden sollten als 0 zu verwenden? – Vivek

+0

Natürlich könnten Sie den Code eher runden als abschneiden, wenn Sie müssen; oft empfinde ich die Kürzung als natürlicher, da sich die Uhren so verhalten. – Rikalous

-4

Wenn Sie Zeit & Datum als (kontinuierlich) Zahl ähnlich Time_t haben, können Sie einfach Modulo verwenden volle Minuten (% 60), Stunden zu bekommen, und so weiter.

Nach meiner Erfahrung scheinen die Werte mit Echtzeit ausgerichtet zu sein (Modulo 60 tritt in voller Minute auf), aber das ist höchstwahrscheinlich nirgendwo garantiert.

Hier Code zu bekommen, was Sie wollen (mit Sub-Sekunden-Auflösung):

/* 
* Returns millisecond timing (in seconds) for the current time. 
* 
* Note: This function should be called once in single-threaded mode in Win32, 
*  to get it initialized. 
*/ 
double now_secs(void) { 

#if (defined PLATFORM_WIN32) || (defined PLATFORM_POCKETPC) 
    /* 
    * Windows FILETIME values are "100-nanosecond intervals since 
    * January 1, 1601 (UTC)" (MSDN). Well, we'd want Unix Epoch as 
    * the offset and it seems, so would they: 
    * 
    * <http://msdn.microsoft.com/en-us/library/ms724928(VS.85).aspx> 
    */ 
    SYSTEMTIME st; 
    FILETIME ft; 
    ULARGE_INTEGER uli; 
    static ULARGE_INTEGER uli_epoch; // Jan 1st 1970 0:0:0 

    if (uli_epoch.HighPart==0) { 
     st.wYear= 1970; 
     st.wMonth= 1; // Jan 
     st.wDay= 1; 
     st.wHour= st.wMinute= st.wSecond= st.wMilliseconds= 0; 
     // 
     st.wDayOfWeek= 0; // ignored 

     if (!SystemTimeToFileTime(&st, &ft)) 
      FAIL("SystemTimeToFileTime", GetLastError()); 

     uli_epoch.LowPart= ft.dwLowDateTime; 
     uli_epoch.HighPart= ft.dwHighDateTime; 
    } 

    GetSystemTime(&st); // current system date/time in UTC 
    if (!SystemTimeToFileTime(&st, &ft)) 
     FAIL("SystemTimeToFileTime", GetLastError()); 

    uli.LowPart= ft.dwLowDateTime; 
    uli.HighPart= ft.dwHighDateTime; 

    /* 'double' has less accuracy than 64-bit int, but if it were to degrade, 
    * it would do so gracefully. In practise, the integer accuracy is not 
    * of the 100ns class but just 1ms (Windows XP). 
    */ 
    return (double)(uli.QuadPart - uli_epoch.QuadPart)/10000000.0; 
#else 
    struct timeval tv; 
     // { 
     // time_t  tv_sec; /* seconds since Jan. 1, 1970 */ 
     // suseconds_t tv_usec; /* and microseconds */ 
     // }; 

    int rc= gettimeofday(&tv, NULL /*time zone not used any more (in Linux)*/); 
    assert(rc==0); 

    return ((double)tv.tv_sec) + ((tv.tv_usec)/1000)/1000.0; 
#endif 
} 
+3

Schöne C# Sie haben dort ... – leppie

0
static DateTime TrimDate(DateTime date, long roundTicks) 
    { 
     return new DateTime(date.Ticks - date.Ticks % roundTicks); 
    } 

    //sample usage: 
    static void Main(string[] args) 
    { 
     Console.WriteLine(DateTime.Now); 
     Console.WriteLine(TrimDate(DateTime.Now, TimeSpan.TicksPerDay)); 
     Console.WriteLine(TrimDate(DateTime.Now, TimeSpan.TicksPerHour)); 
     Console.WriteLine(TrimDate(DateTime.Now, TimeSpan.TicksPerMillisecond)); 
     Console.WriteLine(TrimDate(DateTime.Now, TimeSpan.TicksPerMinute)); 
     Console.WriteLine(TrimDate(DateTime.Now, TimeSpan.TicksPerSecond)); 
     Console.ReadLine(); 
    } 
+0

Bitte entfernen Sie doppelte Antwort. Ich glaube, eine gute Antwort ist ausreichend. – st78

-2
DateTime dt = new DateTime() 
dt = dt.AddSeconds(-dt.Second) 

Above Code Sekunden trimmen.

+0

Es wird keine Millisekunden trimmen und führt zu einem schlechten 'dt'. – Denis

-1

Ich mag diese Methode. Jemand erwähnte, dass es gut sei, das Date Kind usw. zu erhalten. Dies bewirkt, dass, weil es kein neues Datum erstellt, es einfach die restlichen Ticks subtrahiert.

private DateTime FloorToHour(DateTime dt) 
{ 
    return dt.AddTicks(-1 * (dt.Ticks % TimeSpan.TicksPerHour)); 
} 
1

Es gibt einige gute Lösungen präsentierten, aber wenn ich dies tun müssen, kann ich einfach:

DateTime truncDate; 
truncDate = date.Date; // trim to day 
truncDate = date.Date + TimeSpan.Parse(string.Format("{0:HH:00:00}", date)); // trim to hour 
truncDate = date.Date + TimeSpan.Parse(string.Format("{0:HH:mm}", date)); // trim to minute 
truncDate = date.Date + TimeSpan.Parse(string.Format("{0:HH:mm:ss}", date)); // trim to second 

Hoffe, es hilft.

+0

funktioniert nicht, gibt nur den Tag zurück + 00:00:00 –

+0

@katz: Es tut mir leid, aber ich habe diese Lösung getestet, als ich meine Antwort veröffentlicht habe und ich habe es gerade wieder getestet und es funktioniert einwandfrei. Sind Sie sicher, dass Sie nicht nur die erste Option testen (trimmen auf Tag)? Ich glaube nicht, dass alle oben genannten TimeSpan.Parse-Methodenaufrufe zu Ihnen 00:00:00 zurückkehren.Sind Sie sicher, dass Sie eine andere Variable als die Variable "date" selbst verwenden, um die Ergebnisse dieser Operationen zu erhalten (wie ich in meinem Beispiel "truncDate" verwendet habe)? Wenn Sie die Variable "date" selbst verwenden, wird sie durch die erste oben genannte Operation auf den heutigen Tag gekürzt, wodurch alle nachfolgenden Ergebnisse kompromittiert werden. –

+0

@katz: Verwenden Sie eine andere Variable (wie "truncDate") und machen Sie nicht alle oben genannten Operationen nacheinander und DANN drucken Sie das Ergebnis. Mein Code war nur ein Beispiel, aber JEDE Operation (jede Codezeile) sollte separat verwendet werden, abhängig von der gewünschten Präzision (Tag, Stunde, Minute oder Sekunde). Versuchen Sie zum Beispiel, nur die LETZTE Zeile (trimmen auf Sekunde) auszuführen und drucken Sie dann das Ergebnis. –

Verwandte Themen