Perbedaan bulan antara dua tanggal

334

Bagaimana cara menghitung selisih bulan antara dua tanggal dalam C #?

Apakah ada yang setara dengan DateDiff()metode VB di C #. Saya perlu menemukan perbedaan dalam bulan antara dua tanggal yang terpisah tahun. Dokumentasi mengatakan bahwa saya dapat menggunakan TimeSpanseperti:

TimeSpan ts = date1 - date2;

tapi ini memberi saya data dalam Days. Saya tidak ingin membagi angka ini dengan 30 karena tidak setiap bulan adalah 30 hari dan karena dua nilai operan terpisah satu sama lain, saya takut membagi dengan 30 mungkin memberi saya nilai yang salah.

Ada saran?

Rauf
sumber
27
Tentukan "perbedaan dalam bulan", apa perbedaan dalam bulan antara "1 Mei 2010" dan "16 Juni 2010"? 1,5, 1 atau yang lainnya?
Cheng Chen
7
Atau, untuk lebih menekankan poin ini, apa perbedaan dalam bulan antara 31 Desember 2010 dan 1 Jan 2011? Tergantung pada siang hari, perbedaannya hanya 1 detik; Anda akan menghitung ini sebagai perbedaan satu bulan?
stakx - tidak lagi berkontribusi
Berikut adalah kode sederhana dan pendek untuk berjaga-jaga, Anda masih tidak bisa mendapatkan jawabannya, lihat POST ini stackoverflow.com/questions/8820603/…
wirol
11
Danny: 1 bulan dan 15 hari. stakx: 0 bulan dan 1 hari. Intinya adalah untuk mendapatkan komponen bulan . Ini sepertinya cukup jelas bagi saya dan merupakan pertanyaan yang bagus.
Kirk Woll

Jawaban:

462

Mengasumsikan hari dalam bulan tidak relevan (mis. Perbedaan antara 2011.1.1 dan 2010.12.31 adalah 1), dengan date1> date2 memberikan nilai positif dan date2> date1 nilai negatif

((date1.Year - date2.Year) * 12) + date1.Month - date2.Month

Atau, dengan asumsi Anda menginginkan jumlah perkiraan 'bulan rata-rata' antara kedua tanggal, yang berikut ini akan berfungsi untuk semua kecuali perbedaan tanggal yang sangat besar.

date1.Subtract(date2).Days / (365.25 / 12)

Catatan, jika Anda menggunakan solusi yang terakhir maka unit test Anda harus menyatakan rentang tanggal terluas tempat aplikasi Anda dirancang untuk bekerja dan memvalidasi hasil perhitungan yang sesuai.


Perbarui (dengan terima kasih kepada Gary )

Jika menggunakan metode 'bulan rata-rata', angka yang sedikit lebih akurat untuk digunakan untuk 'jumlah hari rata-rata per tahun' adalah 365,2425 .

Adam Ralph
sumber
3
@Kurru - 365/12 hanya merupakan perkiraan ukuran rata-rata sebulan dalam beberapa hari. Ini adalah tindakan yang tidak akurat. Untuk rentang tanggal kecil, ketidaktepatan ini dapat ditoleransi tetapi untuk rentang tanggal yang sangat besar, ketidaktepatan ini dapat menjadi signifikan.
Adam Ralph
21
Saya pikir perlu untuk mempertimbangkan komponen Day. Sesuatu seperti ini (date1.Year - date2.Year) * 12 + date1.Month - date2.Month + (date1.Day >= date2.Day ? 0 : -1)
DrunkCoder
2
@DrunkCoder tergantung pada persyaratan sistem yang diberikan. Dalam beberapa kasus, solusi Anda mungkin memang merupakan pilihan terbaik. Misalnya, penting untuk mempertimbangkan apa yang terjadi ketika dua tanggal mencakup bulan 31 hari, bulan 30 hari, Februari 28 hari atau 29 hari Februari. Jika hasil formula Anda memberikan apa yang dibutuhkan sistem maka itu jelas pilihan yang tepat. Jika tidak, maka diperlukan sesuatu yang lain.
Adam Ralph
6
Yang kedua, apa yang dikatakan Adam, aku menghabiskan waktu bertahun-tahun menulis kode untuk Aktoraris. Beberapa perhitungan dibagi berdasarkan jumlah hari, dibulatkan oleh 30 untuk mendapatkan angka bulanan . Kadang-kadang menghitung bulan diasumsikan setiap tanggal dimulai pada bulan pertama bulan itu, menghitung bulan penuh sesuai . Tidak ada metode terbaik untuk menghitung tanggal. Kecuali jika Anda adalah pelanggan yang Anda tuliskan kode, dorong kembali rantai ini dan lakukan klarifikasi, mungkin oleh akuntan pelanggan Anda.
Binary Worrier
1
365.2425 adalah jumlah hari yang sedikit lebih akurat dalam Kalender Gregorian, jika itu yang Anda gunakan. Namun, berdasarkan DateTime.MaxValue (1 Januari 10000) itu hanya selisih sekitar 59 hari. Juga, definisi setahun dapat sangat berbeda tergantung pada perspektif Anda en.wikipedia.org/wiki/Year .
Gary
207

Berikut adalah solusi komprehensif untuk mengembalikan a DateTimeSpan, mirip dengan a TimeSpan, kecuali bahwa itu mencakup semua komponen tanggal selain komponen waktu.

Pemakaian:

void Main()
{
    DateTime compareTo = DateTime.Parse("8/13/2010 8:33:21 AM");
    DateTime now = DateTime.Parse("2/9/2012 10:10:11 AM");
    var dateSpan = DateTimeSpan.CompareDates(compareTo, now);
    Console.WriteLine("Years: " + dateSpan.Years);
    Console.WriteLine("Months: " + dateSpan.Months);
    Console.WriteLine("Days: " + dateSpan.Days);
    Console.WriteLine("Hours: " + dateSpan.Hours);
    Console.WriteLine("Minutes: " + dateSpan.Minutes);
    Console.WriteLine("Seconds: " + dateSpan.Seconds);
    Console.WriteLine("Milliseconds: " + dateSpan.Milliseconds);
}

Keluaran:

Tahun: 1
Bulan: 5
Hari: 27
Jam: 1
Menit: 36
Detik: 50
Milidetik: 0

Untuk kenyamanan, saya telah memasukkan logika ke dalam DateTimeSpanstruct, tetapi Anda dapat memindahkan metode ini ke CompareDatesmana pun yang Anda inginkan. Perhatikan juga, tidak masalah tanggal mana yang datang sebelum yang lain.

public struct DateTimeSpan
{
    public int Years { get; }
    public int Months { get; }
    public int Days { get; }
    public int Hours { get; }
    public int Minutes { get; }
    public int Seconds { get; }
    public int Milliseconds { get; }

