Domanda

I'm trying to code a generic function to return the difference between two dates in a customized format, but one person reported me that my snippet has an error for example trying to get the difference between this two dates:

15/08/2013 - 02/09/2013 

And my Function returns negative values and also a 1 month of difference 'cause 09 is greater than 08, so it's not working like I need:

1 Months, -1 Weeks, -6 Days, 0 Hours, 0 Minutes and 0 Seconds

The expected result would be this:

0 Months, 2 Weeks, 4 Days, 0 Hours, 0 Minutes and 0 Seconds

Someone can help me to correct that error in some dates?

Here is my code:

#Region " Date Difference "

    ' Date Difference
    '
    ' // By Elektro H@cker
    '
    ' Examples :
    '
    ' MsgBox(DateDifference(DateTime.Parse("01/03/2013"), DateTime.Parse("10/04/2013"))) ' Result: 1 Months, 1 Weeks, 2 Days, 0 Hours, 0 Minutes and 0 Seconds
    ' MsgBox(DateDifference(DateTime.Parse("01/01/2013 14:00:00"), DateTime.Parse("02/01/2013 15:00:30"))) ' Result: 0 Months, 0 Weeks, 1 Days, 1 Hours, 0 Minutes and 30 Seconds

    Private Function DateDifference(ByVal Date1 As DateTime, ByVal Date2 As DateTime) As String

        Dim MonthDiff As String, WeekDiff As String, _
            DayDiff As String, HourDiff As String, _
            MinuteDiff As String, SecondDiff As String

        MonthDiff = Convert.ToString(DateDiff("M", Date1, Date2))
        WeekDiff = Convert.ToString(DateDiff("d", Date1.AddMonths(DateDiff("M", Date1, Date2)), Date2) \ 7)
        DayDiff = Convert.ToString(DateDiff("d", Date1.AddMonths(DateDiff("M", Date1, Date2)), Date2) - (WeekDiff * 7))
        HourDiff = Convert.ToString(DateDiff("h", Date1.AddHours(DateDiff("h", Date1, Date2)), Date2) - (Date1.Hour - Date2.Hour))
        MinuteDiff = Convert.ToString(DateDiff("n", Date1.AddMinutes(DateDiff("n", Date1, Date2)), Date2) - (Date1.Minute - Date2.Minute))
        SecondDiff = Convert.ToString(DateDiff("s", Date1.AddSeconds(DateDiff("s", Date1, Date2)), Date2) - (Date1.Second - Date2.Second))

        Return String.Format("{0} Months, {1} Weeks, {2} Days, {3} Hours, {4} Minutes and {5} Seconds", _
                             MonthDiff, WeekDiff, DayDiff, HourDiff, MinuteDiff, SecondDiff)

    End Function

#End Region

UPDATE:

I'm trying to do it like this way, but now how to substract the weeks ?

Private Function DateDifference(ByVal Date1 As DateTime, ByVal Date2 As DateTime) As String

Dim MonthDiff As String, WeekDiff As String, _
   DayDiff As String, HourDiff As String, _
   MinuteDiff As String, SecondDiff As String

MonthDiff = Date2.Month - Date1.Month

' WeekDiff = Date2.Month - Date1.Month

DayDiff = Date2.Day - Date1.Day

HourDiff = Date2.Hour - Date1.Hour

MinuteDiff = Date2.Minute - Date1.Minute

SecondDiff = Date2.Second - Date1.Second

'  MsgBox((Date2 - Date1).ToString("dd"))

Return String.Format("{0} Months, {1} Weeks, {2} Days, {3} Hours, {4} Minutes and {5} Seconds", _
                      MonthDiff, WeekDiff, DayDiff, HourDiff, MinuteDiff, SecondDiff)

End Function

UPDATE 2:

I'm trying to rewrite it using other method to get date accuracy but I¡m totally lost:

Private Function DateDifference(ByVal Date1 As DateTime, ByVal Date2 As DateTime) As String

    Dim DayDiff As Long = Date2.Subtract(Date1).Days
    Dim HourDiff As Long = Date2.Subtract(Date1).Hours
    Dim MinuteDiff As Long = Date2.Subtract(Date1).Minutes
    Dim SecondDiff As Long = Date2.Subtract(Date1).Seconds
    Dim MilliDiff As Long = Date2.Subtract(Date1).Milliseconds

    Dim MonthDiFF As Long
    Dim WeekDiFF As Long

    Select Case (DayDiff Mod DateTime.DaysInMonth(Date1.Year, Date1.Month))

        Case Is <= 0
            MonthDiFF = 0

        Case Is = 1, Is <= 28
            MonthDiFF = 1

        Case Is > 28

    End Select

    MsgBox(DayDiff Mod DateTime.DaysInMonth(Date1.Year, Date1.Month))
    MsgBox(MonthDiFF)

    ' Return String.Format("{0} Months, {1} Weeks, {2} Days, {3} Hours, {4} Minutes and {5} Seconds", _
    '                          MonthDiff, WeekDiff, t.Days, t.Hours, t.Minutes, t.Seconds)

