J'essaie de comparer un horodatage d'une demande entrante à une valeur stockée dans la base de données. Bien sûr, SQL Server conserve une précision de millisecondes sur l'heure et, lorsqu'il est lu dans un DateTime .NET, il inclut ces millisecondes. La demande entrante dans le système, cependant, n'offre pas cette précision. Je dois donc simplement laisser tomber les millisecondes.
J'ai l'impression qu'il me manque 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 une fraction de millisecondes 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
if (dateTime == DateTime.MinValue || dateTime == DateTime.MaxValue) return dateTime; // do not modify "guard" values
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 ...
tilisation:
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;
Parfois, vous voulez tronquer à quelque chose de 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);
Facile...
//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...
Arrondir à la seconde:
dateTime.AddTicks(-dateTime.Ticks % TimeSpan.TicksPerSecond)
Remplacez par TicksPerMinute
pour arrondir à la minute.
Si votre code est sensible aux performances, soyez prudent avec
new DateTime(date.Year, date.Month, date.Day, date.Hour, date.Minute, date.Second)
Mon application passait 12% du temps CPU en System.DateTime.GetDatePart .
Concernant la réponse de 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 me serais attendu à ce que la division de deux valeurs Long donne un Long, supprimant ainsi la partie décimale, mais le résout comme un Double laissant la même valeur exacte après la multiplication.
Eppsy
Nouvelle méthode
String Date = DateTime.Today.ToString("dd-MMM-yyyy");
// définir le paramètre de passage de chaîne jj-mmm-aaaa return 24-fev-2016
Ou affiché dans la zone de texte
txtDate.Text = DateTime.Today.ToString("dd-MMM-yyyy");
// mettre sur PageonLoad
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.ToShortDateString();
Use ToShortDateString() //Date 2-02-2016
Use ToShortDateString() // Time
Et par utilisation de
ToLongDateString() // its show 19 February 2016.
: P
Dans mon cas, je visais à sauver TimeSpan de l'outil datetimePicker sans sauvegarder les secondes et les millisecondes, et voici la solution.
Commencez par convertir le fichier datetimePicker.value au format souhaité, le mien étant "HH: mm", puis reconvertissez-le en TimeSpan.
var datetime = datetimepicker1.Value.ToString("HH:mm");
TimeSpan timeSpan = Convert.ToDateTime(datetime).TimeOfDay;