1
votes

Comment obtenir le 29 février en utilisant la méthode AddYears en c #

Nous utilisons un travail qui s'exécute tous les jours et effectuons des actions pendant un jour un an à l'avance. En fait, nous utilisons simplement quelque chose comme: DateTime.UtcNow.AddYears (1) . Mais il ne semble pas possible d'obtenir un 29 février (par exemple pour 2020) en utilisant cette technique:

var target = new DateTime(2020, 2, 29);
bool result = (target == target.AddYears(-1).AddYears(1));//false

Est-il donc possible de viser un 29 février dans le futur d'une manière ou d'une autre?

p >


3 commentaires

Essayez-vous par ex. cible "le dernier jour du mois de février"? Si tel est le cas, vous envisagerez probablement une construction manuelle basée sur DaysInMonth mais votre exigence n'est pas vraiment claire dans la question ...


Peut-être utiliser IsLeapYear ( docs. microsoft.com/en-us/dotnet/api/... ) Si la date résultante est le 1er mars -> IsLeapYear == true -> Fixer la date en soustrayant un jour. Je ne suis pas sûr de votre exemple de code car il fait en fait le contraire de l'opération dans votre description.


Ce que vous demandez n'est pas tout à fait clair - si vous effectuez une action pour une date exactement un an à l'avance, comme vous n'avez pas de 29 février de l'année précédant une année bissextile, vous ne vous attendez pas à avoir quoi que ce soit de prévu. pour ce jour. Vous devrez décider du moment où effectuer les actions 1 an après le 29 de l'année bissextile - devrait-il être un jour en avance ou en retard?


5 Réponses :


4
votes

Non. La Documentation déclare:

  • Si value + DateTime.Year est également une année bissextile, la valeur renvoyée représente le jour bissextile de cette année. Par exemple, si quatre ans sont ajoutés au 29 février 2012, la date renvoyée est le 29 février 2016.

  • Si value + DateTime.Year n'est pas une année bissextile, la valeur renvoyée représente la veille du jour bissextile de cette année. Par exemple, si une année est ajoutée au 29 février 2012, la date renvoyée est le 28 février 2013.

Cela signifie que si vous ajoutez une année, vous obtiendrez toujours le 28 février. Le seul moyen d'obtenir le 29e via AddYears est d'ajouter un multiple de 4.


0 commentaires

4
votes

Non, c'est par conception .

Si l'instance actuelle représente le jour bissextile d'une année bissextile, le la valeur de retour dépend de la date cible :

  • Si value + DateTime.Year est également une année bissextile, la valeur de retour représente le jour bissextile de cette année. Par exemple, si quatre ans est ajouté au 29 février 2012, la date renvoyée est le 29 février 2016.

  • Si la valeur + DateTime.Year n'est pas une année bissextile, la valeur de retour représente la veille du jour bissextile de cette année. Par exemple, si un an est ajouté au 29 février 2012, la date renvoyée est février 28, 2013.

1 an après le 29 février 2020 devrait être 28 février 2021 car ce n'est pas une année bissextile. Mais dans un tel cas, toutes les années après 2021 fonctionneront comme un 28 février.

Autre que cela, demandez-vous, quelle est la signification d'une «année» pour vous? Combien de jours dans un mois? Combien de jours par an? Est-ce 365? 366? Ou comme wikipedia l'a déclaré 365.2425? De quel calendrier parlons-nous également?

Les cadres, bibliothèques, etc. ne fonctionnent pas comme les gens le pensent. Ils fonctionnent sur la base d'un ensemble de règles définies auparavant. .NET Framework a défini cette règle comme telle. Ainsi, lorsque vous ajoutez une année à une instance DateTime , ils décident que la partie mois doit rester la même, la partie année changera pendant combien d'années seront ajoutées, et la partie jour doit être une < em> valide un.


4 commentaires

Merci, tu as raison. Au moins pour l'instant, je vais utiliser .AddDays (365) au lieu de AddYears (1) .


Gardez à l'esprit que si vous faites cela, vos sauvegardes ne s'aligneront pas - chaque fois que l'année en cours est une année bissextile et que la date se situe entre février et février de l'année prochaine, vous sauvegarderez parfois, du 1er juin au 31 mai et parfois, vous sauvegarderez le 1er juin le 1er juin, en fonction de la façon dont se déroule le décalage.


@RomanKoliada AddDays (365) n'est pas la même chose que AddYears (1) d'ailleurs. Mais avec cela, vous aurez la garantie de travailler tous les 365 jours. Regardez, TicksPerMillisecond , TicksPerMillisecond , TicksPerDay sont des constantes pour le framework .NET par exemple. Ils ne changent pas en fonction de l'année bissextile ou de toute autre chose. Mais lorsque vous commencez à travailler avec des unités plus grandes comme «mois» ou «année», ces sujets en informatique dépendent de beaucoup de choses. C'est pourquoi ils "doivent" être définis dans un ensemble de règles si vous voulez obtenir des résultats stables lorsque vous les traitez.


@RomanKoliada - AddDays (365) est un anti-pattern. Si vous l'utilisez, que vous commenciez le 29 février ou non, si vous traversez le 29 février, vos résultats seront décalés d'un jour. Par exemple, 2019-10-01 + 365 jours = 2020-09-30 (au lieu du 2020-10- attendu 01 ). Voir mon article de blog de la dernière année bissextile.



-1
votes

Comme NibblyPig l'a déclaré, ce n'est pas possible. Cependant, si vous recherchez simplement la fin du mois, vous pouvez utiliser new DateHeure (année, mois + 1, 0) .AddDays (-1)


2 commentaires

0 est un jour non valide et mois + 1 ne fonctionnera pas en décembre.


Tout à fait juste, je me souviens maintenant d'être tombé dans ces pièges lorsque j'implémentais une méthode d'extension EndOfMonth (). Je pense que j'ai fini par utiliser DateTime.DaysInMonth (année, mois)



0
votes

Vous pouvez tromper un peu le système en prenant "la veille du 1er mars" à la place.

stub:

DateTime today = DateTime.UtcNow
if (today.month == 2)
{
  if(today.day == 28 || today.day == 29)
  {
    today.AddDays(1).AddYears(1).AddDays(-1)
   }
}

cela convertit votre 28 février en non-leapyears au 1er mars, ajoute un an, et va à la veille. Si l'année prochaine n'est pas non plus une année bissextile, vous obtiendrez toujours le 28 février, mais si l'année prochaine est une année bissextile, le résultat sera le 29 février.

cela ne résout pas encore la situation de cette année est un leapyear, car ce code reviendra alors le 27 février à la place


0 commentaires

0
votes

Fonction qui retourne le 29. fév. Peut-être que ça aide. en utilisant System;

public class Program
{
    public static DateTime NextTwentyNineFeb()
    {
        int year = DateTime.Now.Year;
        while(true){            
            try{
                var target = new DateTime(year, 2, 29);
                Console.WriteLine(target);
                return target;
            }
            catch
            {
                year++;
            }
        }
    }
}


0 commentaires