End Function

UPDATE 3:

I'm more near to code it but like I've said I'm lost calculating things:

Private Function DateDifference(ByVal Date1 As DateTime, ByVal Date2 As DateTime) As String

    Dim DayDiff As Long = Date2.Subtract(Date1).Days
    Dim HourDiff As Long = Date2.Subtract(Date1).Hours
    Dim MinuteDiff As Long = Date2.Subtract(Date1).Minutes
    Dim SecondDiff As Long = Date2.Subtract(Date1).Seconds
    Dim MilliDiff As Long = Date2.Subtract(Date1).Milliseconds

    Dim MonthDiFF As Long
    Dim WeekDiFF As Long

    For X As Short = CShort(Date1.Month) To CShort(Date2.Month)

        MonthDiFF =
        MsgBox(DayDiff - DateTime.DaysInMonth(Date1.Year, X))

        'MsgBox(DateTime.DaysInMonth(Date1.Year, X))
    Next

    ' MsgBox(DayDiff - DateTime.DaysInMonth(Date1.Year, Date1.Month))
    ' MsgBox(MonthDiFF)

    ' Return String.Format("{0} Months, {1} Weeks, {2} Days, {3} Hours, {4} Minutes and {5} Seconds", _
    '                          MonthDiff, WeekDiff, t.Days, t.Hours, t.Minutes, t.Seconds)

End Function
È stato utile?

Soluzione

This calculates the months and weeks programmatically, then uses a TimeSpan for the remaining portions. The month calculation, which would be tricky, uses the intelligent behavior of AddMonths.

Private Function DateDifference(ByVal Date1 As DateTime, ByVal Date2 As DateTime) As String
    Dim MonthDiff = 0
    While Date1 <= Date2
        Date1 = Date1.AddMonths(1)
        MonthDiff += 1
    End While
    MonthDiff -= 1
    Date1 = Date1.AddMonths(-1)
    Dim t As TimeSpan = Date2 - Date1
    Dim WeekDiff As Integer = t.Days \ 7
    t = t - TimeSpan.FromDays(WeekDiff * 7)
    Return String.Format("{0} Months, {1} Weeks, {2} Days, {3} Hours, {4} Minutes and {5} Seconds", _
                             MonthDiff, WeekDiff, t.Days, t.Hours, t.Minutes, t.Seconds)
End Function

Altri suggerimenti

I think the simplest way would be to compare both dates first and then depending on which date is bigger (later) do your DateDiff. This way you coule avoid negatives. Another way to go would to take the absolute value of the DateDiff result, as it shouldn't matter if it's a month a before or after as long as it is 1 month.

This should do what you want, for most the TimeSpan class gives you the answer:

Public Shared Function DateDifference(ByVal Date1 As DateTime, ByVal Date2 As DateTime) As String
    Dim diff As TimeSpan = Date2 - Date1
    Dim months = (Date2.Month - Date1.Month) + 12 * (Date2.Year - Date1.Year)
    diff -= TimeSpan.FromDays(months * 30)
    Dim weeks = Math.Floor(diff.Days / 7)
    diff -= TimeSpan.FromDays(weeks * 7)
    Dim dayDiff = (diff.Days Mod 7).ToString()
    Dim hourDiff = diff.Hours.ToString()
    Dim minDiff = diff.Minutes.ToString()
    Dim secDiff = diff.Seconds.ToString()

    Return String.Format("{0} Months, {1} Weeks, {2} Days, {3} Hours, {4} Minutes and {5} Seconds", _
                         months.ToString, weeks.ToString, dayDiff, hourDiff, minDiff, secDiff)
End Function

Test:

Dim diffInfo = DateDifference(New Date(2013, 8, 16, 14, 0, 0), New Date(2013, 9, 28, 15, 2, 5))
Console.WriteLine(diffInfo) '1 Months, 1 Weeks, 6 Days, 1 Hours, 2 Minutes and 5 Seconds

Why not just use DateTime.Subtract?

DateTime date1 = new DateTime(2013, 3, 4, 12, 30, 00);
DateTime date2 = DateTime.Now;
TimeSpan diff = date2.Subtract(date1);                 // Subtract dates gives a time span

And then use TimeSpan.ToString

string s = diff.ToString("hh:mm:ss");

It's also possible to subtract a TimeSpan value:

DateTime date = DateTime.Now;
TimeSpan span = new TimeSpan(5, 12, 30, 0);           // 5 Days, 12.5 hours
DateTime newDate = date.Subtract(span);               // Subtract time span from date gives another date

Please be aware about the difference between DateTimeand TimeSpan!

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top