2

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
ElektroStudios
  • 19,105
  • 33
  • 200
  • 417

4 Answers4

1

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.

KonB
  • 220
  • 1
  • 10
1

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!

joe
  • 8,344
  • 9
  • 54
  • 80
1

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
Tim Schmelter
  • 450,073
  • 74
  • 686
  • 939
  • Thanks for the answer but the code isn't working with this dates: "16/08/2013 14:00:00" - "18/09/2013 15:02:05", it returns this result: "-1 Months, 5 Weeks, 33 Days, 1 Hours, 2 Minutes and 5 Seconds" – ElektroStudios Aug 15 '13 at 19:26
  • @ElektroHacker: Edited my answer, there was a "turner" on the month calculation. – Tim Schmelter Aug 15 '13 at 19:32
  • It says there's one month and a day between 31 Aug and 1 Sep. The days accounted for in the months should not be counted in weeks or days. – Tim S. Aug 15 '13 at 19:34
  • no way, using this dates "16/08/2013 14:00:00" - "28/08/2013 15:02:05" the result is: 0 Months, 2 Weeks, 12 Days, 1 Hours, 2 Minutes and 5 Seconds – ElektroStudios Aug 15 '13 at 19:34
  • What is the desired result? – Tim Schmelter Aug 15 '13 at 19:37
  • The difference in the last dates it's 1 week and 4 days but it shows 2 weeks and 12 days xD, getting the week value seems a hard thing for everybody like me – ElektroStudios Aug 15 '13 at 19:38
  • So the days is just the remainder and not the total days? – Tim Schmelter Aug 15 '13 at 19:39
  • @Tim Schmelter yes thats it – ElektroStudios Aug 15 '13 at 19:40
  • @ElektroHacker: But 12 days should be 1 week and 5 days then. Edited my answer, try again. – Tim Schmelter Aug 15 '13 at 19:43
  • Thankyou for your patience but in this dates: "16/08/2013 14:02:00" - "28/09/2013 15:02:05", the result is this: 1 Months, 6 Weeks, 1 Days, 1 Hours, 0 Minutes and 5 Seconds, but would be this else: 1 Months, 1 Weeks, 5 Days, 1 Hours, 0 Minutes and 5 Seconds – ElektroStudios Aug 15 '13 at 19:57
  • Anyways now I've noticed your method will not work under dates as february with 28 days or 30 or 31 days, it just counts the months as "1" without date efficacy :( – ElektroStudios Aug 15 '13 at 20:03
1

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
Tim S.
  • 55,448
  • 7
  • 96
  • 122
  • Thankyou but it returns negative values for this dates: "16/02/2013 14:00:00" - "28/03/2013 15:02:05" – ElektroStudios Aug 15 '13 at 20:05
  • @ElektroHacker I've updated my answer to fix that; I converted my code from C# and missed that integer division in C# is not like integer division in VB.Net. – Tim S. Aug 15 '13 at 20:25
  • Really thankyou but it does not have date accuracy, for example between those dates: "01/02/2013 14:00:00" - "01/03/2013 15:02:05", the result is "1 month", but febryary has 28 days so really the result would be "4 weeks". please see my updates – ElektroStudios Aug 15 '13 at 20:43
  • @ElektroHacker what would you consider to be 1 month after Feb 1, Mar 1, and Apr 1? I'd expect Mar 1, Apr 1, and May 1. – Tim S. Aug 15 '13 at 21:57
  • By Sr. Google: 1 month = 30.4368499 days, it is not the same when we say "1 month" than a "1 month" (full month). – ElektroStudios Aug 15 '13 at 23:31
  • Anyways the months are not a exactly science and this is the best solution, works fine, thanks for your time! – ElektroStudios Aug 15 '13 at 23:56