    public DateTimeSpan(int years, int months, int days, int hours, int minutes, int seconds, int milliseconds)
    {
        Years = years;
        Months = months;
        Days = days;
        Hours = hours;
        Minutes = minutes;
        Seconds = seconds;
        Milliseconds = milliseconds;
    }

    enum Phase { Years, Months, Days, Done }

    public static DateTimeSpan CompareDates(DateTime date1, DateTime date2)
    {
        if (date2 < date1)
        {
            var sub = date1;
            date1 = date2;
            date2 = sub;
        }

        DateTime current = date1;
        int years = 0;
        int months = 0;
        int days = 0;

        Phase phase = Phase.Years;
        DateTimeSpan span = new DateTimeSpan();
        int officialDay = current.Day;

        while (phase != Phase.Done)
        {
            switch (phase)
            {
                case Phase.Years:
                    if (current.AddYears(years + 1) > date2)
                    {
                        phase = Phase.Months;
                        current = current.AddYears(years);
                    }
                    else
                    {
                        years++;
                    }
                    break;
                case Phase.Months:
                    if (current.AddMonths(months + 1) > date2)
                    {
                        phase = Phase.Days;
                        current = current.AddMonths(months);
                        if (current.Day < officialDay && officialDay <= DateTime.DaysInMonth(current.Year, current.Month))
                            current = current.AddDays(officialDay - current.Day);
                    }
                    else
                    {
                        months++;
                    }
                    break;
                case Phase.Days:
                    if (current.AddDays(days + 1) > date2)
                    {
                        current = current.AddDays(days);
                        var timespan = date2 - current;
                        span = new DateTimeSpan(years, months, days, timespan.Hours, timespan.Minutes, timespan.Seconds, timespan.Milliseconds);
                        phase = Phase.Done;
                    }
                    else
                    {
                        days++;
                    }
                    break;
            }
        }

        return span;
    }
}
Kirk Woll
sumber
2
@KirkWoll terima kasih. Tetapi mengapa DateTimeSpan mengembalikan 34hari untuk perbedaan waktu tanggal ini sebenarnya adalah 35 timeanddate.com/date/…
Deeptechtons
@ Deeptechtons, tangkapan yang bagus. Ada beberapa masalah yang Anda bawa ke perhatian saya, baik yang berkaitan dengan tanggal mulai adalah 31dan tanggal "melewati" bulan dengan hari lebih sedikit. Saya telah membalikkan logikanya (sehingga berubah dari awal ke lambat daripada sebaliknya) dan sekarang mengakumulasi bulan tanpa mengubah tanggal saat ini (dan dengan demikian melewati di antara bulan dengan hari yang lebih sedikit) Masih belum sepenuhnya yakin apa hasil yang ideal harus ketika membandingkan 10/31/2012ke 11/30/2012. Sekarang hasilnya adalah 1bulan.
Kirk Woll
@KirkWoll terima kasih atas pembaruannya, mungkin saya dapat beberapa gotchas lagi, izinkan saya menegaskannya setelah beberapa tes Good Job :)
Deeptechtons
1
Saya menulis jawaban stackoverflow.com/a/17537472/1737957 untuk pertanyaan serupa yang menguji jawaban yang diajukan (dan menemukan bahwa kebanyakan dari mereka tidak bekerja). Jawaban ini adalah salah satu dari sedikit yang berhasil (menurut test suite saya). Tautan ke github pada jawaban saya.
jwg
@KirkWoll - Jawaban ini tampaknya tidak berfungsi untuk kasus tepi di mana tanggal dari memiliki nilai hari lebih tinggi dari bulan hingga tanggal atau di mana tanggal sumber adalah hari kabisat. Cobalah 2020-02-29untuk 2021-06-29- ia mengembalikan "1thn 4m 1d", tetapi nilai harus "1thn 4m 0d", kan?
Enigmativity
37

Anda bisa melakukannya

if ( date1.AddMonths(x) > date2 )
Mongus Pong
sumber
Ini sangat sederhana dan berfungsi sempurna untuk saya. Saya terkejut melihat itu berfungsi sebagaimana dimaksud ketika menghitung tanggal dari akhir 1 bulan ke tanggal pada akhir bulan berikutnya yang memiliki lebih sedikit hari. Misalnya .. 1-31-2018 + 1 bulan = 28 Februari 218
lucky.expert
Ini adalah salah satu solusi yang lebih baik.
barnacle.m
Solusi yang sangat sederhana dan efisien! Jawaban terbaik yang diajukan.
Cedric Arnould
2
Bagaimana jika date1 = 2018-10-28 dan date2 = 2018-12-21? Jawaban akan 2. sedangkan jawaban yang benar adalah 3. Karena rentang tanggal selama 3 bulan. jika kita menghitung hanya beberapa bulan mengabaikan hari. Jadi jawaban ini TIDAK benar.
Tommix
Lebih logis adalah: if ( date1.AddMonths(x).Month == date2.Month )maka Anda hanya menggunakan x +1 sebagai hitungan bulan
Tommix
34

Jika Anda menginginkan jumlah pasti bulan penuh, selalu positif (2000-01-15, 2000-02-14 menghasilkan 0), mengingat sebulan penuh adalah saat Anda mencapai hari yang sama di bulan berikutnya (seperti perhitungan umur)

public static int GetMonthsBetween(DateTime from, DateTime to)
{
    if (from > to) return GetMonthsBetween(to, from);

    var monthDiff = Math.Abs((to.Year * 12 + (to.Month - 1)) - (from.Year * 12 + (from.Month - 1)));

    if (from.AddMonths(monthDiff) > to || to.Day < from.Day)
    {
        return monthDiff - 1;
    }
    else
    {
        return monthDiff;
    }
}

Sunting alasan: kode lama tidak benar dalam beberapa kasus seperti:

new { From = new DateTime(1900, 8, 31), To = new DateTime(1901, 8, 30), Result = 11 },

Test cases I used to test the function:

var tests = new[]
{
    new { From = new DateTime(1900, 1, 1), To = new DateTime(1900, 1, 1), Result = 0 },
    new { From = new DateTime(1900, 1, 1), To = new DateTime(1900, 1, 2), Result = 0 },
    new { From = new DateTime(1900, 1, 2), To = new DateTime(1900, 1, 1), Result = 0 },
    new { From = new DateTime(1900, 1, 1), To = new DateTime(1900, 2, 1), Result = 1 },
    new { From = new DateTime(1900, 2, 1), To = new DateTime(1900, 1, 1), Result = 1 },
    new { From = new DateTime(1900, 1, 31), To = new DateTime(1900, 2, 1), Result = 0 },
    new { From = new DateTime(1900, 8, 31), To = new DateTime(1900, 9, 30), Result = 0 },
    new { From = new DateTime(1900, 8, 31), To = new DateTime(1900, 10, 1), Result = 1 },
    new { From = new DateTime(1900, 1, 1), To = new DateTime(1901, 1, 1), Result = 12 },
    new { From = new DateTime(1900, 1, 1), To = new DateTime(1911, 1, 1), Result = 132 },
    new { From = new DateTime(1900, 8, 31), To = new DateTime(1901, 8, 30), Result = 11 },
};
Guillaume86
sumber
Hanya untuk menghindari kebingungan bagi orang lain, saya pikir solusi ini tidak benar. Menggunakan test case: new { From = new DateTime(2015, 12, 31), To = new DateTime(2015, 6, 30), Result = 6 } tes akan gagal karena hasilnya 5.
Cristian Badila
Menambahkan intisari cepat dengan perbaikan yang saya usulkan di sini
Cristian Badila
Saya tidak yakin saya mendapatkannya, fungsi saya mengembalikan 6 sebagaimana mestinya: dotnetfiddle.net/MRZNnC
Guillaume86
Saya menyalin test case di sini dengan tangan dan ini memiliki kesalahan. Spec gagal harus: new { From = new DateTime(2015, 12, 31), To = new DateTime(2016, 06, 30), Result = 6 }. "Bug" terletak pada to.Day < from.Daykode yang tidak memperhitungkan bahwa bulan dapat berakhir pada "hari dalam sebulan" yang berbeda. Dalam hal ini dari 31 Desember 2015, hingga 30 Juni 2016, 6 bulan penuh akan berlalu (sejak Juni memiliki 30 hari) tetapi kode Anda akan kembali 5.
Cristian Badila
3
Itu perilaku yang diharapkan menurut saya, baik atau perilaku yang setidaknya saya harapkan. Saya menyelesaikan satu bulan penuh adalah ketika Anda mencapai hari yang sama (atau bulan berikutnya seperti dalam kasus ini)
Guillaume86
22

Saya memeriksa penggunaan metode ini di VB.NET melalui MSDN dan tampaknya memiliki banyak penggunaan. Tidak ada metode bawaan seperti itu di C #. (Bahkan itu bukan ide yang baik) Anda dapat memanggil VB di C #.

  1. Tambahkan Microsoft.VisualBasic.dllke proyek Anda sebagai referensi
  2. gunakan Microsoft.VisualBasic.DateAndTime.DateDiff dalam kode Anda
