Comment tronquer des millisecondes de a.NET DateTime
j'essaie de comparer un horodatage d'une requête entrante à une valeur stockée dans une base de données. SQL Server garde bien sûr une précision de millisecondes sur le temps, et lorsqu'il est lu dans un .net DateTime, il inclut ces millisecondes. La requête entrante au système, cependant, n'offre pas cette précision, donc je dois simplement laisser tomber les millisecondes.
j'ai l'impression de rater quelque chose d'évident, mais je n'ai pas trouvé une manière élégante de le faire (C#).
13 réponses
ce qui suit fonctionnera pour une DateTime qui a une fraction de millisecondes, et préserve également la propriété Kind (Local, Utc ou non défini).
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é en 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 à n'importe quelle résolution...
Utilisation:
DateTime myDateSansMilliseconds = myDate.Truncate(TimeSpan.TicksPerSecond);
DateTime myDateSansSeconds = myDate.Truncate(TimeSpan.TicksPerMinute)
Classe:
public static class DateTimeUtils
{
/// <summary>
/// <para>Truncates a DateTime to a specified resolution.</para>
/// <para>A convenient source for resolution is TimeSpan.TicksPerXXXX constants.</para>
/// </summary>
/// <param name="date">The DateTime object to truncate</param>
/// <param name="resolution">e.g. to round to nearest second, TimeSpan.TicksPerSecond</param>
/// <returns>Truncated DateTime</returns>
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 laisser tomber les millisecondes puis de comparer, pourquoi ne pas comparer la différence?
DateTime x; DateTime y;
bool areEqual = (x-y).TotalSeconds == 0;
ou
TimeSpan precision = TimeSpan.FromSeconds(1);
bool areEqual = (x-y).Duration() < precision;
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);
parfois vous voulez tronquer à quelque chose de calendrier basé, 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");
}
}
Simple...
//Remove milliseconds
DateTime date = DateTime.Now;
date = DateTime.ParseExact(date.ToString("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.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...
concernant la réponse de Diadistis. Cela a fonctionné pour moi, sauf que j'ai dû utiliser le plancher pour enlever la partie fractionnaire de la division avant la multiplication. So,
d = new DateTime((d.Ticks / TimeSpan.TicksPerSecond) * TimeSpan.TicksPerSecond);
devient
d = new DateTime(Math.Floor(d.Ticks / TimeSpan.TicksPerSecond) * TimeSpan.TicksPerSecond);
Je m'attendais à ce que la division de deux valeurs longues aboutisse à une longue, supprimant ainsi la partie décimale, mais elle se résout comme un Double laissant la même valeur exacte 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;
}
utilisation:
bool liesAfter = myObject.DateProperty.LiesAfterOrEqualsIgnoringMilliseconds(startDateTime, DateTimeKind.Utc);
DateID.Text = DateTime.Today.ToShortDateString();
Use ToShortDateString() //Date 2-02-2016
Use ToShortDateString() // Time
Et Par Utilisation De
ToLongDateString() // its show 19 February 2016.
: P
Nouvelle Méthode
String Date = DateTime.Today.ToString("dd-MMM-yyyy");
// définition de la Chaîne de passer le paramètre jj-mmm-aaaa retour 24-feb-2016
ou indiqué sur la boîte de texte
txtDate.Text = DateTime.Today.ToString("dd-MMM-yyyy");
// mettre sur PageonLoad
d'arrondir À la baisse pour la deuxième:
dateTime.AddTicks(-dateTime.Ticks % TimeSpan.TicksPerSecond)
remplacer par TicksPerMinute
pour arrondir à la minute.
si votre code est sensible aux performances, soyez prudent à propos de
new DateTime(date.Year, date.Month, date.Day, date.Hour, date.Minute, date.Second)
mon application passait 12% du temps CPU dans le système .DateTime.GetDatePart .