2008-09-30 4 views
38

Каков наилучший способ обрезать объект DateTime с определенной точностью? Например, если у меня есть DateTime со значением '2008-09-29 09:41:43', но я хочу только, чтобы точность была на минуту, есть ли лучший способ сделать это, чем это?Есть ли лучший способ обрезать DateTime с определенной точностью?

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

То, что я действительно хочу, чтобы сделать его переменной так, чтобы я мог установить свою точность в секунду, минуту, час или день.

ответ

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

Мне это очень нравится, и если бы я использовал фреймворк 3.5, это маршрут, который я бы взял, если там еще ничего лучше. К сожалению, я использую 2.0, поэтому мне придется придерживаться вашего первого ответа. Благодаря! – 2008-09-30 13:48:39

+8

Если вы используете универсальный метод расширения, стоит сохранить DateTimeKind (Unspecified/Utc/Local): return new DateTime (date.Ticks - date.Ticks% roundTicks, date.Kind); – Joe 2008-10-03 11:12:29

4

Вы можете использовать перечисление

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

и расширяться по мере необходимости.

+0

В течение часа и минуты мне интересно, нужно ли округлить минуты и секунды, чем использовать 0? – Vivek 2008-09-30 13:33:07

+0

Конечно, вы могли бы адаптировать код к раунду, а не усекать, если вам нужно; часто я считаю, что усечение кажется более естественным, поскольку это эффективно, как ведут себя часы. – Rikalous 2008-09-30 14:38:15

-4

Если у вас есть время & дату в виде (непрерывные) чисел сродни time_t, вы можете просто использовать по модулю, чтобы получить полные минуты (% 60), часы и так далее.

По моему опыту, значения, похоже, выровнены с реальным временем (по модулю 60 происходит в полную минуту), но это, скорее всего, не гарантируется нигде.

Вот код, чтобы получить то, что вы хотите (с суб-второй резолюции):

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

Lovely C# у вас там есть ... – leppie 2008-09-30 13:10:35

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

Удалите повторяющийся ответ. Я считаю, что один большой ответ достаточно. – st78 2017-08-01 09:35:46

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

Приведенный выше код будет подрезки секунд.

-1

Мне нравится этот способ. Кто-то упомянул, что было хорошо сохранить вид даты и т. Д. Это достигается тем, что, поскольку он не делает новую дату, он просто вычитает оставшиеся тики.

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

Есть некоторые хорошие решения, представленные здесь, но когда мне нужно сделать это, я просто сделать:

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 

Надеется, что это помогает.

Смежные вопросы