web-dev-qa-db-fra.com

Comment tronquer des millisecondes hors d'un DateTime .NET

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 #).

307
Jeff Putz

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
...
519
Joe
var date = DateTime.Now;

date = new DateTime(date.Year, date.Month, date.Day, date.Hour, date.Minute, date.Second, date.Kind);
136
benPearce

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);
    }
}
52
Sky Sanders
DateTime d = DateTime.Now;
d = d.AddMilliseconds(-d.Millisecond);
26
chris.w.mclean

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;
9
Bob

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

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

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...
3
Sergio Cabral

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 .

1
Colonel Panic

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

1
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

1
Dhawal Shukal

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

1
Dhawal Shukal

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;
0
Thinker Bell