Cómo truncar milisegundos fuera de un .NET DateTime

Estoy tratando de comparar una marca de tiempo de una solicitud entrante a un valor almacenado de la base de datos. SQL Server por supuesto mantiene una precisión de milisegundos en el tiempo, y cuando se lee en .NET DateTime, incluye esos milisegundos. La solicitud entrante al sistema, sin embargo, no ofrece esa precisión, por lo que simplemente tengo que soltar los milisegundos.

Siento que me falta algo obvio, pero no he encontrado una forma elegante de hacerlo (C #).

Lo siguiente funcionará para un DateTime que tiene milisegundos fraccionarios, y también conserva la propiedad Kind (Local, Utc o Undefined).

DateTime dateTime = ... anything ... dateTime = new DateTime( dateTime.Ticks - (dateTime.Ticks % TimeSpan.TicksPerSecond), dateTime.Kind ); 

o el equivalente y más corto:

 dateTime = dateTime.AddTicks( - (dateTime.Ticks % TimeSpan.TicksPerSecond)); 

Esto podría generalizarse en un método de extensión:

 public static DateTime Truncate(this DateTime dateTime, TimeSpan timeSpan) { if (timeSpan == TimeSpan.Zero) return dateTime; // Or could throw an ArgumentException return dateTime.AddTicks(-(dateTime.Ticks % timeSpan.Ticks)); } 

que se usa de la siguiente manera:

 dateTime = dateTime.Truncate(TimeSpan.FromMilliseconds(1)); // Truncate to whole ms dateTime = dateTime.Truncate(TimeSpan.FromSeconds(1)); // Truncate to whole second dateTime = dateTime.Truncate(TimeSpan.FromMinutes(1)); // Truncate to whole minute ... 
 var date = DateTime.Now; date = new DateTime(date.Year, date.Month, date.Day, date.Hour, date.Minute, date.Second, date.Kind); 

Aquí hay un método de extensión basado en una respuesta previa que le permitirá truncar a cualquier resolución …

Uso:

 DateTime myDateSansMilliseconds = myDate.Truncate(TimeSpan.TicksPerSecond); DateTime myDateSansSeconds = myDate.Truncate(TimeSpan.TicksPerMinute) 

Clase:

 public static class DateTimeUtils { ///  /// Truncates a DateTime to a specified resolution. /// A convenient source for resolution is TimeSpan.TicksPerXXXX constants. ///  /// The DateTime object to truncate /// eg to round to nearest second, TimeSpan.TicksPerSecond /// Truncated DateTime public static DateTime Truncate(this DateTime date, long resolution) { return new DateTime(date.Ticks - (date.Ticks % resolution), date.Kind); } } 
 DateTime d = DateTime.Now; d = d.AddMilliseconds(-d.Millisecond); 

En lugar de dejar caer los milisegundos, comparando, ¿por qué no comparar la diferencia?

 DateTime x; DateTime y; bool areEqual = (xy).TotalSeconds == 0; 

o

 TimeSpan precision = TimeSpan.FromSeconds(1); bool areEqual = (xy).Duration() < precision; 

A veces, quiere truncar a algo basado en el calendario, como el año o el mes. Aquí hay un método de extensión que le permite elegir cualquier resolución.

 public enum DateTimeResolution { Year, Month, Day, Hour, Minute, Second, Millisecond, Tick } public static DateTime Truncate(this DateTime self, DateTimeResolution resolution = DateTimeResolution.Second) { switch (resolution) { case DateTimeResolution.Year: return new DateTime(self.Year, 1, 1, 0, 0, 0, 0, self.Kind); case DateTimeResolution.Month: return new DateTime(self.Year, self.Month, 1, 0, 0, 0, self.Kind); case DateTimeResolution.Day: return new DateTime(self.Year, self.Month, self.Day, 0, 0, 0, self.Kind); case DateTimeResolution.Hour: return self.AddTicks(-(self.Ticks % TimeSpan.TicksPerHour)); case DateTimeResolution.Minute: return self.AddTicks(-(self.Ticks % TimeSpan.TicksPerMinute)); case DateTimeResolution.Second: return self.AddTicks(-(self.Ticks % TimeSpan.TicksPerSecond)); case DateTimeResolution.Millisecond: return self.AddTicks(-(self.Ticks % TimeSpan.TicksPerMillisecond)); case DateTimeResolution.Tick: return self.AddTicks(0); default: throw new ArgumentException("unrecognized resolution", "resolution"); } } 

Menos obvio pero más de 2 veces más rápido:

 // 10000000 runs DateTime d = DateTime.Now; // 484,375ms d = new DateTime((d.Ticks / TimeSpan.TicksPerSecond) * TimeSpan.TicksPerSecond); // 1296,875ms d = d.AddMilliseconds(-d.Millisecond); 

Sencillo…

 //Remove milliseconds DateTime date = DateTime.Now; date = DateTime.ParseExact(date.ToString("yyyy-MM-dd HH:mm:ss"), "yyyy-MM-dd HH:mm:ss", null); 

Y más…

 //Remove seconds DateTime date = DateTime.Now; date = DateTime.ParseExact(date.ToString("yyyy-MM-dd HH:mm"), "yyyy-MM-dd HH:mm", null); //Remove minutes DateTime date = DateTime.Now; date = DateTime.ParseExact(date.ToString("yyyy-MM-dd HH"), "yyyy-MM-dd HH", null); //and go on... 

Respecto a la respuesta de Diadistis. Esto funcionó para mí, excepto que tuve que usar Floor para eliminar la parte fraccional de la división antes de la multiplicación. Asi que,

 d = new DateTime((d.Ticks / TimeSpan.TicksPerSecond) * TimeSpan.TicksPerSecond); 

se convierte

 d = new DateTime(Math.Floor(d.Ticks / TimeSpan.TicksPerSecond) * TimeSpan.TicksPerSecond); 

Hubiera esperado que la división de dos valores Long resultara en un Largo, eliminando así la parte decimal, pero la resuelve como un Doble dejando exactamente el mismo valor después de la multiplicación.

Epita

2 Métodos de extensión para las soluciones mencionadas anteriormente

  public static bool LiesAfterIgnoringMilliseconds(this DateTime theDate, DateTime compareDate, DateTimeKind kind) { DateTime thisDate = new DateTime(theDate.Year, theDate.Month, theDate.Day, theDate.Hour, theDate.Minute, theDate.Second, kind); compareDate = new DateTime(compareDate.Year, compareDate.Month, compareDate.Day, compareDate.Hour, compareDate.Minute, compareDate.Second, kind); return thisDate > compareDate; } public static bool LiesAfterOrEqualsIgnoringMilliseconds(this DateTime theDate, DateTime compareDate, DateTimeKind kind) { DateTime thisDate = new DateTime(theDate.Year, theDate.Month, theDate.Day, theDate.Hour, theDate.Minute, theDate.Second, kind); compareDate = new DateTime(compareDate.Year, compareDate.Month, compareDate.Day, compareDate.Hour, compareDate.Minute, compareDate.Second, kind); return thisDate >= compareDate; } 

uso:

 bool liesAfter = myObject.DateProperty.LiesAfterOrEqualsIgnoringMilliseconds(startDateTime, DateTimeKind.Utc); 
 DateID.Text = DateTime.Today.ToShortDateString(); Use ToShortDateString() //Date 2-02-2016 Use ToShortDateString() // Time 

Y por uso de

 ToLongDateString() // its show 19 February 2016. 

:PAG

Nuevo método

 String Date = DateTime.Today.ToString("dd-MMM-yyyy"); 

// define el parámetro String pass dd-mmm-yyyy return 24-feb-2016

O se muestra en el cuadro de texto

 txtDate.Text = DateTime.Today.ToString("dd-MMM-yyyy"); 

// poner en PageonLoad

Para redondear al segundo:

 dateTime.AddTicks(-dateTime.Ticks % TimeSpan.TicksPerSecond) 

Reemplace con TicksPerMinute para redondear al minuto.


Si su código es sensible al rendimiento, tenga cuidado con

 new DateTime(date.Year, date.Month, date.Day, date.Hour, date.Minute, date.Second) 

Mi aplicación estaba gastando el 12% del tiempo de CPU en System.DateTime.GetDatePart .