In C # /. NET TimeSpan
hat TotalDays
, TotalMinutes
etc., aber ich kann keine Formel für die Gesamtmonatsdifferenz herausfinden. Variable Tage pro Monat und Schaltjahre werfen mich immer wieder ab. Wie kann ich TotalMonths erhalten ?
Bearbeiten Es tut mir leid, dass ich nicht klarer bin: Ich weiß, dass ich das nicht wirklich verstehen kann, TimeSpan
aber ich dachte, ich würde es verwenden TotalDays
und TotalMinutes
wäre ein gutes Beispiel, um auszudrücken, wonach ich gesucht habe ... außer ich versuche, Gesamtmonate zu erhalten.
Beispiel: 25. Dezember 2009 - 6. Oktober 2009 = 2 Gesamtmonate. Der 6. Oktober bis 5. November entspricht 0 Monaten. Am 6. November, 1 Monat. Am 6. Dezember 2 Monate
Antworten:
Sie werden das nicht von a bekommen können
TimeSpan
, weil ein "Monat" eine variable Maßeinheit ist. Sie müssen es selbst berechnen und herausfinden, wie genau es funktionieren soll.Sollten Daten beispielsweise einen Unterschied von einem Monat oder null Monaten aufweisen
July 5, 2009
undAugust 4, 2009
ergeben? Wenn Sie sagen, es sollte einen ergeben, was ist dann mitJuly 31, 2009
undAugust 1, 2009
? Ist das ein Monat? Ist es einfach die Differenz derMonth
Werte für die Daten oder hängt es eher mit einer tatsächlichen Zeitspanne zusammen? Die Logik zum Bestimmen all dieser Regeln ist nicht trivial, daher müssen Sie Ihre eigenen bestimmen und den entsprechenden Algorithmus implementieren.Wenn Sie nur einen Unterschied in den Monaten wünschen - ohne Berücksichtigung der Datumswerte -, können Sie Folgendes verwenden:
Beachten Sie, dass dies eine relative Differenz zurückgibt. Wenn dies
rValue
größer als istlValue
, ist der Rückgabewert negativ. Wenn Sie einen absoluten Unterschied wollen, können Sie dies verwenden:quelle
(Mir ist klar, dass dies eine alte Frage ist, aber ...)
Dies ist in reinem .NET relativ schmerzhaft. Ich würde meine eigene Noda Time- Bibliothek empfehlen , die speziell für solche Dinge entwickelt wurde:
(Es gibt andere Optionen, z. B. wenn Sie auch über Jahre hinweg nur eine Anzahl von Monaten wünschen, die Sie verwenden würden
Period period = Period.Between(start, end, PeriodUnits.Months);
)quelle
Period.Between
. Habe den Code so bearbeitet, dass er mit NodaTime 1.3.1 funktioniert.Vielleicht möchten Sie nichts über Monatsfraktionen wissen. Was ist mit diesem Code?
quelle
Sie müssen zunächst definieren, was Sie unter TotalMonths verstehen.
Eine einfache Definition legt einen Monat auf 30,4 Tage (365,25 / 12).
Darüber hinaus scheint jede Definition einschließlich Brüchen nutzlos zu sein, und der häufigere ganzzahlige Wert (ganze Monate zwischen Daten) hängt auch von nicht standardmäßigen Geschäftsregeln ab.
quelle
Ich habe eine sehr einfache Erweiterungsmethode für
DateTime
undDateTimeOffset
dazu geschrieben. Ich wollte, dass es genau so funktioniert, wie eineTotalMonths
ImmobilieTimeSpan
funktionieren würde: dh die Anzahl der vollständigen Monate zwischen zwei Daten zurückgeben, wobei alle Teilmonate ignoriert werden. Weil es darauf basiertDateTime.AddMonths()
, respektiert es unterschiedliche Monatslängen und gibt zurück, was ein Mensch als Zeitraum von Monaten verstehen würde.(Leider können Sie es nicht als Erweiterungsmethode in TimeSpan implementieren, da das Wissen über die tatsächlich verwendeten Daten nicht erhalten bleibt und sie monatelang wichtig sind.)
Der Code und die Tests sind beide auf GitHub verfügbar . Der Code ist sehr einfach:
Und es besteht alle diese Unit-Testfälle:
quelle
Sie müssen es selbst aus den Datenzeiten herausarbeiten. Wie Sie mit den Stub-Tagen am Ende umgehen, hängt davon ab, wofür Sie sie verwenden möchten.
Eine Methode wäre, den Monat zu zählen und am Ende die Tage zu korrigieren. Etwas wie:
quelle
Ich würde es so machen:
quelle
return (dtOther.Month - dtThis.Month) + 12 * (dtOther.Year - dtThis.Year);
Es gibt nicht viele klare Antworten darauf, weil Sie immer Dinge annehmen.
Diese Lösung berechnet zwischen zwei Daten die Monate zwischen der Annahme, dass Sie den Tag des Monats zum Vergleich speichern möchten (dh, der Tag des Monats wird bei der Berechnung berücksichtigt).
Wenn Sie beispielsweise ein Datum vom 30. Januar 2012 haben, ist der 29. Februar 2012 kein Monat, sondern der 1. März 2013.
Es wurde ziemlich gründlich getestet, wird es wahrscheinlich später bereinigen, wenn wir es verwenden, und nimmt zwei Daten anstelle einer Zeitspanne auf, was wahrscheinlich besser ist. Hoffe das hilft jemand anderem.
quelle
Die akzeptierte Antwort funktioniert perfekt, wenn Sie volle Monate möchten.
Ich brauchte Teilmonate. Dies ist die Lösung, die ich für Teilmonate gefunden habe:
Ich brauchte auch einen Jahresunterschied mit dem gleichen Bedarf für Teiljahre. Hier ist die Lösung, die ich gefunden habe:
quelle
YearDifference
Funktion, alslValue.Month < rValue.Month
- ich habe das jetzt behoben, möchten Sie vielleicht überprüfen ...Alte Frage, die ich kenne, aber vielleicht jemandem helfen könnte. Ich habe die oben von @Adam akzeptierte Antwort verwendet, dann aber überprüft, ob die Differenz 1 oder -1 beträgt, und dann überprüft, ob es sich um eine vollständige Differenz des Kalendermonats handelt. 21/07/55 und 20/08/55 wären also kein voller Monat, sondern 21/07/55 und 21/07/55.
quelle
quelle
Das Problem mit Monaten ist, dass es nicht wirklich eine einfache Maßnahme ist - sie sind nicht konstant groß. Sie müssten Ihre Regeln für das definieren, was Sie einschließen möchten, und von dort aus arbeiten. Zum Beispiel vom 1. Januar bis 1. Februar - Sie könnten argumentieren, dass dort 2 Monate beteiligt sind, oder Sie könnten sagen, dass dies ein Monat ist. Was ist dann mit "1 Jan 20:00" bis "1 Feb 00:00" - das ist nicht ganz ein ganzer Monat. Ist das 0? 1? Was ist mit umgekehrt (1. Januar 00:00 bis 1. Februar 20:00) ... 1? 2?
Definieren Sie zuerst die Regeln, dann müssen Sie sie selbst codieren, fürchte ich ...
quelle
Wenn Sie ein Ergebnis
1
zwischen28th Feb
und haben möchten1st March
:quelle
Diese Bibliothek berechnet die Differenz der Monate unter Berücksichtigung aller Teile von DateTime:
quelle
Im Folgenden finden Sie die genaueste Methode, da die Definition von "1 Monat" sich je nach Monat ändert und keine der anderen Antworten dies berücksichtigt! Wenn Sie weitere Informationen zu dem Problem wünschen, das nicht in das Framework integriert ist, können Sie diesen Beitrag lesen: Ein reales Zeitspannenobjekt mit .Jahren und .Monaten (das Lesen dieses Beitrags ist jedoch nicht erforderlich, um die folgende Funktion zu verstehen und zu verwenden. Es funktioniert zu 100%, ohne die inhärenten Ungenauigkeiten der Annäherung, die andere gerne verwenden - und Sie können die .ReverseIt-Funktion durch die integrierte .Reverse-Funktion ersetzen, die Sie möglicherweise in Ihrem Framework haben (der Vollständigkeit halber nur hier).
Bitte beachten Sie, dass Sie eine beliebige Anzahl von Datums- / Zeitgenauigkeiten, Sekunden und Minuten oder Sekunden, Minuten und Tage bis zu Jahren (die 6 Teile / Segmente enthalten würden) erhalten können. Wenn Sie die Top 2 angeben und diese älter als ein Jahr sind, wird "vor 1 Jahr und 3 Monaten" zurückgegeben und der Rest wird nicht zurückgegeben, da Sie zwei Segmente angefordert haben. Wenn es nur ein paar Stunden alt ist, wird es nur "vor 2 Stunden und 1 Minute" zurückgegeben. Natürlich gelten dieselben Regeln, wenn Sie 1, 2, 3, 4, 5 oder 6 Segmets angeben (maximal 6, da Sekunden, Minuten, Stunden, Tage, Monate, Jahre nur 6 Typen ergeben). Es werden auch Grammatikprobleme wie "Minuten" und "Minute" korrigiert, je nachdem, ob es 1 Minute oder mehr ist, für alle Typen gleich, und die generierte "Zeichenfolge" ist immer grammatikalisch korrekt.
Hier einige Beispiele zur Verwendung: bAllowSegments gibt an, wie viele Segmente angezeigt werden sollen ... dh: Wenn 3, wäre die Rückgabezeichenfolge (als Beispiel) ...
"3 years, 2 months and 13 days"
(ohne Stunden, Minuten und Sekunden als Top-3-Zeit Kategorien werden zurückgegeben), wenn das Datum jedoch ein neueres Datum war, z. B. vor einigen Tagen, wird"4 days, 1 hour and 13 minutes ago"
stattdessen die Angabe derselben Segmente (3) zurückgegeben , sodass alles berücksichtigt wird!Wenn bAllowSegments 2 ist, wird es zurückgegeben
"3 years and 2 months"
und wenn 6 (Maximalwert) zurückgegeben wird. Beachten Sie"3 years, 2 months, 13 days, 13 hours, 29 minutes and 9 seconds"
jedoch, dassNEVER RETURN
dies in"0 years, 0 months, 0 days, 3 hours, 2 minutes and 13 seconds ago"
etwa so ist, da es keine Datumsdaten in den oberen 3 Segmenten enthält und diese ignoriert, selbst wenn Sie 6 Segmente angeben Also mach dir keine Sorgen :). Wenn sich ein Segment mit 0 darin befindet, wird dies natürlich beim Bilden des Strings berücksichtigt und als"3 days and 4 seconds ago"
Teil "0 Stunden" angezeigt und ignoriert! Viel Spaß und bitte kommentieren Sie, wenn Sie möchten.Natürlich benötigen Sie eine "ReplaceLast" -Funktion, die eine Quellzeichenfolge und ein Argument verwendet, das angibt, was ersetzt werden muss, und ein weiteres Argument, das angibt, durch was ersetzt werden soll, und das nur das letzte Vorkommen dieser Zeichenfolge ersetzt ... Ich habe meine aufgenommen, wenn Sie keine haben oder sie nicht implementieren möchten. Hier funktioniert sie also "wie sie ist", ohne dass Änderungen erforderlich sind. Ich weiß, dass die Umkehrfunktion nicht mehr benötigt wird (existiert in .net), aber die Funktionen ReplaceLast und ReverseIt wurden aus den Tagen vor.net übernommen. Bitte entschuldigen Sie, wie alt sie aussehen könnten (funktioniert immer noch zu 100%, obwohl sie verwendet wurden) em seit über zehn Jahren, kann garantieren, dass sie fehlerfrei sind) ... :). Prost.
quelle
Wenn Sie die genaue Zahl wollen, können Sie nicht nur aus der Zeitspanne, da Sie wissen müssen, welche Monate Sie zu tun haben und ob Sie es mit einem Schaltjahr zu tun haben, wie Sie sagten.
Geben Sie entweder eine ungefähre Zahl an oder spielen Sie mit den ursprünglichen DateTimes
quelle
http://www.astro.uu.nl/~strous/AA/en/reken/juliaansedag.html
Wenn Sie die Zeit von einem gregorianischen Datum in eine julianische Tageszahl umrechnen lassen können, können Sie einfach einen Operator erstellen, um Vergleiche der zulianischen Tageszahl durchzuführen, die doppelt eingegeben werden kann, um Monate, Tage, Sekunden usw. zu erhalten Link für einen Algorithmus zur Konvertierung von Gregorianisch nach Julian.
quelle
In idiomatic-c # gibt es keine eingebaute Möglichkeit, dies genau zu tun. Es gibt einige Problemumgehungen, wie z. B. dieses CodeProject-Beispiel , das von Personen codiert wurde.
quelle
Wenn Sie mit Monaten und Jahren zu tun haben, brauchen Sie etwas, das weiß, wie viele Tage jeder Monat hat und welche Jahre Schaltjahre sind.
Geben Sie den Gregorianischen Kalender (und andere kulturspezifische Kalenderimplementierungen ) ein.
Der Kalender bietet zwar keine Methoden zur direkten Berechnung der Differenz zwischen zwei Zeitpunkten, verfügt jedoch über Methoden wie
quelle
quelle
Die Methode gibt eine Liste zurück, die 3 Elemente enthält: Das erste ist das Jahr, das zweite der Monat und das Endelement der Tag:
quelle
Hier ist mein Beitrag, um einen Unterschied in Monaten zu erzielen, den ich für richtig befunden habe:
Verwendung:
Sie können eine andere Methode namens DiffYears erstellen und genau dieselbe Logik wie oben und AddYears anstelle von AddMonths in der while-Schleife anwenden.
quelle
Viel zu spät zum Spiel, aber ich kann mir vorstellen, dass dies für jemanden hilfreich sein kann. Die Mehrheit der Menschen neigt dazu, Monat für Monat nach Datum zu messen, mit Ausnahme der Tatsache, dass Monate in verschiedenen Variationen vorliegen. Mit diesem Gedankenrahmen habe ich einen Einzeiler erstellt, der die Daten für uns vergleicht. Verwenden Sie den folgenden Prozess.
Wenn das Endjahr nicht größer ist, führen wir die gleiche Leistung wie 2A / 2B durch, jedoch ohne die 12 Monate hinzuzufügen, da wir nicht um das Jahr herum bewerten müssen.
quelle
Meine Einstellung zu dieser Antwort verwendet ebenfalls eine Erweiterungsmethode , die jedoch ein positives oder negatives Ergebnis liefern kann.
Ein paar Tests:
quelle
Wenn Sie zwei der obigen Antworten kombinieren, ist eine andere Erweiterungsmethode:
Vielen Dank an @AdamRobinson und @MarkWhittaker
quelle
Berechnen Sie die Anzahl der Monate zwischen 2 Daten:
quelle