61 votes

Existe-t-il un meilleur moyen de découper un DateTime à une précision spécifique ?

Quelle est la meilleure façon de découper un objet DateTime à une précision spécifique ? Par exemple, si j'ai un objet DateTime dont la valeur est '2008-09-29 09:41:43', mais que je veux que sa précision soit à la minute près, y a-t-il un meilleur moyen de le faire que celui-ci ?

private static DateTime TrimDateToMinute(DateTime date)
{
    return new DateTime(
        date.Year, 
        date.Month, 
        date.Day, 
        date.Hour, 
        date.Minute, 
        0);
}

Ce que je voudrais vraiment, c'est qu'il soit variable afin de pouvoir régler sa précision sur la seconde, la minute, l'heure ou le jour.

109voto

Bartek Szabat Points 1611
static class Program
{
    //using extension method:
    static DateTime Trim(this DateTime date, long roundTicks)
    {
        return new DateTime(date.Ticks - date.Ticks % roundTicks, date.Kind);
    }

    //sample usage:
    static void Main(string[] args)
    {
        Console.WriteLine(DateTime.Now);
        Console.WriteLine(DateTime.Now.Trim(TimeSpan.TicksPerDay));
        Console.WriteLine(DateTime.Now.Trim(TimeSpan.TicksPerHour));
        Console.WriteLine(DateTime.Now.Trim(TimeSpan.TicksPerMillisecond));
        Console.WriteLine(DateTime.Now.Trim(TimeSpan.TicksPerMinute));
        Console.WriteLine(DateTime.Now.Trim(TimeSpan.TicksPerSecond));
        Console.ReadLine();
    }

}

0 votes

J'aime beaucoup cette solution et si j'utilisais le framework 3.5, c'est la voie que je suivrais, à moins qu'il n'existe quelque chose de mieux. Malheureusement, j'utilise la version 2.0 et je vais donc devoir m'en tenir à votre première réponse. Merci.

16 votes

Si vous en faites une méthode d'extension à usage général, il est utile de conserver le DateTimeKind (Unspecified/Utc/Local) : return new DateTime(date.Ticks - date.Ticks % roundTicks, date.Kind) ;

0 votes

... ou une ligne simple qui préserve également la propriété Kind : d = d.AddTicks(-(d.Ticks + 30*TimeSpan.TicksPerSecond) % TimeSpan.TicksPerMinute) ;

9voto

Rikalous Points 2996

Vous pourriez utiliser une énumération

public enum DateTimePrecision
{
  Hour, Minute, Second
}

public static DateTime TrimDate(DateTime date, DateTimePrecision precision)
{
  switch (precision)
  {
    case DateTimePrecision.Hour:
      return new DateTime(date.Year, date.Month, date.Day, date.Hour, 0, 0);
    case DateTimePrecision.Minute:
      return new DateTime(date.Year, date.Month, date.Day, date.Hour, date.Minute, 0);
    case DateTimePrecision.Second:
      return new DateTime(date.Year, date.Month, date.Day, date.Hour, date.Minute, date.Second);
    default:
      break;
  }
}

et l'étendre si nécessaire.

0 votes

Pour les heures et les minutes, je me demande si les minutes et les secondes doivent être arrondies plutôt que d'utiliser 0 ?

1 votes

Vous pouvez certainement adapter le code pour arrondir plutôt que tronquer si vous en avez besoin ; souvent, je trouve que la troncature semble plus naturelle car c'est effectivement la façon dont les horloges se comportent.

0 votes

Lorsque vous n'en avez besoin qu'une seule fois - return new DateTime(dt.Year, 1, 1)

7voto

rocketsarefast Points 1167

J'aime cette méthode. Quelqu'un a mentionné qu'il était bon de préserver le Date Kind, etc. Cette méthode permet d'y parvenir car il n'est pas nécessaire de créer un nouveau DateTime. L'heure de la date est correctement clonée à partir de l'heure de la date d'origine et il suffit de soustraire les ticks restants.

public static DateTime FloorTime(DateTime dt, TimeSpan interval) 
{
  return dt.AddTicks(-1 * (dt.Ticks % interval.Ticks));
}

l'usage :

dt = FloorTime(dt, TimeSpan.FromMinutes(5)); // floor to the nearest 5min interval
dt = FloorTime(dt, TimeSpan.FromSeconds(1)); // floor to the nearest second
dt = FloorTime(dt, TimeSpan.FromDays(1));    // floor to the nearest day

0 votes

Le format DateTime étant une structure (type de valeur), toute manipulation créera une nouvelle valeur, même si elle ne la présente pas ainsi. stackoverflow.com/a/1859266/955444

0 votes

C'est vrai, mais il est correctement cloné par le code DateTime, donc le fuseau horaire est effectivement préservé. Je vais légèrement reformuler ma réponse pour être plus clair. Merci.

-1voto

Bartek Szabat Points 1611
    static DateTime TrimDate(DateTime date, long roundTicks)
    {
        return new DateTime(date.Ticks - date.Ticks % roundTicks);
    }

    //sample usage:
    static void Main(string[] args)
    {
        Console.WriteLine(DateTime.Now);
        Console.WriteLine(TrimDate(DateTime.Now, TimeSpan.TicksPerDay));
        Console.WriteLine(TrimDate(DateTime.Now, TimeSpan.TicksPerHour));
        Console.WriteLine(TrimDate(DateTime.Now, TimeSpan.TicksPerMillisecond));
        Console.WriteLine(TrimDate(DateTime.Now, TimeSpan.TicksPerMinute));
        Console.WriteLine(TrimDate(DateTime.Now, TimeSpan.TicksPerSecond));
        Console.ReadLine();
    }

6 votes

Veuillez supprimer la réponse en double. Je pense qu'une seule bonne réponse est suffisante

-2voto

Gunarathinam Points 148
DateTime dt = new DateTime()
dt = dt.AddSeconds(-dt.Second)

Le code ci-dessus coupe les secondes.

0 votes

Cela ne réduira pas les millisecondes et entraînera de mauvais résultats. dt .

0 votes

Ajoutez simplement .AddMillisceconds() aussi alors. Cette réponse est supérieure aux autres à mon avis, puisqu'elle est beaucoup moins lourde. Mais je vous prie de me corriger.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X