2008-09-30 17 views
38

Bir DateTime nesnesini belirli bir hassasiyetle kesmenin en iyi yolu nedir? Mesela, '2008-09-29 09:41:43' değerine sahip bir DateTime'ım varsa, ama sadece dakikanın hassas olmasını istiyorum, bundan daha iyi bir yol var mı?Bir DateTime'ı belirli bir hassasiyete göre düzeltmenin daha iyi bir yolu var mı?

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

İstediğim gerçekten istiyorum ben ikinci, dakika, saat veya gün onun hassas ayarlanmış böylece değişken yapmaktır.

cevap

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

Bunu çok beğendim ve eğer 3.5 çerçevesini kullanıyor olsaydım, hala daha iyi bir şey olmadıkça bu benim alacağım rota. Maalesef, 2.0 kullanıyorum, böylece ilk cevabınıza bağlı kalmalıyım. Teşekkürler! –

+8

Genel amaçlı bir uzantı yöntemi yapıyorsanız, DateTimeKind (Belirtilmemiş/Utc/Yerel): yeni DateTime (date.Ticks - date.Ticks% roundTicks, date.Kind) döndürmeye değer; – Joe

+0

... veya Kind özelliğini koruyan bir tek liner: d = d.AddTicks (- (d.Ticks + 30 * TimeSpan.TicksPerSecond)% TimeSpan.TicksPerMinute); – Joe

4

Bir numaralandırma kalıbına

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

kullanmak ve gerektiğinde genişletebilecek.

+0

Saat ve Dakika için, Dakikalar ve Saniyelerin 0'dan daha mı yuvarlanması gerektiğini merak ediyorum. – Vivek

+0

Tabii ki, kodun ihtiyaç duyduğunuzda kesmeden ziyade yuvarlakya uyarlayabilirsiniz; genellikle kesmenin, saatlerin nasıl davrandığını daha etkili olduğu için daha doğal hisseder. – Rikalous

-4

Eğer seferinde time_t benzer bir (sürekli) sayı olarak & tarihi varsa, basitçe böyle devam tam dakika (% 60), saat, ve almak için modülo kullanabilirsiniz.

Deneyimlerimde, değerler gerçek zamanlı olarak hizalanmış gibi görünüyor (modulo 60 tam dakikada gerçekleşiyor), ancak bu büyük olasılıkla her yerde garanti edilmiyor. Saniye kırpmak olacaktır kod Üstü

/* 
* 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

Güzel C# orada var ... – 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

Lütfen kopyayı kaldırın. Büyük bir cevabın yeterli olduğuna inanıyorum – st78

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

: Burada

istediğini elde etmek kodu (alt ikinci çözünürlükte) 'dir.

+0

Milisaniye kesmeyecek ve kötü 'dt' ile sonuçlanacaktır. – Denis

-1

Bu yöntemi sevdim. Birisi Tarih Türünü korumak için iyi olduğunu belirtti. Bu, yeni bir tarih yapmadığı için, geriye kalan keneleri çıkardığını başarır.

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

Burada sunulan bazı iyi çözümler vardır, ama bunu gerektiğinde, ben sadece yapın:

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 

yardımcı olur Umut.

+0

çalışmıyor, sadece gün + 00:00:00 döndürür –

+0

@katz: Üzgünüm, ama cevabımı yayınladığımda bu çözümü test ettim ve tekrar test ettim ve gayet iyi çalışıyor. Yukarıdaki sadece ilk seçeneği test etmediğinizden emin misiniz (güne göre)? Yukarıdaki tüm TimeSpan.Parse yönteminin yukarıdaki çağrılara 00:00:00 döndüğüne inanmıyorum.Bu işlemlerin sonuçlarını almak için (örnekte "truncDate" kullandığım gibi) FARKLI bir değişken ("tarih" değişkeninin dışında) kullandığınızdan emin misiniz? "Tarih" değişkeninin kendisini kullanırsanız, yukarıdaki ilk işlem, aşağıdaki diğer tüm sonuçlardan ödün vererek bunu güne kadar keser. –

+0

@katz: FARKLI bir değişken kullanın ("truncDate" gibi) ve yukarıdaki işlemleri TÜMÜNÜ yapmayın ve SONRA yazdırın. Kodum sadece bir örnekti, ancak HER işle (her kod satırı), istediğiniz hassasiyete (gün, saat, dakika veya saniye) bağlı olarak ayrı olarak kullanılmalıdır. Örneğin, sadece LAST satırını (ikincisini kes) çalıştırmayı deneyin ve sonucu yazdırın. –

İlgili konular