Cheng Chen
sumber
7
Menurut Anda mengapa itu bukan ide yang baik? Secara intuitif, saya akan menebak bahwa perpustakaan adalah 'hanya perpustakaan NET.' Untuk runtime. Catatan, saya bermain sebagai penasihat setan di sini, saya juga akan enggan melakukan ini karena itu hanya 'terasa salah' (semacam curang) tapi saya bertanya-tanya apakah ada alasan teknis yang meyakinkan untuk tidak melakukan ini.
Adam Ralph
3
@AdamRalph: Tidak ada alasan sama sekali untuk tidak melakukannya. Pustaka tersebut diimplementasikan dalam kode yang dikelola 100%, jadi semuanya sama dengan yang lainnya. Satu-satunya perbedaan yang mungkin adalah bahwa Microsoft.VisualBasic.dllmodul harus dimuat, tetapi waktu yang diperlukan untuk melakukan itu dapat diabaikan. Tidak ada alasan untuk menipu diri Anda sendiri dari fitur yang telah teruji dan berguna hanya karena Anda telah memilih untuk menulis program Anda dalam C #. (Ini berlaku untuk hal-hal seperti My.Application.SplashScreenjuga.)
Cody Gray
3
Apakah Anda akan berubah pikiran jika Anda tahu itu ditulis dalam C #? Dulu. Dengan logika yang sama, menggunakan System.Data dan PresentationFramework juga curang, sebagian besar ditulis dalam C ++ / CLI.
Hans Passant
3
@AdamRalph: Adakah contoh khusus dari "bagasi aneh" yang muncul di benak Anda? Atau apakah Anda mengatakan itu murni hipotesis? Dan ya, itu mungkin mengacaukan pikiran beberapa teman C # Anda yang telah menulis sejumlah kode untuk melakukan sesuatu yang dapat Anda lakukan dalam satu baris dengan usingpernyataan yang benar , tetapi saya ragu akan ada kerusakan serius.
Cody Gray
1
@Cody Grey: setuju, contohnya sepele seperti yang Anda gambarkan. Ini adalah kode tambahan 'noise' yang diperkenalkan dengan memanggil metode yang tidak biasa (dari C # POV) yang ingin saya hindari. Dalam tim yang terorganisasi dengan baik hal-hal seperti itu akan tetap dijemput dalam tinjauan kode dan dapat dengan mudah dihindari. BTW - Saya tidak mencoba untuk menyerang VB6 / VB.NET. Saya menggambarkan metode seperti 'aneh' hanya karena, dari. NET POV, tidak ada alasan untuk DateAndTime.Year()ada, mengingat yang DateTimememiliki Yearproperti. Itu hanya ada untuk membuat VB.NET tampak lebih seperti VB6. Sebagai mantan programmer VB6, saya bisa menghargai ini ;-)
Adam Ralph
10

Untuk mendapatkan perbedaan dalam bulan (termasuk awal dan akhir), terlepas dari tanggal:

DateTime start = new DateTime(2013, 1, 1);
DateTime end = new DateTime(2014, 2, 1);
var diffMonths = (end.Month + end.Year * 12) - (start.Month + start.Year * 12);
Chirag
sumber
5
Bayangkan startdan endidentik. Lalu Anda mendapatkan hasil 1. Bagaimana itu benar? Mengapa Anda menambahkan 1 ke hasilnya? Siapa yang memberikan suara untuk jawaban ini: - /?
paul
Untuk tanggal yang identik, itu akan memberikan output sebagai 1. Pada dasarnya, itu akan menghitung semua bulan termasuk awal dan akhir bulan.
Chirag
3
tidak terdengar seperti perbedaan antara dua item bagi saya. Apa perbedaan antara 2 dan 2? Benarkah 1? Saya akan menyarankan perbedaannya adalah 0.
paul
8

Gunakan Waktu Noda :

LocalDate start = new LocalDate(2013, 1, 5);
LocalDate end = new LocalDate(2014, 6, 1);
Period period = Period.Between(start, end, PeriodUnits.Months);
Console.WriteLine(period.Months); // 16

(contoh sumber)

Edward Brey
sumber
7

Saya hanya perlu sesuatu yang sederhana untuk memenuhi misalnya tanggal kerja di mana hanya bulan / tahun dimasukkan, jadi ingin tahun yang berbeda dan bulan bekerja. Inilah yang saya gunakan, di sini hanya untuk kegunaan saja

public static YearsMonths YearMonthDiff(DateTime startDate, DateTime endDate) {
    int monthDiff = ((endDate.Year * 12) + endDate.Month) - ((startDate.Year * 12) + startDate.Month) + 1;
    int years = (int)Math.Floor((decimal) (monthDiff / 12));
    int months = monthDiff % 12;
    return new YearsMonths {
        TotalMonths = monthDiff,
            Years = years,
            Months = months
    };
}

.NET Fiddle

jenson-button-event
sumber
4

Anda bisa menggunakan kelas DateDiff dari Perpustakaan Periode Waktu untuk .NET :

// ----------------------------------------------------------------------
public void DateDiffSample()
{
  DateTime date1 = new DateTime( 2009, 11, 8, 7, 13, 59 );
  DateTime date2 = new DateTime( 2011, 3, 20, 19, 55, 28 );
  DateDiff dateDiff = new DateDiff( date1, date2 );

  // differences
  Console.WriteLine( "DateDiff.Months: {0}", dateDiff.Months );
  // > DateDiff.Months: 16

  // elapsed
  Console.WriteLine( "DateDiff.ElapsedMonths: {0}", dateDiff.ElapsedMonths );
  // > DateDiff.ElapsedMonths: 4

  // description
  Console.WriteLine( "DateDiff.GetDescription(6): {0}", dateDiff.GetDescription( 6 ) );
  // > DateDiff.GetDescription(6): 1 Year 4 Months 12 Days 12 Hours 41 Mins 29 Secs
} // DateDiffSample

sumber
2

Inilah kontribusi saya untuk mendapatkan perbedaan dalam Bulan yang menurut saya akurat:

namespace System
{
     public static class DateTimeExtensions
     {
         public static Int32 DiffMonths( this DateTime start, DateTime end )
         {
             Int32 months = 0;
             DateTime tmp = start;

             while ( tmp < end )
             {
                 months++;
                 tmp = tmp.AddMonths( 1 );
             }

             return months;
        }
    }
}

Pemakaian:

Int32 months = DateTime.Now.DiffMonths( DateTime.Now.AddYears( 5 ) );

Anda dapat membuat metode lain yang disebut DiffYears dan menerapkan logika yang persis sama seperti di atas dan AddYears alih-alih AddMonths di loop sementara.

Morg
sumber
2

Ini bekerja untuk apa saya membutuhkannya. Hari bulan tidak menjadi masalah dalam kasus saya karena selalu merupakan hari terakhir bulan itu.

public static int MonthDiff(DateTime d1, DateTime d2){
    int retVal = 0;

    if (d1.Month<d2.Month)
    {
        retVal = (d1.Month + 12) - d2.Month;
        retVal += ((d1.Year - 1) - d2.Year)*12;
    }
    else
    {
        retVal = d1.Month - d2.Month;
        retVal += (d1.Year - d2.Year)*12;
    }
    //// Calculate the number of years represented and multiply by 12
    //// Substract the month number from the total
    //// Substract the difference of the second month and 12 from the total
    //retVal = (d1.Year - d2.Year) * 12;
    //retVal = retVal - d1.Month;
    //retVal = retVal - (12 - d2.Month);

    return retVal;
}
Elmer
sumber
2

Cara yang paling tepat adalah ini yang mengembalikan perbedaan dalam beberapa bulan berdasarkan fraksi:

private double ReturnDiffereceBetweenTwoDatesInMonths(DateTime startDateTime, DateTime endDateTime)
{
    double result = 0;
    double days = 0;
    DateTime currentDateTime = startDateTime;
    while (endDateTime > currentDateTime.AddMonths(1))
    {
        result ++;

        currentDateTime = currentDateTime.AddMonths(1);
    }

    if (endDateTime > currentDateTime)
    {
        days = endDateTime.Subtract(currentDateTime).TotalDays;

    }
    return result + days/endDateTime.GetMonthDays;
}
Saeed Mahmoudi
sumber
2

Ini adalah solusi sederhana yang paling tidak cocok untuk saya. Ini mungkin bukan yang tercepat karena menggunakan fitur AddMonth DateTime yang keren dalam satu lingkaran:

public static int GetMonthsDiff(DateTime start, DateTime end)
{
    if (start > end)
        return GetMonthsDiff(end, start);

    int months = 0;
    do
    {
        start = start.AddMonths(1);
        if (start > end)
            return months;

        months++;
    }
    while (true);
}
Simon Mourier
sumber
1
Public Class ClassDateOperation
    Private prop_DifferenceInDay As Integer
    Private prop_DifferenceInMonth As Integer
    Private prop_DifferenceInYear As Integer


    Public Function DayMonthYearFromTwoDate(ByVal DateStart As Date, ByVal DateEnd As Date) As ClassDateOperation
        Dim differenceInDay As Integer
        Dim differenceInMonth As Integer
        Dim differenceInYear As Integer
        Dim myDate As Date

        DateEnd = DateEnd.AddDays(1)

        differenceInYear = DateEnd.Year - DateStart.Year

        If DateStart.Month <= DateEnd.Month Then
            differenceInMonth = DateEnd.Month - DateStart.Month
        Else
            differenceInYear -= 1
            differenceInMonth = (12 - DateStart.Month) + DateEnd.Month
        End If


        If DateStart.Day <= DateEnd.Day Then
            differenceInDay = DateEnd.Day - DateStart.Day
        Else

            myDate = CDate("01/" & DateStart.AddMonths(1).Month & "/" & DateStart.Year).AddDays(-1)
            If differenceInMonth <> 0 Then
                differenceInMonth -= 1
            Else
                differenceInMonth = 11
                differenceInYear -= 1
            End If

            differenceInDay = myDate.Day - DateStart.Day + DateEnd.Day

        End If

        prop_DifferenceInDay = differenceInDay
        prop_DifferenceInMonth = differenceInMonth
        prop_DifferenceInYear = differenceInYear

        Return Me
    End Function

    Public ReadOnly Property DifferenceInDay() As Integer
        Get
            Return prop_DifferenceInDay
        End Get
    End Property

    Public ReadOnly Property DifferenceInMonth As Integer
        Get
            Return prop_DifferenceInMonth
        End Get
    End Property

    Public ReadOnly Property DifferenceInYear As Integer
        Get
            Return prop_DifferenceInYear
        End Get
    End Property

End Class
Mohammad Ali
sumber
1

Ini dari perpustakaan saya sendiri, akan mengembalikan perbedaan bulan antara dua tanggal.

public static int MonthDiff(DateTime d1, DateTime d2)
{
    int retVal = 0;

    // Calculate the number of years represented and multiply by 12
    // Substract the month number from the total
    // Substract the difference of the second month and 12 from the total
    retVal = (d1.Year - d2.Year) * 12;
    retVal = retVal - d1.Month;
    retVal = retVal - (12 - d2.Month);

    return retVal;
}
Wayne
sumber
1
Apakah ini berhasil? Saya terus mendapatkan 11 di atas kertas untuk Jan-31-2014danDec-31-2013
Dave Cousineau
1

Anda dapat memiliki fungsi seperti ini.

Misalnya, mulai 2012/12/27 hingga 2012/12/29 menjadi 3 hari. Demikian juga, dari 2012/12/15 hingga 2013/01/15 menjadi 2 bulan, karena hingga 2013/01/14 adalah 1 bulan. mulai tanggal 15 bulan kedua dimulai.

Anda dapat menghapus "=" pada kondisi if kedua, jika Anda tidak ingin memasukkan kedua hari dalam perhitungan. yaitu, dari 2012/12/15 hingga 2013/01/15 adalah 1 bulan.

public int GetMonths(DateTime startDate, DateTime endDate)
{
    if (startDate > endDate)
    {
        throw new Exception("Start Date is greater than the End Date");
    }

    int months = ((endDate.Year * 12) + endDate.Month) - ((startDate.Year * 12) + startDate.Month);

    if (endDate.Day >= startDate.Day)
    {
        months++;
    }

    return months;
}
Firnas
sumber
1

Anda dapat menggunakan ekstensi berikut: Kode

public static class Ext
{
    #region Public Methods

    public static int GetAge(this DateTime @this)
    {
        var today = DateTime.Today;
        return ((((today.Year - @this.Year) * 100) + (today.Month - @this.Month)) * 100 + today.Day - @this.Day) / 10000;
    }

    public static int DiffMonths(this DateTime @from, DateTime @to)
    {
        return (((((@to.Year - @from.Year) * 12) + (@to.Month - @from.Month)) * 100 + @to.Day - @from.Day) / 100);
    }

    public static int DiffYears(this DateTime @from, DateTime @to)
    {
        return ((((@to.Year - @from.Year) * 100) + (@to.Month - @from.Month)) * 100 + @to.Day - @from.Day) / 10000;
    }

    #endregion Public Methods
}

Penerapan !

int Age;
int years;
int Months;
//Replace your own date
var d1 = new DateTime(2000, 10, 22);
var d2 = new DateTime(2003, 10, 20);
//Age
Age = d1.GetAge();
Age = d2.GetAge();
//positive
years = d1.DiffYears(d2);
Months = d1.DiffMonths(d2);
//negative
years = d2.DiffYears(d1);
Months = d2.DiffMonths(d1);
//Or
Months = Ext.DiffMonths(d1, d2);
years = Ext.DiffYears(d1, d2); 
Waleed AK
sumber
1

Inilah solusi yang jauh lebih ringkas menggunakan VB.Net DateDiff untuk Tahun, Bulan, Hari saja. Anda dapat memuat pustaka DateDiff di C # juga.

date1 harus <= date2

VB.NET

Dim date1 = Now.AddDays(-2000)
Dim date2 = Now
Dim diffYears = DateDiff(DateInterval.Year, date1, date2) - If(date1.DayOfYear > date2.DayOfYear, 1, 0)
Dim diffMonths = DateDiff(DateInterval.Month, date1, date2) - diffYears * 12 - If(date1.Day > date2.Day, 1, 0)
Dim diffDays = If(date2.Day >= date1.Day, date2.Day - date1.Day, date2.Day + (Date.DaysInMonth(date1.Year, date1.Month) - date1.Day))

C #

DateTime date1 = Now.AddDays(-2000);
DateTime date2 = Now;
int diffYears = DateDiff(DateInterval.Year, date1, date2) - date1.DayOfYear > date2.DayOfYear ? 1 : 0;
int diffMonths = DateDiff(DateInterval.Month, date1, date2) - diffYears * 12 - date1.Day > date2.Day ? 1 : 0;
int diffDays = date2.Day >= date1.Day ? date2.Day - date1.Day : date2.Day + (System.DateTime.DaysInMonth(date1.Year, date1.Month) - date1.Day);
Brent
sumber
1

Ini sebagai jawaban atas jawaban Kirk Woll. Saya belum memiliki poin reputasi yang cukup untuk membalas komentar ...

Saya menyukai solusi Kirk dan akan merobeknya tanpa malu-malu dan menggunakannya dalam kode saya, tetapi ketika saya melihatnya, saya menyadari bahwa itu terlalu rumit. Pergantian dan perulangan yang tidak perlu, dan konstruktor publik yang tidak berguna untuk digunakan.

Inilah penulisan ulang saya:

public class DateTimeSpan {
    private DateTime _date1;
    private DateTime _date2;
    private int _years;
    private int _months;
    private int _days;
    private int _hours;
    private int _minutes;
    private int _seconds;
    private int _milliseconds;

    public int Years { get { return _years; } }
    public int Months { get { return _months; } }
    public int Days { get { return _days; } }
    public int Hours { get { return _hours; } }
    public int Minutes { get { return _minutes; } }
    public int Seconds { get { return _seconds; } }
    public int Milliseconds { get { return _milliseconds; } }

    public DateTimeSpan(DateTime date1, DateTime date2) {
        _date1 = (date1 > date2) ? date1 : date2;
        _date2 = (date2 < date1) ? date2 : date1;

        _years = _date1.Year - _date2.Year;
        _months = (_years * 12) + _date1.Month - _date2.Month;
        TimeSpan t = (_date2 - _date1);
        _days = t.Days;
        _hours = t.Hours;
        _minutes = t.Minutes;
        _seconds = t.Seconds;
        _milliseconds = t.Milliseconds;

    }

    public static DateTimeSpan CompareDates(DateTime date1, DateTime date2) {
        return new DateTimeSpan(date1, date2);
    }
}

Penggunaan1, hampir sama:

void Main()
{
    DateTime compareTo = DateTime.Parse("8/13/2010 8:33:21 AM");
    DateTime now = DateTime.Parse("2/9/2012 10:10:11 AM");
    var dateSpan = new DateTimeSpan(compareTo, now);
    Console.WriteLine("Years: " + dateSpan.Years);
    Console.WriteLine("Months: " + dateSpan.Months);
    Console.WriteLine("Days: " + dateSpan.Days);
    Console.WriteLine("Hours: " + dateSpan.Hours);
    Console.WriteLine("Minutes: " + dateSpan.Minutes);
    Console.WriteLine("Seconds: " + dateSpan.Seconds);
    Console.WriteLine("Milliseconds: " + dateSpan.Milliseconds);
}

Penggunaan2, serupa:

void Main()
{
    DateTime compareTo = DateTime.Parse("8/13/2010 8:33:21 AM");
    DateTime now = DateTime.Parse("2/9/2012 10:10:11 AM");
    Console.WriteLine("Years: " + DateTimeSpan.CompareDates(compareTo, now).Years);
    Console.WriteLine("Months: " + DateTimeSpan.CompareDates(compareTo, now).Months);
    Console.WriteLine("Days: " + DateTimeSpan.CompareDates(compareTo, now).Days);
    Console.WriteLine("Hours: " + DateTimeSpan.CompareDates(compareTo, now).Hours);
    Console.WriteLine("Minutes: " + DateTimeSpan.CompareDates(compareTo, now).Minutes);
    Console.WriteLine("Seconds: " + DateTimeSpan.CompareDates(compareTo, now).Seconds);
    Console.WriteLine("Milliseconds: " + DateTimeSpan.CompareDates(compareTo, now).Milliseconds);
}
John A
sumber
1

Dalam kasus saya, diperlukan untuk menghitung bulan lengkap dari tanggal mulai ke hari sebelum hari ini di bulan berikutnya atau dari awal hingga akhir bulan.


Mis: mulai 1/1/2018 hingga 31/1/2018 adalah bulan lengkap
Ex2: dari 5/1/2018 hingga 4/2/2018 adalah bulan lengkap

jadi berdasarkan ini di sini adalah solusi saya:

public static DateTime GetMonthEnd(DateTime StartDate, int MonthsCount = 1)
{
    return StartDate.AddMonths(MonthsCount).AddDays(-1);
}
public static Tuple<int, int> CalcPeriod(DateTime StartDate, DateTime EndDate)
{
    int MonthsCount = 0;
    Tuple<int, int> Period;
    while (true)
    {
        if (GetMonthEnd(StartDate) > EndDate)
            break;
        else
        {
            MonthsCount += 1;
            StartDate = StartDate.AddMonths(1);
        }
    }
    int RemainingDays = (EndDate - StartDate).Days + 1;
    Period = new Tuple<int, int>(MonthsCount, RemainingDays);
    return Period;
}

Pemakaian:

Tuple<int, int> Period = CalcPeriod(FromDate, ToDate);

Catatan: dalam kasus saya itu diperlukan untuk menghitung hari-hari yang tersisa setelah bulan-bulan lengkap jadi jika bukan kasus Anda, Anda dapat mengabaikan hasil hari atau bahkan Anda dapat mengubah metode pengembalian dari tuple ke integer.

Ahmed
sumber
1
public static int PayableMonthsInDuration(DateTime StartDate, DateTime EndDate)
{
    int sy = StartDate.Year; int sm = StartDate.Month; int count = 0;
    do
    {
        count++;if ((sy == EndDate.Year) && (sm >= EndDate.Month)) { break; }
        sm++;if (sm == 13) { sm = 1; sy++; }
    } while ((EndDate.Year >= sy) || (EndDate.Month >= sm));
    return (count);
}

Solusi ini untuk perhitungan Sewa / berlangganan, di mana perbedaan tidak berarti menjadi pengurangan, itu dimaksudkan sebagai rentang dalam dua tanggal tersebut.

Sukanta
sumber
1

Ada 3 kasus: tahun yang sama, tahun sebelumnya dan tahun-tahun lainnya.

Jika hari dalam sebulan tidak masalah ...

public int GetTotalNumberOfMonths(DateTime start, DateTime end)
{
    // work with dates in the right order
    if (start > end)
    {
        var swapper = start;
        start = end;
        end = swapper;
    }

    switch (end.Year - start.Year)
    {
        case 0: // Same year
            return end.Month - start.Month;

        case 1: // last year
            return (12 - start.Month) + end.Month;

        default:
            return 12 * (3 - (end.Year - start.Year)) + (12 - start.Month) + end.Month;
    }
}
Patrice Calvé
sumber
1

Saya menulis fungsi untuk menyelesaikan ini, karena cara-cara lain tidak berhasil untuk saya.

public string getEndDate (DateTime startDate,decimal monthCount)
{
    int y = startDate.Year;
    int m = startDate.Month;

    for (decimal  i = monthCount; i > 1; i--)
    {
        m++;
        if (m == 12)
        { y++;
            m = 1;
        }
    }
    return string.Format("{0}-{1}-{2}", y.ToString(), m.ToString(), startDate.Day.ToString());
}
reza akhlaghi
sumber
Harap jawab dalam bahasa Inggris (vs. bahasa yang ditemukan ...)
kleopatra
Mengapa tidak melakukan startDate.AddMonths (monthCount) .ToShortDateString ()? Ini tidak menjawab pertanyaan asli yang ditanyakan pula!
TabbyCool
oh, maaf @TabbyCool, kode ini berfungsi baik di program saya! aturan programmer mengatakan: kode pertama berfungsi dan kemudian optimasi! tanx for
your
1

Pemahaman saya tentang perbedaan bulan total antara 2 tanggal memiliki bagian integral dan fraksional (tanggal penting).

Bagian integral adalah perbedaan bulan penuh.

Bagian fraksional, bagi saya, adalah perbedaan dari% hari (ke hari penuh bulan) antara bulan awal dan akhir.

public static class DateTimeExtensions
{
    public static double TotalMonthsDifference(this DateTime from, DateTime to)
    {
        //Compute full months difference between dates
        var fullMonthsDiff = (to.Year - from.Year)*12 + to.Month - from.Month;

        //Compute difference between the % of day to full days of each month
        var fractionMonthsDiff = ((double)(to.Day-1) / (DateTime.DaysInMonth(to.Year, to.Month)-1)) -
            ((double)(from.Day-1)/ (DateTime.DaysInMonth(from.Year, from.Month)-1));

        return fullMonthsDiff + fractionMonthsDiff;
    }
}

Dengan ekstensi ini, itulah hasilnya:

2/29/2000 TotalMonthsDifference 2/28/2001 => 12
2/28/2000 TotalMonthsDifference 2/28/2001 => 12.035714285714286
01/01/2000 TotalMonthsDifference 01/16/2000 => 0.5
01/31/2000 TotalMonthsDifference 01/01/2000 => -1.0
01/31/2000 TotalMonthsDifference 02/29/2000 => 1.0
01/31/2000 TotalMonthsDifference 02/28/2000 => 0.9642857142857143
01/31/2001 TotalMonthsDifference 02/28/2001 => 1.0
George Mavritsakis
sumber
1

Tidak ada banyak jawaban yang jelas tentang ini karena Anda selalu mengasumsikan sesuatu.

Solusi ini menghitung antara dua tanggal bulan antara asumsi Anda ingin menyimpan hari bulan untuk perbandingan, (artinya hari bulan dipertimbangkan dalam perhitungan)

Contoh, jika Anda memiliki tanggal 30 Jan 2012, 29 Feb 2012 tidak akan menjadi sebulan tetapi 01 Maret 2013 akan.

Sudah diuji cukup menyeluruh, mungkin akan membersihkannya nanti saat kita menggunakannya, tapi di sini:

private static int TotalMonthDifference(DateTime dtThis, DateTime dtOther)
{
    int intReturn = 0;
    bool sameMonth = false;

    if (dtOther.Date < dtThis.Date) //used for an error catch in program, returns -1
        intReturn--;

    int dayOfMonth = dtThis.Day; //captures the month of day for when it adds a month and doesn't have that many days
    int daysinMonth = 0; //used to caputre how many days are in the month

    while (dtOther.Date > dtThis.Date) //while Other date is still under the other
    {
        dtThis = dtThis.AddMonths(1); //as we loop, we just keep adding a month for testing
        daysinMonth = DateTime.DaysInMonth(dtThis.Year, dtThis.Month); //grabs the days in the current tested month

        if (dtThis.Day != dayOfMonth) //Example 30 Jan 2013 will go to 28 Feb when a month is added, so when it goes to march it will be 28th and not 30th
        {
            if (daysinMonth < dayOfMonth) // uses day in month max if can't set back to day of month
                dtThis.AddDays(daysinMonth - dtThis.Day);
            else
                dtThis.AddDays(dayOfMonth - dtThis.Day);
        }
        if (((dtOther.Year == dtThis.Year) && (dtOther.Month == dtThis.Month))) //If the loop puts it in the same month and year
        {
            if (dtOther.Day >= dayOfMonth) //check to see if it is the same day or later to add one to month
                intReturn++;
            sameMonth = true; //sets this to cancel out of the normal counting of month
        }
        if ((!sameMonth)&&(dtOther.Date > dtThis.Date))//so as long as it didn't reach the same month (or if i started in the same month, one month ahead, add a month)
            intReturn++;
    }
    return intReturn; //return month
}
GreatNate
sumber
1

Berdasarkan pada pekerjaan DateTimeSpan yang sangat baik yang dilakukan di atas, saya telah menormalkan kode sedikit; ini tampaknya bekerja dengan cukup baik:

public class DateTimeSpan
{
  private DateTimeSpan() { }

  private DateTimeSpan(int years, int months, int days, int hours, int minutes, int seconds, int milliseconds)
  {
    Years = years;
    Months = months;
    Days = days;
    Hours = hours;
    Minutes = minutes;
    Seconds = seconds;
    Milliseconds = milliseconds;
  }

  public int Years { get; private set; } = 0;
  public int Months { get; private set; } = 0;
  public int Days { get; private set; } = 0;
  public int Hours { get; private set; } = 0;
  public int Minutes { get; private set; } = 0;
  public int Seconds { get; private set; } = 0;
  public int Milliseconds { get; private set; } = 0;

  public static DateTimeSpan CompareDates(DateTime StartDate, DateTime EndDate)
  {
    if (StartDate.Equals(EndDate)) return new DateTimeSpan();
    DateTimeSpan R = new DateTimeSpan();
    bool Later;
    if (Later = StartDate > EndDate)
    {
      DateTime D = StartDate;
      StartDate = EndDate;
      EndDate = D;
    }

    // Calculate Date Stuff
    for (DateTime D = StartDate.AddYears(1); D < EndDate; D = D.AddYears(1), R.Years++) ;
    if (R.Years > 0) StartDate = StartDate.AddYears(R.Years);
    for (DateTime D = StartDate.AddMonths(1); D < EndDate; D = D.AddMonths(1), R.Months++) ;
    if (R.Months > 0) StartDate = StartDate.AddMonths(R.Months);
    for (DateTime D = StartDate.AddDays(1); D < EndDate; D = D.AddDays(1), R.Days++) ;
    if (R.Days > 0) StartDate = StartDate.AddDays(R.Days);

    // Calculate Time Stuff
    TimeSpan T1 = EndDate - StartDate;
    R.Hours = T1.Hours;
    R.Minutes = T1.Minutes;
    R.Seconds = T1.Seconds;
    R.Milliseconds = T1.Milliseconds;

    // Return answer. Negate values if the Start Date was later than the End Date
    if (Later)
      return new DateTimeSpan(-R.Years, -R.Months, -R.Days, -R.Hours, -R.Minutes, -R.Seconds, -R.Milliseconds);
    return R;
  }
}
Dan Sutton
sumber
Ketika membandingkan dengan di CompareDates(x, y)mana x={01/02/2019 00:00:00}dan y={01/05/2020 00:00:00}kemudian Monthsmemberi saya2
Bassie
1

Fungsi statis sederhana ini menghitung fraksi bulan antara dua Datetimes, misalnya

  • 1.1. ke 31.1. = 1.0
  • 1.4. ke 15.4. = 0,5
  • 16.4. hingga 30,4. = 0,5
  • 1.3. ke 1.4. = 1 + 1/30

Fungsi ini mengasumsikan bahwa kencan pertama lebih kecil dari kencan kedua. Untuk berurusan dengan interval waktu negatif, seseorang dapat memodifikasi fungsi dengan mudah dengan memperkenalkan tanda dan swap variabel di awal.

public static double GetDeltaMonths(DateTime t0, DateTime t1)
{
     DateTime t = t0;
     double months = 0;
     while(t<=t1)
     {
         int daysInMonth = DateTime.DaysInMonth(t.Year, t.Month);
         DateTime endOfMonth = new DateTime(t.Year, t.Month, daysInMonth);
         int cutDay = endOfMonth <= t1 ? daysInMonth : t1.Day;
         months += (cutDay - t.Day + 1) / (double) daysInMonth;
         t = new DateTime(t.Year, t.Month, 1).AddMonths(1);
     }
     return Math.Round(months,2);
 }
Michael
sumber
0

Untuk dapat menghitung perbedaan antara 2 tanggal dalam bulan adalah hal yang sangat logis untuk dilakukan, dan diperlukan dalam banyak aplikasi bisnis. Beberapa coders di sini yang telah memberikan komentar seperti - apa perbedaan dalam bulan antara "1 Mei 2010" dan "16 Juni 2010, apa perbedaan dalam bulan antara 31 Desember 2010 dan 1 Januari 2011? - telah gagal untuk memahami dasar-dasar aplikasi bisnis.

Berikut adalah jawaban untuk 2 komentar di atas - Jumlah bulan antara 1-Mei-2010 dan 16 Juni-2010 adalah 1 bulan, jumlah bulan antara 31-Desember-2010 dan 1-Januari-2011 adalah 0. akan sangat bodoh untuk menghitungnya sebagai 1,5 bulan dan 1 detik, seperti yang disarankan oleh pembuat kode di atas.

Orang-orang yang telah mengerjakan kartu kredit, pemrosesan hipotek, pemrosesan pajak, pemrosesan sewa, perhitungan bunga bulanan, dan beragam solusi bisnis lainnya akan setuju.

Masalahnya adalah bahwa fungsi seperti itu tidak termasuk dalam C # atau VB.NET dalam hal ini. Datediff hanya memperhitungkan tahun atau komponen bulan, jadi sebenarnya tidak berguna.

Berikut adalah beberapa contoh kehidupan nyata di mana Anda perlu dan dapat dengan benar menghitung bulan:

Anda tinggal di sewa jangka pendek dari 18 Februari hingga 23 Agustus. Berapa bulan tinggal di sana? Jawabannya sederhana - 6 bulan

Anda memiliki rekening bank tempat bunga dihitung dan dibayar pada akhir setiap bulan. Anda menyetor uang pada 10 Juni dan mengeluarkannya pada 29 Oktober (tahun yang sama). Berapa bulan yang Anda minati? Jawaban yang sangat sederhana - 4 bulan (lagi hari tambahan tidak masalah)

Dalam aplikasi bisnis, sebagian besar waktu, ketika Anda perlu menghitung bulan, itu karena Anda perlu tahu bulan 'penuh' berdasarkan bagaimana manusia menghitung waktu; tidak didasarkan pada beberapa pemikiran abstrak / tidak relevan.

Tom
sumber
5
Ini adalah salah satu alasan mengapa akuntansi bukan matematika. Dalam akuntansi hasilnya tergantung pada cara Anda menghitungnya .. Saya tahu poin Anda dan saya tahu "pandangan bisnis umum" tentang ini, tetapi penjelasan ini jelas salah. Antara 2012.11.30 dan 2012.12.01 ada 0, atau 1/30, atau 1/31, atau 1 atau 2 bulan, tergantung pada apa yang Anda minta . Apakah tanggal eksklusif atau inklusif? Apakah Anda meminta jumlah bulan melewati, menyentuh, atau berlalu? Apakah Anda ingin membulatkan ke atas, ke atas ke bawah, atau tepat?
quetzalcoatl
3
Sekarang jelaskan kepada orang bisnis atau seorang akuntan dan mereka akan memberi Anda tampilan bingung. Itu selalu "sangat jelas bagi mereka bahwa mereka tentu saja berarti X dan Y dan Z, bagaimana Anda bisa berpikir berbeda?" Sekarang dapatkan beberapa pebisnis dan usahakan agar mereka menyetujui topik tersebut. Akuntan lebih cenderung untuk setuju, karena pada suatu saat mereka akan menggunakan matematika untuk memeriksa dengan opsi apa mereka mungkin secara tidak sengaja meringkas periode yang sama dua kali, dll. Bahkan contoh perhitungan Anda dapat diperdebatkan dan tergantung pada wilayah, atau jelas tidak valid karena mereka menganggap aturan bisnis tambahan seperti mengabaikan hari ekstra.
quetzalcoatl
2
-1 Anda mengasumsikan bahwa semua perangkat lunak adalah "aplikasi bisnis". Tujuan kode yang dimaksud tidak disebutkan. Anda juga menganggap semua "aplikasi bisnis" memiliki aturan yang sama, yang jelas tidak benar.
Jesse Webb
0

Diperluas struct Kirks dengan ToString (format) dan Durasi (ms panjang)

 public struct DateTimeSpan
{
    private readonly int years;
    private readonly int months;
    private readonly int days;
    private readonly int hours;
    private readonly int minutes;
    private readonly int seconds;
    private readonly int milliseconds;

    public DateTimeSpan(int years, int months, int days, int hours, int minutes, int seconds, int milliseconds)
    {
        this.years = years;
        this.months = months;
        this.days = days;
        this.hours = hours;
        this.minutes = minutes;
        this.seconds = seconds;
        this.milliseconds = milliseconds;
    }

    public int Years { get { return years; } }
    public int Months { get { return months; } }
    public int Days { get { return days; } }
    public int Hours { get { return hours; } }
    public int Minutes { get { return minutes; } }
    public int Seconds { get { return seconds; } }
    public int Milliseconds { get { return milliseconds; } }

    enum Phase { Years, Months, Days, Done }


    public string ToString(string format)
    {
        format = format.Replace("YYYY", Years.ToString());
        format = format.Replace("MM", Months.ToString());
        format = format.Replace("DD", Days.ToString());
        format = format.Replace("hh", Hours.ToString());
        format = format.Replace("mm", Minutes.ToString());
        format = format.Replace("ss", Seconds.ToString());
        format = format.Replace("ms", Milliseconds.ToString());
        return format;
    }


    public static DateTimeSpan Duration(long ms)
    {
        DateTime dt = new DateTime();
        return CompareDates(dt, dt.AddMilliseconds(ms));
    }


    public static DateTimeSpan CompareDates(DateTime date1, DateTime date2)
    {
        if (date2 < date1)
        {
            var sub = date1;
            date1 = date2;
            date2 = sub;
        }

        DateTime current = date1;
        int years = 0;
        int months = 0;
        int days = 0;

        Phase phase = Phase.Years;
        DateTimeSpan span = new DateTimeSpan();

        while (phase != Phase.Done)
        {
            switch (phase)
            {
                case Phase.Years:
                    if (current.AddYears(years + 1) > date2)
                    {
                        phase = Phase.Months;
                        current = current.AddYears(years);
                    }
                    else
                    {
                        years++;
                    }
                    break;
                case Phase.Months:
                    if (current.AddMonths(months + 1) > date2)
                    {
                        phase = Phase.Days;
                        current = current.AddMonths(months);
                    }
                    else
                    {
                        months++;
                    }
                    break;
                case Phase.Days:
                    if (current.AddDays(days + 1) > date2)
                    {
                        current = current.AddDays(days);
                        var timespan = date2 - current;
                        span = new DateTimeSpan(years, months, days, timespan.Hours, timespan.Minutes, timespan.Seconds, timespan.Milliseconds);
                        phase = Phase.Done;
                    }
                    else
                    {
                        days++;
                    }
                    break;
            }
        }

        return span;
    }
}
Ivan
sumber
0
  var dt1 = (DateTime.Now.Year * 12) + DateTime.Now.Month;
  var dt2 = (DateTime.Now.AddMonths(-13).Year * 12) + DateTime.Now.AddMonths(-13).Month;
  Console.WriteLine(dt1);
  Console.WriteLine(dt2);
  Console.WriteLine((dt1 - dt2));
Paul
sumber