Page 2 of 3 FirstFirst 123 LastLast
Results 41 to 80 of 93

Thread: Calculating exact time in Years, MOnths, Days

  1. #41
    Member
    Join Date
    Mar 2011
    Posts
    44

    Re: Calculating exact time in Years, MOnths, Days

    Hey my friend
    Ju can adjust the day month and year how you want now the negative you can remove by splitting again because in this case the number is correct exept the negative.

    If you have any questions I like to hear.
    If you prefer emailing pietercdevries@gmail.com

  2. #42
    Smooth Moperator techgnome's Avatar
    Join Date
    May 2002
    Posts
    34,532

    Re: Calculating exact time in Years, MOnths, Days

    Still doesn't work... it appears to work... but consider the following dates:
    2011-02-05 & 2011-03-03 .... by your numbers, that's 1 month (03-02) & 2 days (abs(03-05))... but it isn't... it's 28days... less than a month. your calcs work only under the assumption of 30day months.

    consider still
    2011-01-30 and 2011-02-05 ... your calc would have it as 1 month (02-01) & 25 days(abs(05-30)). Again, this isn't accurate.

    Shall I go on? Try two dates that straddle the new year.
    2011-12-15 & 2012-01-15... 1 year (2012-2011) 11 months (abs(01-12)) and 0 days (15-15) ... again...

    -tg
    * I don't respond to private (PM) requests for help. It's not conducive to the general learning of others.*
    * I also don't respond to friend requests. Save a few bits and don't bother. I'll just end up rejecting anyways.*
    * How to get EFFECTIVE help: The Hitchhiker's Guide to Getting Help at VBF - Removing eels from your hovercraft *
    * How to Use Parameters * Create Disconnected ADO Recordset Clones * Set your VB6 ActiveX Compatibility * Get rid of those pesky VB Line Numbers * I swear I saved my data, where'd it run off to??? *

  3. #43
    Powered By Medtronic dbasnett's Avatar
    Join Date
    Dec 2007
    Location
    Jefferson City, MO
    Posts
    9,754

    Re: Calculating exact time in Years, MOnths, Days

    This is how I test age (as years / days OR years / months / days) calculations.

    I have a series of past dates and future dates that I use.

    Code:
        Dim dp() As Date = New Date() {#1/31/2004#, #2/29/2004#, #1/31/2005#}
        Dim df() As Date = New Date() {#1/31/2009#, #2/28/2009#, #12/31/2009#}
    The basic loop looks like this

    Code:
            For Each pastDate In dp
    
                For Each futureDate In df
    
                    Dim stopAt As Date = futureDate
                    futureDate = pastDate.AddDays(1)
                    Do While futureDate <= stopAt
    
                        'calculate age then check
    
                        futureDate = futureDate.AddDays(1)
                    Loop
    
                Next
    
            Next

    Basic age as years and days check

    If days are greater than 365 it is an error.
    If the years changes, then the days should be 0.
    If the years are the same then the days should be one more than the previous day count.


    Basic age as years, months, and days check

    If days are greater than 31 it is an error.
    If the year changes, then the days and months should be 0.
    If the months changes, then the days should be 0.
    If the months are the same then the days should be one more than the previous day count.
    My First Computer -- Documentation Link (RT?M) -- Using the Debugger -- Prime Number Sieve
    Counting Bits -- Subnet Calculator -- UI Guidelines -- >> SerialPort Answer <<

    "Those who use Application.DoEvents have no idea what it does and those who know what it does never use it." John Wein

  4. #44
    Powered By Medtronic dbasnett's Avatar
    Join Date
    Dec 2007
    Location
    Jefferson City, MO
    Posts
    9,754

    Re: Calculating exact time in Years, MOnths, Days

    Quote Originally Posted by techgnome View Post
    Still doesn't work... it appears to work... but consider the following dates:
    2011-02-05 & 2011-03-03 .... by your numbers, that's 1 month (03-02) & 2 days (abs(03-05))... but it isn't... it's 28days... less than a month. your calcs work only under the assumption of 30day months.

    consider still
    2011-01-30 and 2011-02-05 ... your calc would have it as 1 month (02-01) & 25 days(abs(05-30)). Again, this isn't accurate.

    Shall I go on? Try two dates that straddle the new year.
    2011-12-15 & 2012-01-15... 1 year (2012-2011) 11 months (abs(01-12)) and 0 days (15-15) ... again...

    -tg
    By my calculation 2011-02-05 & 2011-03-03 is 26 days (and 26 days when I use a calendar and count the days manually).

    I didn't test pauls last submission because it did not lend itself to being put into my test rig.
    My First Computer -- Documentation Link (RT?M) -- Using the Debugger -- Prime Number Sieve
    Counting Bits -- Subnet Calculator -- UI Guidelines -- >> SerialPort Answer <<

    "Those who use Application.DoEvents have no idea what it does and those who know what it does never use it." John Wein

  5. #45
    Powered By Medtronic dbasnett's Avatar
    Join Date
    Dec 2007
    Location
    Jefferson City, MO
    Posts
    9,754

    Re: Calculating exact time in Years, MOnths, Days

    So I figured out how to check pauls code using my test rig. Here is the first error sequence

    0 years, 0 months, 28 days between 1/31/2004 2/28/2004
    0 years, 0 months, 29 days between 1/31/2004 2/29/2004 <<<<<<<<<<<<<<<<<<<< s/b 1 month
    0 years, 0 months, 30 days between 1/31/2004 3/1/2004 <<<<<<<<<<<<<<<<<<<< s/b 1 month 1 day
    0 years, 1 months, 2 days between 1/31/2004 3/2/2004

    and another

    5 years, 0 months, -2 days between 2/29/2004 2/27/2009 A C
    5 years, 0 months, -1 days between 2/29/2004 2/28/2009 A C
    5 years, 0 months, 0 days between 2/29/2004 3/1/2009 C
    5 years, 1 months, -28 days between 2/29/2004 3/2/2009 A C
    5 years, 1 months, -27 days between 2/29/2004 3/3/2009 A C
    Last edited by dbasnett; Jul 26th, 2011 at 08:55 AM.
    My First Computer -- Documentation Link (RT?M) -- Using the Debugger -- Prime Number Sieve
    Counting Bits -- Subnet Calculator -- UI Guidelines -- >> SerialPort Answer <<

    "Those who use Application.DoEvents have no idea what it does and those who know what it does never use it." John Wein

  6. #46
    Smooth Moperator techgnome's Avatar
    Join Date
    May 2002
    Posts
    34,532

    Re: Calculating exact time in Years, MOnths, Days

    My point was that the calculation that was being proposed of blindly day - day1, month - month1, year - year1 produces wrong results under some cases... enough of a problem to not be a viable solution imho.

    -tg
    * I don't respond to private (PM) requests for help. It's not conducive to the general learning of others.*
    * I also don't respond to friend requests. Save a few bits and don't bother. I'll just end up rejecting anyways.*
    * How to get EFFECTIVE help: The Hitchhiker's Guide to Getting Help at VBF - Removing eels from your hovercraft *
    * How to Use Parameters * Create Disconnected ADO Recordset Clones * Set your VB6 ActiveX Compatibility * Get rid of those pesky VB Line Numbers * I swear I saved my data, where'd it run off to??? *

  7. #47
    Smooth Moperator techgnome's Avatar
    Join Date
    May 2002
    Posts
    34,532

    Re: Calculating exact time in Years, MOnths, Days

    Also... I'm not sure how you come to the conclusion that the results of Paul's code produces an error sequence... the values seem to reflect what I'd expect... ok... the second sequence isn't right... that's for sure... but the first sequence looks right to me... what's wrong with it?

    -tg
    * I don't respond to private (PM) requests for help. It's not conducive to the general learning of others.*
    * I also don't respond to friend requests. Save a few bits and don't bother. I'll just end up rejecting anyways.*
    * How to get EFFECTIVE help: The Hitchhiker's Guide to Getting Help at VBF - Removing eels from your hovercraft *
    * How to Use Parameters * Create Disconnected ADO Recordset Clones * Set your VB6 ActiveX Compatibility * Get rid of those pesky VB Line Numbers * I swear I saved my data, where'd it run off to??? *

  8. #48
    Powered By Medtronic dbasnett's Avatar
    Join Date
    Dec 2007
    Location
    Jefferson City, MO
    Posts
    9,754

    Re: Calculating exact time in Years, MOnths, Days

    Quote Originally Posted by techgnome View Post
    Also... I'm not sure how you come to the conclusion that the results of Paul's code produces an error sequence... the values seem to reflect what I'd expect... ok... the second sequence isn't right... that's for sure... but the first sequence looks right to me... what's wrong with it?

    -tg
    I should have said

    0 years, 0 months, 28 days between 1/31/2004 2/28/2004
    0 years, 0 months, 29 days between 1/31/2004 2/29/2004 <<<<<<<<<<<<<<<<<<<< s/b 1 month
    0 years, 0 months, 30 days between 1/31/2004 3/1/2004 <<<<<<<<<<<<<<<<<<<< s/b 1 month 1 day
    0 years, 1 months, 2 days between 1/31/2004 3/2/2004

    my mistake.
    My First Computer -- Documentation Link (RT?M) -- Using the Debugger -- Prime Number Sieve
    Counting Bits -- Subnet Calculator -- UI Guidelines -- >> SerialPort Answer <<

    "Those who use Application.DoEvents have no idea what it does and those who know what it does never use it." John Wein

  9. #49
    Hyperactive Member
    Join Date
    Apr 2011
    Location
    England
    Posts
    421

    Re: Calculating exact time in Years, MOnths, Days

    Hi guys,

    Here's my attempt at this:
    I tried a bunch of the Date Pairs from within this post and it seems to hold it's own.. so far!! Let me know if you can 'break' my function

    VB.NET Code:
    1. Public Class Form1
    2.  
    3.     Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    4.  
    5.         Dim Date1 As Date = DateTimePicker1.Value 'Lowest Date
    6.         Dim Date2 As Date = DateTimePicker2.Value 'Highest Date
    7.  
    8.         'Use DateDiff for months. (Check the days values to see if an extra month was added when not needed).
    9.         Dim Months As Long = DateDiff(DateInterval.Month, Date1, Date2)
    10.         If Date2.Day < Date1.Day Then Months -= 1
    11.         'Workout years from months
    12.         Dim Years As Long = Nothing
    13.         If Months >= 12 Then
    14.             Do Until Months < 12
    15.                 Years += 1
    16.                 Months -= 12
    17.             Loop
    18.         End If
    19.  
    20.         'Days
    21.         Dim Days As Long = Nothing
    22.         Dim FirstDay As Long = Date1.Day
    23.         Dim SecondDay As Long = Date2.Day
    24.  
    25.         Select Case FirstDay
    26.  
    27.             Case Is < SecondDay
    28.                 'If the Day from Date1 is less than that of Date2 then we know datediff worked out the months upto the month of Date2.
    29.                 'Therfore a simple subtraction will get the correct number of days.
    30.                 Days = SecondDay - FirstDay
    31.             Case Is > SecondDay
    32.                 'If Date1's day is greater than Date2's day then datediff looked at the months upto 1 month prior to Date2's month.
    33.                 'That being the case, work out how many days are in that month and count the days from Date1's Day to the end of that month.
    34.                 'Then we can just add the day value of Date2.
    35.                 Dim MonthBeforeLast As Integer = Date2.Month
    36.                 Dim Year As Integer = Date2.Year
    37.                 If MonthBeforeLast = 1 Then
    38.                     MonthBeforeLast = 12
    39.                     Year -= 1
    40.                 Else : MonthBeforeLast -= 1
    41.                 End If
    42.  
    43.                 Dim DaysLeftInMonth As Long = Date.DaysInMonth(Year, MonthBeforeLast) - Date1.Day
    44.  
    45.                 Days = Date2.Day + DaysLeftInMonth
    46.             Case Is = SecondDay
    47.                 'If the day values are equal then the number of days will always be 0
    48.                 Days = 0
    49.  
    50.         End Select
    51.  
    52.         'Display results
    53.         Label1.Text = String.Format("Years: {1}{0}Months: {2}{0}Days: {3}{0}", {vbCrLf, Years, Months, Days})
    54.     End Sub
    55.  
    56. End Class
    Hope this helps

    Jay
    Last edited by JayJayson; Jul 26th, 2011 at 09:22 AM. Reason: Fixed MonthBeforeLast. Didn't deduct 1 year if current month was Jan.

  10. #50
    Powered By Medtronic dbasnett's Avatar
    Join Date
    Dec 2007
    Location
    Jefferson City, MO
    Posts
    9,754

    Re: Calculating exact time in Years, MOnths, Days

    @jay

    0 years, 0 months, 29 days between 1/31/2004 2/29/2004
    0 years, 1 months, -1 days between 1/31/2004 3/1/2004 A D

    1 years, 0 months, 28 days between 1/31/2004 2/28/2005 C
    1 years, 1 months, -2 days between 1/31/2004 3/1/2005 A C
    1 years, 1 months, -1 days between 1/31/2004 3/2/2005 A C
    1 years, 1 months, 0 days between 1/31/2004 3/3/2005 C
    My First Computer -- Documentation Link (RT?M) -- Using the Debugger -- Prime Number Sieve
    Counting Bits -- Subnet Calculator -- UI Guidelines -- >> SerialPort Answer <<

    "Those who use Application.DoEvents have no idea what it does and those who know what it does never use it." John Wein

  11. #51
    Hyperactive Member
    Join Date
    Apr 2011
    Location
    England
    Posts
    421

    Re: Calculating exact time in Years, MOnths, Days

    That was a little quicker than I hoped

    I updated the function with something I had overlooked earlier. Can you test it for me now

    VB.NET Code:
    1. Public Class Form1
    2.  
    3.     Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    4.  
    5.         Dim Date1 As Date = DateTimePicker1.Value 'Lowest Date
    6.         Dim Date2 As Date = DateTimePicker2.Value 'Highest Date
    7.  
    8.         'Use DateDiff for months. (Check the days values to see if an extra month was added when not needed).
    9.         Dim Months As Long = DateDiff(DateInterval.Month, Date1, Date2)
    10.         If Date2.Day < Date1.Day Then Months -= 1
    11.         'Workout years from months
    12.         Dim Years As Long = Nothing
    13.         If Months >= 12 Then
    14.             Do Until Months < 12
    15.                 Years += 1
    16.                 Months -= 12
    17.             Loop
    18.         End If
    19.  
    20.         'Days
    21.         Dim Days As Long = Nothing
    22.         Dim FirstDay As Long = Date1.Day
    23.         Dim SecondDay As Long = Date2.Day
    24.  
    25.         If FirstDay > SecondDay And SecondDay = Date.DaysInMonth(Date2.Year, Date2.Month) And FirstDay = Date.DaysInMonth(Date1.Year, Date1.Month) Then
    26.             Months += 1
    27.             Days = 0
    28.         Else : Select Case FirstDay
    29.  
    30.                 Case Is < SecondDay
    31.                     'If the Day from Date1 is less than that of Date2 then we know datediff worked out the months upto the month of Date2.
    32.                     'Therfore a simple subtraction will get the correct number of days.
    33.                     Days = SecondDay - FirstDay
    34.                 Case Is > SecondDay
    35.                     'If Date1's day is greater than Date2's day then datediff looked at the months upto 1 month prior to Date2's month.
    36.                     'That being the case, work out how many days are in that month and count the days from Date1's Day to the end of that month.
    37.                     'Then we can just add the day value of Date2.
    38.                     Dim MonthBeforeLast As Integer = Date2.Month
    39.                     Dim Year As Integer = Date2.Year
    40.                     If MonthBeforeLast = 1 Then
    41.                         MonthBeforeLast = 12
    42.                         Year -= 1
    43.                     Else : MonthBeforeLast -= 1
    44.                     End If
    45.  
    46.                     'Edited code
    47.                     Dim DaysLeftInMonth As Long = Date.DaysInMonth(Year, MonthBeforeLast)
    48.                     If Date1.Day < DaysLeftInMonth Then DaysLeftInMonth -= Date1.Day Else  : DaysLeftInMonth = 0
    49.  
    50.                     Days = Date2.Day + DaysLeftInMonth
    51.                 Case Is = SecondDay
    52.                     'If the day values are equal then the number of days will always be 0
    53.                     Days = 0
    54.  
    55.             End Select
    56.         End If
    57.  
    58.         'Display results
    59.         Label1.Text = String.Format("Years: {1}{0}Months: {2}{0}Days: {3}{0}", {vbCrLf, Years, Months, Days})
    60.     End Sub
    61.  
    62. End Class
    Last edited by JayJayson; Jul 26th, 2011 at 10:06 AM. Reason: Edited to make last day in month to last day in month count as a month rather than x days.

  12. #52
    Powered By Medtronic dbasnett's Avatar
    Join Date
    Dec 2007
    Location
    Jefferson City, MO
    Posts
    9,754

    Re: Calculating exact time in Years, MOnths, Days

    0 years, 0 months, 29 days between 1/31/2004 2/29/2004
    0 years, 1 months, 1 days between 1/31/2004 3/1/2004 D

    0 years, 2 months, 30 days between 1/31/2005 4/30/2005
    0 years, 3 months, 1 days between 1/31/2005 5/1/2005 D

    What happened to x months 0 days?

    0 years, 5 months, 0 days between 2/29/2004 7/29/2004
    0 years, 5 months, 1 days between 2/29/2004 7/30/2004
    0 years, 5 months, 2 days between 2/29/2004 7/31/2004
    0 years, 5 months, 1 days between 2/29/2004 8/1/2004 D

    I posted how I was testing this in Post #42. (Hint)
    My First Computer -- Documentation Link (RT?M) -- Using the Debugger -- Prime Number Sieve
    Counting Bits -- Subnet Calculator -- UI Guidelines -- >> SerialPort Answer <<

    "Those who use Application.DoEvents have no idea what it does and those who know what it does never use it." John Wein

  13. #53
    Hyperactive Member
    Join Date
    Apr 2011
    Location
    England
    Posts
    421

    Re: Calculating exact time in Years, MOnths, Days

    I edited the code to fix the x months 0 days after making that last post

    Although I can see another problem with this now...
    Last edited by JayJayson; Jul 26th, 2011 at 10:26 AM.

  14. #54
    Hyperactive Member
    Join Date
    Apr 2011
    Location
    England
    Posts
    421

    Re: Calculating exact time in Years, MOnths, Days

    Right ok, I think my latest effort cracked it, fingers crossed

    VB.NET Code:
    1. Public Class Form1
    2.  
    3.     Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    4.  
    5.         Dim Date1 As Date = DateTimePicker1.Value 'Lowest Date
    6.         Dim Date2 As Date = DateTimePicker2.Value 'Highest Date
    7.  
    8.         'Use DateDiff for months. (Check the days values to see if an extra month was added when not needed).
    9.         Dim Months As Long = DateDiff(DateInterval.Month, Date1, Date2)
    10.         If Date2.Day < Date1.Day Then Months -= 1
    11.         'Workout years from months
    12.         Dim Years As Long = Nothing
    13.         If Months >= 12 Then
    14.             Do Until Months < 12
    15.                 Years += 1
    16.                 Months -= 12
    17.             Loop
    18.         End If
    19.  
    20.         'Days
    21.         Dim Days As Long = Nothing
    22.         Dim FirstDay As Long = Date1.Day
    23.         Dim SecondDay As Long = Date2.Day
    24.  
    25.         'Check for end of the month dates (to be handled differently)
    26.         If SecondDay = Date.DaysInMonth(Date2.Year, Date2.Month) And FirstDay = Date.DaysInMonth(Date1.Year, Date1.Month) Then
    27.             Days = 0
    28.         ElseIf FirstDay = Date.DaysInMonth(Date1.Year, Date1.Month) And SecondDay < Date.DaysInMonth(Date2.Year, Date2.Month) Then
    29.             If SecondDay >= FirstDay Then Months -= 1
    30.             Days = SecondDay
    31.         Else : Select Case FirstDay
    32.                 'Otherwise just calculate the days ourselves
    33.  
    34.                 Case Is < SecondDay
    35.                     'If the Day from Date1 is less than that of Date2 then we know datediff worked out the months upto the month of Date2.
    36.                     'Therfore a simple subtraction will get the correct number of days.
    37.                     Days = SecondDay - FirstDay
    38.                 Case Is > SecondDay
    39.                     'If Date1's day is greater than Date2's day then datediff looked at the months upto 1 month prior to Date2's month.
    40.                     'That being the case, work out how many days are in that month and count the days from Date1's Day to the end of that month.
    41.                     'Then we can just add the day value of Date2.
    42.                     Dim MonthBeforeLast As Integer = Date2.Month
    43.                     Dim Year As Integer = Date2.Year
    44.                     If MonthBeforeLast = 1 Then
    45.                         MonthBeforeLast = 12
    46.                         Year -= 1
    47.                     Else : MonthBeforeLast -= 1
    48.                     End If
    49.  
    50.                     Dim DaysLeftInMonth As Long = Date.DaysInMonth(Year, MonthBeforeLast) - Date1.Day
    51.  
    52.                     Days = Date2.Day + DaysLeftInMonth
    53.                 Case Is = SecondDay
    54.                     'If the day values are equal then the number of days will always be 0
    55.                     Days = 0
    56.  
    57.             End Select
    58.         End If
    59.  
    60.         'Display results
    61.         Label1.Text = String.Format("Years: {1}{0}Months: {2}{0}Days: {3}{0}", {vbCrLf, Years, Months, Days})
    62.     End Sub
    63.  
    64. End Class
    In any case, a better DateDiff function would be nice for the future

  15. #55
    Powered By Medtronic dbasnett's Avatar
    Join Date
    Dec 2007
    Location
    Jefferson City, MO
    Posts
    9,754

    Re: Calculating exact time in Years, MOnths, Days

    No. See post#42.
    My First Computer -- Documentation Link (RT?M) -- Using the Debugger -- Prime Number Sieve
    Counting Bits -- Subnet Calculator -- UI Guidelines -- >> SerialPort Answer <<

    "Those who use Application.DoEvents have no idea what it does and those who know what it does never use it." John Wein

  16. #56
    You don't want to know.
    Join Date
    Aug 2010
    Posts
    4,578

    Re: Calculating exact time in Years, MOnths, Days

    I don't know what's going on in this thread. If anything it's a painful proof of my assertion that my technique's the best

    I count 2 correct results: #2 and #8. After that, 9 attempts to do the same thing other ways were proposed (.paul.'s tried and failed at least 5 times!) I stand my my assertion that my "increment days and update counter" approach is the most accurate way to do this. Everyone who's tried another technique has failed. Do we really need to keep trying?

    There's an interesting discussion from #24-#34. Do we call 1/1/2005 to 1/1/2006 1 year exactly? If so, what about 1/1/2004-1/1/2005? 2004 was a leap year so that's technically 366 days. I say that's still 1 year, 0 days. Years are not 365 days every year. Some years they are 366 days. This is why you can only *approximate* days using years \ 365. Perhaps you might encounter some business logic that wants to call that span 1 year and 1 day; you can modify the algorithm accordingly. I don't think "I think you should have one day more for this leap year period" is a bug because in my eyes the behavior is correct.

    Quote Originally Posted by .paul. View Post
    afraid of a little competition???
    Hardly. DateDiff() is objectively awful. Just read the documentation; .NET has entire classes with less documentation than this one little function. The documentation also outlines situations where the return value isn't what you'd expect and in some cases is inaccurate. It takes as long to discover its pitfalls as it does to implement another solution. As further evidence, I present your failed attempts to use it. If an MS Community Contributor with 11k posts and dozens of tutorials under his belt can't use DateDiff() properly, what hope does the average developer have? This is why I retch when I see it.

    What I'm afraid of is giving users incorrect advice. Many people copy/paste forum examples and don't bother testing until deployment. That's a dumb approach to coding, but it's out there and odds are I'm going to be affected by it one day. I wanted to dismiss conversation of DateDiff() immediately because any errors involving DateDiff() are usually subtle and complex. Just look at the damage it's done: we've got nearly failed 10 attempts to wrangle DateDiff() into something predictable. You've got 11k posts to my 500 or so; that means you'll usually win the tiebreaker and your posts have more perceived authority. That makes it all the more tragic when your code is incorrect. I was also quite agitated that proposing new solutions implies the previous solutions have a flaw, though none have been raised against my code or dbasnett's. Your code's been attacked because it produces incorrect results. What's wrong with ours? It's odd there's so much discussion about a solved problem.

    DateDiff() was designed for a structured programming world. Even in structured programming, it's generally agreed functions with multiple behaviors are confusing. In the OOP world, it would be best represented as many methods of a class: MonthsBetween(), YearsBetween(), etc. I think the noda-time project has some functionality to do this that might present an API example. It's a shame they haven't found the time to write documentation so I could prove it.
    Last edited by Sitten Spynne; Jul 26th, 2011 at 11:48 AM.

  17. #57
    Powered By Medtronic dbasnett's Avatar
    Join Date
    Dec 2007
    Location
    Jefferson City, MO
    Posts
    9,754

    Re: Calculating exact time in Years, MOnths, Days

    As of now there aren't any correct answers, IMHO. Here are some of the results, using your code, from my test (post #42).

    0 years, 0 months, 29 days between 1/31/2004 2/29/2004
    0 years, 0 months, 30 days between 1/31/2004 3/1/2004
    0 years, 0 months, 31 days between 1/31/2004 3/2/2004
    0 years, 0 months, 32 days between 1/31/2004 3/3/2004 A
    0 years, 0 months, 33 days between 1/31/2004 3/4/2004 A


    The problems are boundaries (for everyone as far as I can tell).

    If you are in the Doctors office on 1/31/2004 and they say they will see you, in a month or in a year I take it to mean 2/29/2004 and 1/31/2005 respectively.

    If you are in the Doctors office on 1/31/2005 and they say they will see you, in a month or in a year I take it to mean 2/28/2005 and 1/31/2006 respectively.


    If anyone has issue with how I test, or how I define the boundaries, please let me know. This thread is painful proof that this is hard.
    My First Computer -- Documentation Link (RT?M) -- Using the Debugger -- Prime Number Sieve
    Counting Bits -- Subnet Calculator -- UI Guidelines -- >> SerialPort Answer <<

    "Those who use Application.DoEvents have no idea what it does and those who know what it does never use it." John Wein

  18. #58
    Hyperactive Member
    Join Date
    Apr 2011
    Location
    England
    Posts
    421

    Re: Calculating exact time in Years, MOnths, Days

    Using post #42 to test the output, I have tweaked my code to the following:

    VB.NET Code:
    1. Public Class Form1
    2.  
    3.     'Date1 = LowestDate, Date2 = Highest Date
    4.     Private Sub DateCompare(ByVal Date1 As Date, ByVal date2 As Date)
    5.  
    6.         'Get the Months first
    7.         Dim Months As Long = ((date2.Year * 12) + date2.Month) - ((Date1.Year * 12) + Date1.Month) - 1
    8.  
    9.         'Days
    10.         Dim Days As Long = Nothing
    11.         Dim FirstDay As Long = Date1.Day
    12.         Dim SecondDay As Long = date2.Day
    13.  
    14.         'Check for end of the month dates (to be handled differently)
    15.         If SecondDay = Date.DaysInMonth(date2.Year, date2.Month) And FirstDay = Date.DaysInMonth(Date1.Year, Date1.Month) Then
    16.             Months += 1
    17.             Days = 0
    18.         ElseIf FirstDay = Date.DaysInMonth(Date1.Year, Date1.Month) And SecondDay < Date.DaysInMonth(date2.Year, date2.Month) Then
    19.             If SecondDay >= FirstDay Then Months += 1
    20.             Days = SecondDay
    21.         Else : Select Case FirstDay
    22.                 'Otherwise just calculate the days ourselves
    23.  
    24.                 Case Is < SecondDay
    25.                     'If the Day from Date1 is less than that of Date2 then we know datediff worked out the months upto the month of Date2.
    26.                     'Therfore a simple subtraction will get the correct number of days.
    27.                     Days = SecondDay - FirstDay
    28.                 Case Is > SecondDay
    29.                     'If Date1's day is greater than Date2's day then datediff looked at the months upto 1 month prior to Date2's month.
    30.                     'That being the case, work out how many days are in that month and count the days from Date1's Day to the end of that month.
    31.                     'Then we can just add the day value of Date2.
    32.                     Dim MonthBeforeLast As Integer = date2.Month
    33.                     Dim Year As Integer = date2.Year
    34.                     If MonthBeforeLast = 1 Then
    35.                         MonthBeforeLast = 12
    36.                         Year -= 1
    37.                     Else : MonthBeforeLast -= 1
    38.                     End If
    39.  
    40.                     Dim DaysLeftInMonth As Long = Date.DaysInMonth(Year, MonthBeforeLast) - Date1.Day
    41.  
    42.                     Days = date2.Day + DaysLeftInMonth
    43.                 Case Is = SecondDay
    44.                     'If the day values are equal then the number of days will always be 0
    45.                     Days = 0
    46.  
    47.             End Select
    48.         End If
    49.  
    50.         'Workout years from months
    51.         Dim Years As Long = Nothing
    52.         If Months >= 12 Then
    53.             Do Until Months < 12
    54.                 Years += 1
    55.                 Months -= 12
    56.             Loop
    57.         End If
    58.  
    59.         'Display results
    60.         MsgBox(String.Format("Years: {1}{0}Months: {2}{0}Days: {3}{0}", {vbCrLf, Years, Months, Days}))
    61.  
    62.     End Sub
    63.  
    64. End Class
    As far as I can see it gets the desired result every time now

  19. #59
    Powered By Medtronic dbasnett's Avatar
    Join Date
    Dec 2007
    Location
    Jefferson City, MO
    Posts
    9,754

    Re: Calculating exact time in Years, MOnths, Days

    Here is the code to test with(crude I know). The last attempt by jay did not work.

    Code:
        Dim dp() As Date = New Date() {#1/31/2004#, #2/29/2004#, #1/31/2005#}
        Dim df() As Date = New Date() {#1/31/2009#, #2/28/2009#, #12/31/2009#}
    
        Private Sub Button2_Click(sender As System.Object, e As System.EventArgs) Handles Button2.Click
            Debug.WriteLine("")
            Debug.WriteLine("")
            Dim pastDate As DateTime
            Dim futureDate As DateTime
            Dim foo As New Age
            Dim sb As New System.Text.StringBuilder
    
            For Each pastDate In dp
                Debug.WriteLine("")
                For Each futureDate In df
                    Dim stopAt As Date = futureDate
                    futureDate = pastDate.AddDays(1)
                    Dim ly As Integer = 0
                    Dim ld As Integer = 0
                    Dim lm As Integer = 0
                    Dim isErr As String = ""
    
                    Do While futureDate <= stopAt
                        'checks
                        foo.DateFuture = futureDate
                        foo.DatePast = pastDate
    
                        'PUT YOUR CALL TO CALC HERE
                        foo = myAgeCalc.AgeInYearsMonthsDays()
                        '<<<<<<<<<
                        If foo.Days < 0 OrElse foo.Days > 31 Then
                            isErr &= "A "
                        End If
                        If foo.Months < 0 OrElse foo.Months > 11 Then
                            isErr &= "B "
                        End If
                        If foo.Years <> ly Then
                            If foo.Years = ly + 1 AndAlso foo.Months = 0 AndAlso foo.Days = 0 Then
                                ly = foo.Years
                                ld = 0
                                lm = 0
                                Debug.WriteLine("New Year")
                            Else
                                isErr &= "C "
                            End If
                        ElseIf foo.Months <> lm Then
                            If foo.Months = lm + 1 AndAlso foo.Days = 0 Then
                                lm = foo.Months
                                ld = 0
                            Else
                                isErr &= "D "
                                lm = foo.Months
                                ld = 0
                            End If
                        ElseIf foo.Days <> ld + 1 Then
                            isErr &= "D "
                            ld = foo.Days
                        Else
                            ld = foo.Days
                        End If
                        Debug.Write(String.Format("{0} years,  {1} months,  {2} days  between  {3} {4} ", foo.Years, foo.Months, foo.Days, pastDate.ToShortDateString, futureDate.ToShortDateString))
                        If isErr <> "" Then
                            Debug.WriteLine(isErr)
                            sb.AppendLine(isErr & pastDate.ToShortDateString & "  " & futureDate.ToShortDateString)
                            isErr = "" 'for error stop
                        Else
                            Debug.WriteLine("")
                        End If
                        futureDate = futureDate.AddDays(1)
                    Loop
                Next
            Next
            If sb.Length <> 0 Then
                Stop
                'My.Computer.Clipboard.SetText(sb.ToString)
            End If
        End Sub
    Code:
    Class Age
        Private _Years As Integer
        Public Property Years() As Integer
            Get
                Return Me._Years
            End Get
            Set(ByVal value As Integer)
                Me._Years = value
            End Set
        End Property
    
        Private _Months As Integer
        Public Property Months() As Integer
            Get
                Return Me._Months
            End Get
            Set(ByVal value As Integer)
                Me._Months = value
            End Set
        End Property
    
        Private _Days As Integer
        Public Property Days() As Integer
            Get
                Return Me._Days
            End Get
            Set(ByVal value As Integer)
                Me._Days = value
            End Set
        End Property
    
        Private _DatePast As DateTime
        Public Property DatePast() As DateTime
            Get
                Return Me._DatePast
            End Get
            Set(ByVal value As DateTime)
                Me._DatePast = value
                Me.setInterval()
            End Set
        End Property
    
        Private _DateFuture As DateTime
        Public Property DateFuture() As DateTime
            Get
                Return Me._DateFuture
            End Get
            Set(ByVal value As DateTime)
                Me._DateFuture = value
                Me.setInterval()
            End Set
        End Property
    
        Private Sub setInterval()
            Me._Interval = (Me.DateFuture - Me.DatePast).Duration
        End Sub
    
        Private _Interval As TimeSpan
        Public ReadOnly Property Interval() As TimeSpan
            Get
                Return Me._Interval
            End Get
        End Property
    End Class
    Last edited by dbasnett; Jul 26th, 2011 at 12:37 PM.
    My First Computer -- Documentation Link (RT?M) -- Using the Debugger -- Prime Number Sieve
    Counting Bits -- Subnet Calculator -- UI Guidelines -- >> SerialPort Answer <<

    "Those who use Application.DoEvents have no idea what it does and those who know what it does never use it." John Wein

  20. #60
    Hyperactive Member
    Join Date
    Apr 2011
    Location
    England
    Posts
    421

    Re: Calculating exact time in Years, MOnths, Days

    Just curious which dates it failed on?

    I will implement your test later as I am on my way out

  21. #61
    You don't want to know.
    Join Date
    Aug 2010
    Posts
    4,578

    Re: Calculating exact time in Years, MOnths, Days

    I feel like some of the "failed" cases are correct, but it depends on when you want to say "a month has elapsed."

    If it's 31 Jan 2004 and my doctor says I need an appointment scheduled in "a month", I wouldn't be surprised by an appointment anywhere between 28 Feb 2004 and anything in March 2004. The semantics are "roughly 30 days should elapse before you see me again." So 29 days is as accurate a description as 1 month, seeing as a month means anything from 28-31 days.

    That's not to say it's an unimportant distinction. My banking contracts speak either in terms of days or include an end date for vague concepts like "30-year mortgage". 90 days is unambiguous. 21 October 2042 is unambiguous. "2 months" can mean anything from 59 to 62 days; resolution of the exact period requires the start date. My credit card interest is determined by average daily balance, and every statement explicitly states the number of days in the billing period.

    This issue doesn't matter so much in less important scenarios. If my buddy asks for $10 and promises to pay me back "next month", I tend to assume that means some time in the next 30-60 days. Even something precise like "meet me in 5 minutes" has some assumed leeway. For these scenarios, simple estimations will work. "1 month from now" on January 31 can be Feb 28, Feb 29, Mar 1, or any of a handful of other days and most people won't bat an eye. Even if you're calculating a loan term, "1 year 6 months" is close enough for most people to properly visualize 3,842 days.

    So I'm not sure if it's ever worth the effort to work out all the kinks. If the software needs to be accurate, then all time spans should be reported in days; anything with years and months should be qualified as an estimate only (and optionally allow display of the exact number of days.) I think we've stumbled upon an explanation for why TimeSpan only goes up to days: days are the largest constant unit of time. (Technically, leap seconds take even that away!)

    It's definitely wrong that I calculate 32 days between 31 Jan 2004 and 3 Mar 2004. If the start date is on a 31 day, this error happens in many other places. I might be able to correct it, but I'd rather attack it from a different angle.

    Here's a second attempt that gets many boundary cases right; I'll include the beginnings of my test harness so you can see what I tested.
    Code:
    Function CalculateRange2(ByVal startDate As DateTime, ByVal endDate As DateTime) As TimePeriod
        Dim period As New TimePeriod()
    
        Dim currentDate As DateTime = startDate
    
        ' Add years until we're at the same year
        Do While currentDate.Year <> endDate.Year
            currentDate = currentDate.AddYears(1)
    
            If currentDate > endDate Then
                ' We overshot by some amount; take the year back and exit the loop. This happens when going from say
                ' 24 Feb 2003 to 1 Jan 2004.
                currentDate = currentDate.AddYears(-1)
                Exit Do
            Else
                ' We haven't overshot yet; add a year to the reckoning
                period.Years += 1
            End If
        Loop
    
        ' Add months until we're at the same month; it's possible we're the same month in a previous year
        Do While currentDate.Month <> endDate.Month OrElse currentDate.Year <> endDate.Year
            currentDate = currentDate.AddMonths(1)
    
            If currentDate > endDate Then
                ' Overshot; take the month back and exit.
                currentDate = currentDate.AddMonths(-1)
                Exit Do
            Else
                period.Months += 1
            End If
        Loop
    
        ' Add days until we're at the same date
        Do Until currentDate.Day = endDate.Day
            currentDate = currentDate.AddDays(1)
            period.Days += 1
        Loop
    
        Return period
    End Function
    Test cases (I'm sure you can figure out the TestCase class):
    Code:
    Dim testCases() As TestCase = {New TestCase(#2/28/2004#, #3/1/2004#, New TimePeriod() With {.Days = 2}),
                                   New TestCase(#2/28/2004#, #3/2/2004#, New TimePeriod() With {.Days = 3}),
                                   New TestCase(#2/28/2005#, #3/1/2005#, New TimePeriod() With {.Days = 1}),
                                   New TestCase(#2/28/2005#, #3/2/2005#, New TimePeriod() With {.Days = 2}),
                                   New TestCase(#1/28/2004#, #3/1/2004#, New TimePeriod() With {.Months = 1, .Days = 2}),
                                   New TestCase(#1/28/2005#, #3/1/2005#, New TimePeriod() With {.Months = 1, .Days = 1}),
                                   New TestCase(#2/28/2004#, #2/28/2005#, New TimePeriod() With {.Years = 1}),
                                   New TestCase(#2/28/2005#, #2/28/2006#, New TimePeriod() With {.Years = 1}),
                                   New TestCase(#1/31/2004#, #2/28/2004#, New TimePeriod() With {.Days = 30}),
                                   New TestCase(#1/31/2004#, #2/29/2004#, New TimePeriod() With {.Months = 1}),
                                   New TestCase(#1/31/2005#, #2/28/2005#, New TimePeriod() With {.Months = 1}),
                                   New TestCase(#12/15/2003#, #12/14/2004#, New TimePeriod() With {.Months = 11, .Days = 29}),
                                   New TestCase(#12/15/2003#, #12/16/2004#, New TimePeriod() With {.Years = 1, .Days = 1}),
                                   New TestCase(#12/15/2004#, #12/15/2005#, New TimePeriod() With {.Years = 1}),
                                   New TestCase(#12/15/2004#, #12/14/2005#, New TimePeriod() With {.Months = 11, .Days = 29}),
                                   New TestCase(#12/15/2004#, #12/16/2005#, New TimePeriod() With {.Years = 1, .Days = 1})
                                    }
    The most interesting test case in my opinion is 31 Jan 2004 to 28 Feb 2004. Technically, 1 month from the start date is 29 Feb 2004, so rather than the intuitive 1 month span it's actually a 30 day span. This is not true in 2005, where the distance between the two dates is 1 month again. Many people would argue this is *still* a distance of one month. I think both sides are right and business logic should be the deciding factor; if your boss wants it to be a month special case it to a month.

    I'm less confident this one is correct in all cases than my original because it's far more complicated. It took me about 45 minutes to get it right, whereas #2 took me 10 minutes. It looks like a reimagining of AgeInYearsMonthsDays() from your post #2, so it's hardly a new idea. And whether it is "correct" still depends on when 28 days counts as a month. I think the hardest part of verifying correctness is the sheer number of edge cases; I'm not sure if I've covered all of them yet.

    On #57: it's complicated and less intuitive than an incremental approach; that makes me superstitious it's got hidden errors. My guess is it started simple, then lots of special cases got added. That's why I made a different attempt rather than tweaking #2. Incremental approaches are easier to understand and thus easier to maintain. Others might not share my opinion, but I don't like math-based approach to date differencing. Been burned too many times. I'm too lazy to throw test cases at it; I'm out of break time today.

  22. #62
    eXtreme Programmer .paul.'s Avatar
    Join Date
    May 2007
    Location
    Chelmsford UK
    Posts
    25,464

    Re: Calculating exact time in Years, MOnths, Days

    @dBasnett

    what about this:

    Start: 23/08/2008
    End: 22/07/2010

    Years: 1
    Months: 10
    Days: 28

    should be 1 yr, 10 months, 29 days

    but allowing for the 366 day year in 2008 it's wrong.???

  23. #63
    eXtreme Programmer .paul.'s Avatar
    Join Date
    May 2007
    Location
    Chelmsford UK
    Posts
    25,464

    Re: Calculating exact time in Years, MOnths, Days

    Quote Originally Posted by Sitten Spynne View Post
    I don't know what's going on in this thread. If anything it's a painful proof of my assertion that my technique's the best

    Quote Originally Posted by dbasnett View Post
    As of now there aren't any correct answers, IMHO.
    it'd help if Microsoft had a consensus of opinion on this. their methods are all over the place...

  24. #64
    PowerPoster Evil_Giraffe's Avatar
    Join Date
    Aug 2002
    Location
    Suffolk, UK
    Posts
    2,555

    Re: Calculating exact time in Years, MOnths, Days

    Quote Originally Posted by Sitten Spynne View Post
    I think the noda-time project has some functionality to do this that might present an API example. It's a shame they haven't found the time to write documentation so I could prove it.
    It's also a shame they haven't reached a stable release either, as that precludes it from most production code. My first thought yesterday when reading this thread was "Ah! Use Noda Time!", only to find they're still a little way off a 1.0 release.

    Quote Originally Posted by Sitten Spynne View Post
    I think both sides are right and business logic should be the deciding factor; if your boss wants it to be a month special case it to a month.
    I'm slightly disappointed it took 60 posts before someone threw in that phrase. The requirements for this seem very simple but they hide a huge number of edge and corner cases where we need clarification on the desired behaviour. Yes, I have an idea of what makes sense to me, but that doesn't mean my idea of the obvious behaviour in those cases is correct for this application. (And as to why I haven't posted the code for my answer? I got bored after the fifth test case )

    The real answer here, IMO, is "That's hard to get correct in all cases, are you sure you can't just have the number of days, or just display the start and end date?"

  25. #65
    Hyperactive Member
    Join Date
    Apr 2011
    Location
    England
    Posts
    421

    Re: Calculating exact time in Years, MOnths, Days

    I have taken a leaf out of SittenSpynne's book and rewritten my code from the beggining. Although it is mostly the same, it helped me find a bug and lay the code out in an easier to follow way.

    I've tested it with a bunch of dates and so far it seems to be working as it should be (or at least according to the 'rules' laid out by dbasnett, which I am onboard with).

    Let's hope none of you manage to find a date pair to ruin my moment of self gratifaction

    Here's the code:
    VB.NET Code:
    1. Public Class Form1
    2.  
    3.     'Date1 is the lowest date, Date2 is the highest date
    4.     Private Sub DateCompare(ByVal Date1 As Date, ByVal Date2 As Date)
    5.  
    6.         Dim Days As Integer = Nothing
    7.         Dim Months As Integer = Nothing
    8.         Dim Years As Integer = Nothing
    9.  
    10.         'Convert Date1/Date2 months and years into months.
    11.         Dim Date1Months As Integer = Date1.Year * 12 + Date1.Month
    12.         Dim Date2Months As Integer = Date2.Year * 12 + Date2.Month
    13.         'Get the number of Months between the two dates. Subtract 1 (we will add this back later where necessary)
    14.         Months = Date2Months - Date1Months - 1
    15.  
    16.         'See how many days are within the Month Date1/Date2 reside.
    17.         Dim DaysInDate1Month As Integer = Date.DaysInMonth(Date1.Year, Date1.Month)
    18.         Dim DaysInDate2Month As Integer = Date.DaysInMonth(Date2.Year, Date2.Month)
    19.  
    20.  
    21.         If Date1.Day = DaysInDate1Month And Date2.Day = DaysInDate2Month Then
    22.             'If Both Date1 and Date2 occur on the LastDayOfTheMonth.
    23.  
    24.             'We count this as a month rather than x amount of days.
    25.             'Therefore add 1 to Months and set Days to zero.
    26.             'nb: We subtracted a month when we first grabbed the number of Months. Add it back here.
    27.             Months += 1
    28.             Days = 0
    29.         ElseIf Date1.Day = DaysInDate1Month And Date2.Day < DaysInDate2Month Then
    30.             'If Date1 occur's on the LastDayOfTheMonth but Date2 resides on a day prior to the end of it's month.
    31.  
    32.             'We know the number of Days between the two dates will be the number of Days in Date2.
    33.             Days = Date2.Day
    34.         Else
    35.             'If Neither Date1 or Date2 occur on the LastDayOfTheMonth then we can do a day count ourselves.
    36.             Select Case Date1.Day
    37.  
    38.                 Case Is < Date2.Day
    39.                     'If Date2's Day is higher then Date1's Day then the 'Months' value will represent the number of months upto the Month that Date2 resides.
    40.  
    41.                     'The number of days will therefore be the difference between Date1/Date2's Day values.
    42.                     Days = Date2.Day - Date1.Day
    43.  
    44.                     'nb: We subtracted a month when we first grabbed the number of Months. Add it back here.
    45.                     Months += 1
    46.                 Case Is > Date2.Day
    47.                     'If Date2's Day is lower then Date1's Day then the 'Months' value will represent the number of months upto the Month prior to that which Date2 resides.
    48.  
    49.                     'First we need to find out the month prior to Date2's month value.
    50.                     Dim MonthBeforeDate2 As Integer = Date2.Month
    51.                     'If Date2 occurs in January, then we will also need to use the previous year in our calculation.
    52.                     Dim Date2Year As Integer = Date2.Year
    53.                     If MonthBeforeDate2 = 1 Then
    54.                         MonthBeforeDate2 = 12
    55.                         Date2Year -= 1
    56.                     Else : MonthBeforeDate2 -= 1
    57.                     End If
    58.  
    59.                     'Next we will see how many days occur between the value of Date1's Day and the end of the month prior to Date2.
    60.                     Dim DaysLeftInMonthBeforeDate2 As Long = Date.DaysInMonth(Date2Year, MonthBeforeDate2) - Date1.Day
    61.  
    62.                     'Finally we can add the number of Days in Date2.
    63.                     Days = DaysLeftInMonthBeforeDate2 + Date2.Day
    64.                 Case Is = Date2.Day
    65.                     'If the Day value in Date1/Date2 matches.
    66.  
    67.                     'nb: We subtracted a month when we first grabbed the number of Months. Add it back here.
    68.                     Months += 1
    69.             End Select
    70.  
    71.         End If
    72.  
    73.         'The last step is to work out the number of Years. We can work this out from the 'Months'.
    74.         'nb: We left this until last because there may have been a few neccessary changes to the Months value along the way.
    75.         If Months >= 12 Then
    76.             Do Until Months < 12
    77.                 Years += 1
    78.                 Months -= 12
    79.             Loop
    80.         End If
    81.  
    82.         'Now just format the result:
    83.         MsgBox(String.Format("Years: {1}{0}Months: {2}{0}Days: {3}", {vbCrLf, Years, Months, Days}))
    84.  
    85.     End Sub
    86.  
    87. End Class

  26. #66
    eXtreme Programmer .paul.'s Avatar
    Join Date
    May 2007
    Location
    Chelmsford UK
    Posts
    25,464

    Re: Calculating exact time in Years, MOnths, Days

    Quote Originally Posted by jay20aiii View Post
    I have taken a leaf out of SittenSpynne's book and rewritten my code from the beggining.
    i haven't tested your code, but if you had taken a leaf out of SittenSpynne's book you'd have just written an essay + no code

  27. #67
    Hyperactive Member
    Join Date
    Apr 2011
    Location
    England
    Posts
    421

    Re: Calculating exact time in Years, MOnths, Days

    I could paste some Wikipedia excerpts if that would help

  28. #68
    PowerPoster Evil_Giraffe's Avatar
    Join Date
    Aug 2002
    Location
    Suffolk, UK
    Posts
    2,555

    Re: Calculating exact time in Years, MOnths, Days

    Quote Originally Posted by .paul. View Post
    i haven't tested your code, but if you had taken a leaf out of SittenSpynne's book you'd have just written an essay + no code
    I think a leaf from SittenSpynne's book would be more like "post some pretty robust code, then discuss why it's robust and the thought processes behind making it robust so that next time, the people asking for help might be able to get a bit further by themselves."

    Compare that with a leaf from another person's book:
    "Post some code that seems to work when given a cursory test with some really easy values. When it is pointed out the code has flaws, tweak the code to handle each bug. Hope and pray you don't introduce new bugs with the changes, or regress previously working cases. Give up and then try and suggest SittenSpynne is the one posturing."

    I know whose book I'd rather be reading.

  29. #69
    eXtreme Programmer .paul.'s Avatar
    Join Date
    May 2007
    Location
    Chelmsford UK
    Posts
    25,464

    Re: Calculating exact time in Years, MOnths, Days

    Quote Originally Posted by Evil_Giraffe View Post
    I think a leaf from SittenSpynne's book would be more like "post some pretty robust code, then discuss why it's robust and the thought processes behind making it robust so that next time, the people asking for help might be able to get a bit further by themselves."

    Compare that with a leaf from another person's book:
    "Post some code that seems to work when given a cursory test with some really easy values. When it is pointed out the code has flaws, tweak the code to handle each bug. Hope and pray you don't introduce new bugs with the changes, or regress previously working cases. Give up and then try and suggest SittenSpynne is the one posturing."

    I know whose book I'd rather be reading.
    hmmm...

  30. #70
    eXtreme Programmer .paul.'s Avatar
    Join Date
    May 2007
    Location
    Chelmsford UK
    Posts
    25,464

    Re: Calculating exact time in Years, MOnths, Days

    Quote Originally Posted by Evil_Giraffe View Post
    I think a leaf from SittenSpynne's book would be more like "post some pretty robust code, then discuss why it's robust and the thought processes behind making it robust so that next time, the people asking for help might be able to get a bit further by themselves."

    Compare that with a leaf from another person's book:
    "Post some code that seems to work when given a cursory test with some really easy values. When it is pointed out the code has flaws, tweak the code to handle each bug. Hope and pray you don't introduce new bugs with the changes, or regress previously working cases. Give up and then try and suggest SittenSpynne is the one posturing."

    I know whose book I'd rather be reading.
    you should obviously be made aware that SittenSpynne's code doesn't work reliably either...

    check the history. my reference to SittenSpynne's essays was based on his past performance.

  31. #71
    eXtreme Programmer .paul.'s Avatar
    Join Date
    May 2007
    Location
    Chelmsford UK
    Posts
    25,464

    Re: Calculating exact time in Years, MOnths, Days

    @Evil Giraffe. see post#62

  32. #72
    PowerPoster Evil_Giraffe's Avatar
    Join Date
    Aug 2002
    Location
    Suffolk, UK
    Posts
    2,555

    Re: Calculating exact time in Years, MOnths, Days

    @.paul.

    Apologies, my last post was incredibly snarky towards you, and it looks like it's derailed the thread into mud-slinging - for which I apologise to everyone involved. If you want to continue that discussion (I'm not particularly keen to, but since I started it...) PM me and we'll take it off-thread.

    Sorry again, everyone.

  33. #73
    Hyperactive Member
    Join Date
    Apr 2011
    Location
    England
    Posts
    421

    Re: Calculating exact time in Years, MOnths, Days

    I managed to find a date that makes my code in post #64 redundant. Better to find the bug myself I guess... but way to soil in my own sand.

    Back to the drawing board I guess

  34. #74
    Powered By Medtronic dbasnett's Avatar
    Join Date
    Dec 2007
    Location
    Jefferson City, MO
    Posts
    9,754

    Re: Calculating exact time in Years, Months, Days

    What sitten had to say was needed for perspective. This thread was started with this, "I am trying to calculate the exact amount of time in Years, Months and Days between 2 date values." We have all found out how incredibly hard to know what that means, and how hard it is to do with any consistency.

    Personal attacks don't have a place here, no matter how frustrated you are.
    My First Computer -- Documentation Link (RT?M) -- Using the Debugger -- Prime Number Sieve
    Counting Bits -- Subnet Calculator -- UI Guidelines -- >> SerialPort Answer <<

    "Those who use Application.DoEvents have no idea what it does and those who know what it does never use it." John Wein

  35. #75
    Powered By Medtronic dbasnett's Avatar
    Join Date
    Dec 2007
    Location
    Jefferson City, MO
    Posts
    9,754

    Re: Calculating exact time in Years, MOnths, Days

    Success!

    0 years, 0 months, 28 days between 2/29/2004 3/28/2004
    0 years, 1 months, 0 days between 2/29/2004 3/29/2004

    0 years, 1 months, 30 days between 2/29/2004 4/28/2004
    0 years, 2 months, 0 days between 2/29/2004 4/29/2004

    0 years, 11 months, 30 days between 2/29/2004 2/28/2005
    1 years, 0 months, 0 days between 2/29/2004 3/1/2005

    0 years, 0 months, 28 days between 1/31/2004 2/28/2004
    0 years, 1 months, 0 days between 1/31/2004 2/29/2004

    0 years, 2 months, 29 days between 1/31/2004 4/29/2004
    0 years, 3 months, 0 days between 1/31/2004 4/30/2004

    0 years, 1 months, 0 days between 1/31/2005 2/28/2005
    0 years, 1 months, 1 days between 1/31/2005 3/1/2005

    2 years, 0 months, 29 days between 1/29/2005 2/27/2007
    2 years, 1 months, 0 days between 1/29/2005 2/28/2007
    2 years, 1 months, 1 days between 1/29/2005 3/1/2007

    3 years, 0 months, 30 days between 1/29/2005 2/28/2008
    3 years, 1 months, 0 days between 1/29/2005 2/29/2008
    Last edited by dbasnett; Jul 27th, 2011 at 07:47 AM.
    My First Computer -- Documentation Link (RT?M) -- Using the Debugger -- Prime Number Sieve
    Counting Bits -- Subnet Calculator -- UI Guidelines -- >> SerialPort Answer <<

    "Those who use Application.DoEvents have no idea what it does and those who know what it does never use it." John Wein

  36. #76
    Hyperactive Member
    Join Date
    Apr 2011
    Location
    England
    Posts
    421

    Re: Calculating exact time in Years, MOnths, Days

    congrats dbasnett, can we see the code your referring to?

    The main reason I have been following this thread is because I made a datediff function years ago to work out my son's age in Years, Months, Weeks, Days and would like to update it with a more robust version

  37. #77
    Powered By Medtronic dbasnett's Avatar
    Join Date
    Dec 2007
    Location
    Jefferson City, MO
    Posts
    9,754

    Re: Calculating exact time in Years, MOnths, Days

    Quote Originally Posted by jay20aiii View Post
    congrats dbasnett, can we see the code your referring to?

    The main reason I have been following this thread is because I made a datediff function years ago to work out my son's age in Years, Months, Weeks, Days and would like to update it with a more robust version
    As you might imagine the code is a mess at this point. Let me clean it up and I'll post it.

    Weeks!
    My First Computer -- Documentation Link (RT?M) -- Using the Debugger -- Prime Number Sieve
    Counting Bits -- Subnet Calculator -- UI Guidelines -- >> SerialPort Answer <<

    "Those who use Application.DoEvents have no idea what it does and those who know what it does never use it." John Wein

  38. #78
    Powered By Medtronic dbasnett's Avatar
    Join Date
    Dec 2007
    Location
    Jefferson City, MO
    Posts
    9,754

    Re: Calculating exact time in Years, MOnths, Days

    Still needs work but the code is here

    http://www.vbforums.com/showpost.php...40&postcount=2

    Sitten was right about keeping the date manipulation as simple as possible.
    My First Computer -- Documentation Link (RT?M) -- Using the Debugger -- Prime Number Sieve
    Counting Bits -- Subnet Calculator -- UI Guidelines -- >> SerialPort Answer <<

    "Those who use Application.DoEvents have no idea what it does and those who know what it does never use it." John Wein

  39. #79
    Hyperactive Member
    Join Date
    Apr 2011
    Location
    England
    Posts
    421

    Re: Calculating exact time in Years, MOnths, Days

    Cool, I will take a look over it

    I think I have just managed to irradicate the last of the issues with my code. So here it is as well. A bit of competition never hurts and hopefully that will make 2 working DateDiff functions!

    VB.NET Code:
    1. Public Class Form1
    2.  
    3.     'Date1 is the lowest date, Date2 is the highest date
    4.     Private Sub DateCompare(ByVal Date1 As Date, ByVal Date2 As Date)
    5.  
    6.         Dim Days As Integer = Nothing
    7.         Dim Months As Integer = Nothing
    8.         Dim Years As Integer = Nothing
    9.  
    10.         'Convert Date1/Date2 months and years into months.
    11.         Dim Date1Months As Integer = Date1.Year * 12 + Date1.Month
    12.         Dim Date2Months As Integer = Date2.Year * 12 + Date2.Month
    13.         'Get the number of Months between the two dates. Subtract 1 (we will add this back later where necessary)
    14.         Months = Date2Months - Date1Months - 1
    15.  
    16.         'See how many days are within the Month Date1/Date2 reside.
    17.         Dim DaysInDate1Month As Integer = Date.DaysInMonth(Date1.Year, Date1.Month)
    18.         Dim DaysInDate2Month As Integer = Date.DaysInMonth(Date2.Year, Date2.Month)
    19.  
    20.  
    21.         If Date1.Day = DaysInDate1Month And Date2.Day = DaysInDate2Month Then
    22.             'If Both Date1 and Date2 occur on the LastDayOfTheMonth.
    23.  
    24.             'We count this as a month rather than x amount of days.
    25.             'Therefore add 1 to Months and set Days to zero.
    26.             'nb: We subtracted a month when we first grabbed the number of Months. Add it back here.
    27.             Months += 1
    28.             Days = 0
    29.         ElseIf Date1.Day = DaysInDate1Month And Date2.Day < DaysInDate2Month Then
    30.             'If Date1 occur's on the LastDayOfTheMonth but Date2 resides on a day prior to the end of it's month.
    31.  
    32.             'We know the number of Days between the two dates will be the number of Days in Date2.
    33.             Days = Date2.Day
    34.         Else
    35.             'If Neither Date1 or Date2 occur on the LastDayOfTheMonth then we can do a day count ourselves.
    36.             Select Case Date1.Day
    37.  
    38.                 Case Is < Date2.Day
    39.                     'If Date2's Day is higher then Date1's Day then the 'Months' value will represent the number of months upto the Month that Date2 resides.
    40.  
    41.                     'The number of days will therefore be the difference between Date1/Date2's Day values.
    42.                     Days = Date2.Day - Date1.Day
    43.  
    44.                     'nb: We subtracted a month when we first grabbed the number of Months. Add it back here.
    45.                     Months += 1
    46.                 Case Is > Date2.Day
    47.                     'If Date2's Day is lower then Date1's Day then the 'Months' value will represent the number of months upto the Month prior to that which Date2 resides.
    48.  
    49.                     'First we need to find out the month prior to Date2's month value.
    50.                     Dim MonthBeforeDate2 As Integer = Date2.Month
    51.                     'If Date2 occurs in January, then we will also need to use the previous year in our calculation.
    52.                     Dim Date2Year As Integer = Date2.Year
    53.                     If MonthBeforeDate2 = 1 Then
    54.                         MonthBeforeDate2 = 12
    55.                         Date2Year -= 1
    56.                     Else : MonthBeforeDate2 -= 1
    57.                     End If
    58.  
    59.                     'If there are more days in Date1 than occur in the month prior to Date2 then we want to avoid calculating the days that remain in that month.
    60.                     'As that would lead to a neagtive value.
    61.                     If Date1.Day > Date.DaysInMonth(Date2Year, MonthBeforeDate2) Then
    62.                         'In this case we only need the number of days in Date2.
    63.                         Days = Date2.Day
    64.                     Else
    65.                         'Otherwise next we will see how many days occur between the value of Date1's Day and the end of the month prior to Date2.
    66.                         Dim DaysLeftInMonthBeforeDate2 As Long = Date.DaysInMonth(Date2Year, MonthBeforeDate2) - Date1.Day
    67.  
    68.                         'Finally we can add the number of Days in Date2.
    69.                         Days = DaysLeftInMonthBeforeDate2 + Date2.Day
    70.                     End If
    71.  
    72.                 Case Is = Date2.Day
    73.                     'If the Day value in Date1/Date2 matches.
    74.  
    75.                     'nb: We subtracted a month when we first grabbed the number of Months. Add it back here.
    76.                     Months += 1
    77.             End Select
    78.  
    79.         End If
    80.  
    81.         'The last step is to work out the number of Years. We can work this out from the 'Months'.
    82.         'nb: We left this until last because there may have been a few neccessary changes to the Months value along the way.
    83.         If Months >= 12 Then
    84.             Do Until Months < 12
    85.                 Years += 1
    86.                 Months -= 12
    87.             Loop
    88.         End If
    89.  
    90.         'Now just format the result:
    91.         MsgBox(String.Format("Years: {1}{0}Months: {2}{0}Days: {3}", {vbCrLf, Years, Months, Days}))
    92.  
    93.     End Sub
    94.  
    95. End Class
    Now, about those weeks...

  40. #80
    Powered By Medtronic dbasnett's Avatar
    Join Date
    Dec 2007
    Location
    Jefferson City, MO
    Posts
    9,754

    Re: Calculating exact time in Years, MOnths, Days

    Quote Originally Posted by jay20aiii View Post
    Cool, I will take a look over it ....Now, about those weeks...
    When you look it over you might find weeks.

    BTW - IMHO this is an error

    0 years, 0 months, 30 days between 1/29/2005 2/28/2005
    0 years, 1 months, 1 days between 1/29/2005 3/1/2005
    Last edited by dbasnett; Jul 27th, 2011 at 09:30 AM.
    My First Computer -- Documentation Link (RT?M) -- Using the Debugger -- Prime Number Sieve
    Counting Bits -- Subnet Calculator -- UI Guidelines -- >> SerialPort Answer <<

    "Those who use Application.DoEvents have no idea what it does and those who know what it does never use it." John Wein

Page 2 of 3 FirstFirst 123 LastLast

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width