Comment tronquer les millisecondes d’un .NET DateTime

J’essaie de comparer un horodatage d’une demande entrante à une valeur stockée dans une firebase database. SQL Server garde bien sûr une précision de quelques millisecondes sur le temps et, lorsqu’il est lu dans un .NET DateTime, il inclut ces millisecondes. La demande entrante sur le système n’offre cependant pas cette précision, alors je dois simplement supprimer les millisecondes.

J’ai l’impression de manquer quelque chose d’évident, mais je n’ai pas trouvé de moyen élégant de le faire (C #).

Ce qui suit fonctionnera pour un DateTime qui a des millisecondes fractionnaires et préserve également la propriété Kind (Local, Utc ou Undefined).

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

ou l’équivalent et plus court:

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

Cela pourrait être généralisé dans une méthode d’extension:

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

qui est utilisé comme suit:

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

Voici une méthode d’extension basée sur une réponse précédente qui vous permettra de tronquer toute résolution …

Usage:

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

Classe:

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

Au lieu de baisser les millisecondes puis de comparer, pourquoi ne pas comparer la différence?

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

ou

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

Parfois, vous voulez tronquer quelque chose en fonction du calendrier, comme l’année ou le mois. Voici une méthode d’extension qui vous permet de choisir n’importe quelle résolution.

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

Moins évident mais plus de 2 fois plus rapide:

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

Simple…

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

Et plus…

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

En ce qui concerne la réponse Diadistis. Cela a fonctionné pour moi, sauf que j’ai dû utiliser Floor pour supprimer la partie fractionnaire de la division avant la multiplication. Alors,

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

devient

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

Je m’attendrais à ce que la division de deux valeurs longues aboutisse à un long, supprimant ainsi la partie décimale, mais elle le résout sous la forme d’un double laissant exactement la même valeur après la multiplication.

Eppsy

2 méthodes d’extension pour les solutions mentionnées ci-dessus

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

usage:

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

Et par l’utilisation de

 ToLongDateSsortingng() // its show 19 February 2016. 

: P

Nouvelle méthode

 Ssortingng Date = DateTime.Today.ToSsortingng("dd-MMM-yyyy"); 

// définit le paramètre de passe-chaîne jj-mmm-aaaa retour 24 février 2016

Ou montré sur le textbox

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

// mettre sur PageonLoad

Pour arrondir au second:

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

Remplacez par TicksPerMinute pour arrondir à la minute.


Si votre code est sensible aux performances, soyez prudent

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

Mon application passait 12% du temps CPU dans System.DateTime.GetDatePart .