En C # /. NET TimeSpan
a TotalDays
, TotalMinutes
etc. mais je ne peux pas trouver de formule pour la différence totale des mois. Les jours variables par mois et les années bissextiles ne cessent de me déranger. Comment puis-je obtenir TotalMonths ?
Modifier Désolé de ne pas être plus clair: je sais que je ne peux pas vraiment obtenir cela, TimeSpan
mais j'ai pensé TotalDays
que ce TotalMinutes
serait un bon exemple pour exprimer ce que je cherchais ... sauf que j'essaie d'obtenir le nombre total de mois.
Exemple: 25 décembre 2009 - 6 octobre 2009 = 2 mois au total. Du 6 octobre au 5 novembre équivaut à 0 mois. Le 6 novembre, 1 mois. Le 6 décembre, 2 mois
Réponses:
Vous ne pourrez pas obtenir cela à partir de a
TimeSpan
, car un «mois» est une unité de mesure variable. Vous devrez le calculer vous-même et vous devrez déterminer exactement comment vous voulez que cela fonctionne.Par exemple, les dates devraient-elles aimer
July 5, 2009
etAugust 4, 2009
donner un mois ou zéro mois de différence? Si vous dites qu'il devrait en donner un, qu'en est-ilJuly 31, 2009
etAugust 1, 2009
? Est- ce un mois? S'agit-il simplement de la différence desMonth
valeurs des dates ou est-ce davantage lié à une période réelle? La logique pour déterminer toutes ces règles n'est pas triviale, vous devrez donc déterminer la vôtre et implémenter l'algorithme approprié.Si tout ce que vous voulez est simplement une différence dans les mois - sans tenir compte des valeurs de date - alors vous pouvez utiliser ceci:
Notez que cela renvoie une différence relative, ce qui signifie que si
rValue
est supérieur àlValue
, la valeur de retour sera négative. Si vous voulez une différence absolue, vous pouvez utiliser ceci:la source
(Je me rends compte que c'est une vieille question, mais ...)
C'est relativement pénible à faire en .NET pur. Je recommanderais ma propre bibliothèque Noda Time , qui est particulièrement conçue pour des choses comme celle-ci:
(Il existe d'autres options, par exemple, si vous ne voulez qu'un nombre de mois, même sur plusieurs années, vous utiliseriez
Period period = Period.Between(start, end, PeriodUnits.Months);
)la source
Period.Between
. J'ai édité le code pour qu'il fonctionne avec NodaTime 1.3.1.Peut-être que vous ne voulez pas connaître les fractions mensuelles; Et ce code?
la source
Vous devrez définir ce que vous entendez par TotalMonths pour commencer.
Une définition simple met un mois à 30,4 jours (365,25 / 12).
Au-delà de cela, toute définition incluant des fractions semble inutile, et la valeur entière plus courante (mois entiers entre les dates) dépend également de règles métier non standard.
la source
J'ai écrit une méthode d'extension très simple
DateTime
etDateTimeOffset
pour ce faire. Je voulais que cela fonctionne exactement comme uneTotalMonths
propriété sur laquelleTimeSpan
fonctionnerait: c'est-à-dire retourner le nombre de mois complets entre deux dates, en ignorant les mois partiels. Parce qu'elle est basée surDateTime.AddMonths()
elle respecte différentes longueurs de mois et renvoie ce qu'un humain comprendrait comme une période de mois.(Malheureusement, vous ne pouvez pas l'implémenter en tant que méthode d'extension sur TimeSpan car cela ne conserve pas la connaissance des dates réelles utilisées, et pendant des mois, elles sont importantes.)
Le code et les tests sont tous deux disponibles sur GitHub . Le code est très simple:
Et il réussit tous ces cas de test unitaires:
la source
Vous devez le résoudre vous-même en dehors des datetimes. La façon dont vous gérez les jours de bout à la fin dépendra de l'utilisation que vous en faites.
Une méthode serait de compter le mois, puis de corriger les jours à la fin. Quelque chose comme:
la source
Je le ferais comme ceci:
la source
return (dtOther.Month - dtThis.Month) + 12 * (dtOther.Year - dtThis.Year);
Il n'y a pas beaucoup de réponses claires à ce sujet parce que vous assumez toujours les choses.
Cette solution calcule entre deux dates les mois entre la supposition que vous souhaitez enregistrer le jour du mois à des fins de comparaison, (ce qui signifie que le jour du mois est pris en compte dans le calcul)
Par exemple, si vous avez une date du 30 janvier 2012, le 29 février 2012 ne sera pas un mois mais le 1er mars 2013 le sera.
Il a été testé assez minutieusement, il sera probablement nettoyé plus tard au fur et à mesure que nous l'utilisons, et prend deux dates au lieu d'un Timespan, ce qui est probablement mieux. J'espère que cela aide quelqu'un d'autre.
la source
La réponse acceptée fonctionne parfaitement lorsque vous voulez des mois complets.
J'avais besoin de mois partiels. Voici la solution que j'ai proposée pendant des mois partiels:
J'avais aussi besoin d'une différence d'année avec le même besoin d'années partielles. Voici la solution que j'ai trouvée:
la source
YearDifference
fonction quandlValue.Month < rValue.Month
- j'ai corrigé cela maintenant, vous voudrez peut-être revoir ...Ancienne question que je connais, mais pourrait aider quelqu'un. J'ai utilisé la réponse acceptée par @Adam ci-dessus, mais j'ai ensuite vérifié si la différence était de 1 ou -1, puis vérifiez s'il s'agit de la différence d'un mois civil complet. Ainsi, le 21/07/55 et le 20/08/55 ne seraient pas un mois complet, mais le 21/07/55 et le 21/07/55 le seraient.
la source
la source
Le problème avec les mois est que ce n'est pas vraiment une mesure simple - ils ne sont pas de taille constante. Vous devrez définir vos règles pour ce que vous voulez inclure et travailler à partir de là. Par exemple, du 1er janvier au 1er février - vous pourriez dire que 2 mois sont impliqués là-bas, ou vous pourriez dire que c'est un mois. Alors que dire du «1er janvier 20h00» au «1er février 00h00» - ce n'est pas tout à fait un mois complet. Est-ce 0? 1? qu'en est-il de l'inverse (du 1er janvier 00h00 au 1er février 20h00) ... 1? 2?
Définissez d'abord les règles, puis vous devrez le coder vous-même, j'en ai bien peur ...
la source
Si vous voulez avoir un résultat
1
entre28th Feb
et1st March
:la source
Cette bibliothèque calcule la différence de mois, en tenant compte de toutes les parties de DateTime:
la source
Voici en fait la façon la plus précise de le faire, car la définition de «1 mois» change en fonction du mois, et aucune des autres réponses n'en tient compte! Si vous voulez plus d'informations sur le problème qui n'est pas intégré au framework, vous pouvez lire cet article: Un objet Real Timespan avec .Years & .Months (cependant, la lecture de cet article n'est pas nécessaire pour comprendre et utiliser la fonction ci-dessous, cela fonctionne à 100%, sans les inexactitudes inhérentes à l'approximation que les autres aiment utiliser - et n'hésitez pas à remplacer la fonction .ReverseIt par la fonction .Reverse intégrée que vous pouvez avoir sur votre framework (c'est juste ici pour l'exhaustivité).
Veuillez noter que vous pouvez obtenir n'importe quel nombre de dates / heures de précision, secondes et minutes, ou secondes, minutes et jours, n'importe où jusqu'à des années (qui contiendraient 6 parties / segments). Si vous spécifiez les deux premiers et qu'il date de plus d'un an, il renverra "Il y a 1 an et 3 mois" et ne renverra pas le reste, car vous avez demandé deux segments. s'il n'a que quelques heures, il ne retournera que "il y a 2 heures et 1 minute". Bien sûr, les mêmes règles s'appliquent si vous spécifiez 1, 2, 3, 4, 5 ou 6 segments (maximum à 6 car les secondes, minutes, heures, jours, mois, années ne font que 6 types). Il corrigera également les problèmes de grammaire tels que "minutes" vs "minute" selon qu'il s'agit d'une minute ou plus, même pour tous les types, et la "chaîne" générée sera toujours grammaticalement correcte.
Voici quelques exemples d'utilisation: bAllowSegments identifie le nombre de segments à afficher ... c'est-à-dire: si 3, alors la chaîne de retour serait (à titre d'exemple) ...
"3 years, 2 months and 13 days"
(n'inclut pas les heures, les minutes et les secondes comme les 3 premières heures catégories sont renvoyées), si toutefois la date était une date plus récente, comme quelque chose d'il y a quelques jours, la spécification des mêmes segments (3) reviendra à la"4 days, 1 hour and 13 minutes ago"
place, donc il prend tout en compte!si bAllowSegments vaut 2, il retournera
"3 years and 2 months"
et si 6 (valeur maximale) retournera"3 years, 2 months, 13 days, 13 hours, 29 minutes and 9 seconds"
, mais rappelez-vous que ce seraNEVER RETURN
quelque chose comme ça"0 years, 0 months, 0 days, 3 hours, 2 minutes and 13 seconds ago"
car il comprend qu'il n'y a pas de données de date dans les 3 premiers segments et les ignore, même si vous spécifiez 6 segments , alors ne vous inquiétez pas :). Bien sûr, s'il y a un segment avec 0 dedans, il en tiendra compte lors de la formation de la chaîne, et s'affichera comme"3 days and 4 seconds ago"
et en ignorant la partie "0 heures"! Profitez-en et commentez si vous le souhaitez.Bien sûr, vous aurez besoin d'une fonction "ReplaceLast", qui prend une chaîne source, et un argument spécifiant ce qui doit être remplacé, et un autre argument spécifiant par quoi vous voulez le remplacer, et il ne remplace que la dernière occurrence de cette chaîne ... j'ai inclus mon un si vous n'en avez pas ou ne voulez pas l'implémenter, alors le voici, il fonctionnera "tel quel" sans aucune modification nécessaire. Je sais que la fonction reverseit n'est plus nécessaire (existe dans .net) mais les fonctions ReplaceLast et ReverseIt sont reportées des jours pre-.net, alors veuillez excuser à quel point elle peut sembler datée (fonctionne toujours à 100%, utilise em depuis plus de dix ans, peut garantir qu'ils sont sans bogue) ... :). à votre santé.
la source
Si vous voulez le nombre exact, vous ne pouvez pas seulement le Timespan, car vous devez savoir à quels mois vous avez affaire et si vous avez affaire à une année bissextile, comme vous l'avez dit.
Soit optez pour un nombre approximatif, soit faites un peu de travail avec les DateTimes d'origine
la source
http://www.astro.uu.nl/~strous/AA/en/reken/juliaansedag.html
Si vous pouvez convertir l'heure d'une date grégorienne en un numéro de jour julien , vous pouvez simplement créer un opérateur pour faire des comparaisons du numéro de jour zulien, qui peut être de type double pour obtenir des mois, des jours, des secondes, etc. lien pour un algorithme de conversion de grégorien à julien.
la source
Il n'y a pas de moyen intégré de faire cela avec précision dans idiomatic-c #. Il existe cependant des solutions de contournement, telles que cet exemple CodeProject que les gens ont codé.
la source
Si vous avez affaire à des mois et des années, vous avez besoin de quelque chose qui sait combien de jours chaque mois compte et quelles années sont des années bissextiles.
Entrez le calendrier grégorien (et tout autre calendrier spécifique à la culture implémentations de ).
Bien que Calendar ne fournisse pas de méthodes pour calculer directement la différence entre deux points dans le temps, il dispose de méthodes telles que
la source
la source
La méthode renvoie une liste qui contient 3 éléments: le premier est l'année, le second le mois et l'élément de fin le jour:
la source
Voici ma contribution pour obtenir la différence en mois que j'ai trouvée exacte:
Usage:
Vous pouvez créer une autre méthode appelée DiffYears et appliquer exactement la même logique que ci-dessus et AddYears au lieu de AddMonths dans la boucle while.
la source
Bien tard dans le match, mais j'imagine que cela peut être utile à quelqu'un. La majorité des gens ont tendance à mesurer mois par mois par date, à l'exclusion du fait que les mois se présentent sous différentes variantes. En utilisant ce cadre de pensée, j'ai créé une ligne unique qui compare les dates pour nous. En utilisant le processus suivant.
Si l'année de fin n'est pas plus grande, nous effectuons la même chose que 2A / 2B, mais sans ajouter les 12 mois car nous n'avons pas besoin d'évaluer autour de l'année.
la source
Mon point de vue sur cette réponse utilise également une méthode d'extension , mais elle peut renvoyer un résultat positif ou négatif.
Quelques tests:
la source
En combinant deux des réponses ci-dessus, une autre méthode d'extension est:
Merci à @AdamRobinson et @MarkWhittaker
la source
Calculez le nombre de mois entre 2 dates:
la source