473,397 Members | 1,949 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,397 software developers and data experts.

Calculate age / age next birthday from date of birth without using DateDiff solution

I hit on this problem converting a VB.NET insurance application to C#.
Age next birthday calculated from date of birth is often needed in
insurance premium calculations.
Originally done using DateDiff in VB.NET which is only available in C#
if you don't mind linking in Microsoft.VisualBasic.dll to your C#
application.
I wanted to avoid this so set about a pure C# solution which uses a
combination of TimeSpan in whole days and the
System.Globalizarion.Calendar class GetDaysInYear() function to work
it out.
The added advantage here over DateDiff is this function should work
with all the different System.Globalization.Calendar types (Japanese
etc.), however I have only tested it with GregorianCalendar.

Here is the C# source code which includes a console application test
harness.
To get "Age" rather than "Age next birthday" just subtract 1 from this
result (sorry for pointing out the obvious!)

<code>
using System;

namespace WorkbenchCSConsole
{
/// <summary>
/// Summary description for AgeNextBirtdatCalculator.
/// </summary>
class AgeNextBirtdatCalculator
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main(string[] args)
{
//
// Test harness for AgeNextBirthday function
//
int AgeNextBirthday;

DateTime DOB;
DateTime DateNow;
System.Globalization.Calendar MyCalendar = new
System.Globalization.GregorianCalendar(); // should work with other
calendars
DateNow = DateTime.Now;
System.Console.WriteLine("Calendar independant date of birth to
age NEXT birtday function (commonly required in the insurance
industry) for C# written by Adrian Hilder, Camdaw Limited
www.camdaw.net. You are free to use and distribute this function in
your applications, you may not sell it for profit as a stand alone
utility without prior consent from Camdaw Limited.\nThis function is
provided as is in the hope it is usefull with no warrantee of any
kind. You should test this function to your satisfaction before using
it in your applications.\nIf you do find any faults please tell
me!\nIf you use this please tell me, I'm interested to know if anyone
uses it (it was about 3 hours work). (contact details at
www.camdaw.net)\n\n");

DOB = DateTime.MinValue;
DOB = DOB.AddYears(1970-1);
DOB = DOB.AddMonths(DateNow.Month-1);
DOB = DOB.AddDays(DateNow.Day-2);
System.Console.WriteLine("Calendar type: " +
MyCalendar.ToString() + "\n");

System.Console.WriteLine("Testing with todays date " +
DateNow.Day + "/" + DateNow.Month + "/" + DateNow.Year + "
(dd/mm/yyyy)\n");

Console.WriteLine("Test with DOB yesterdays date in 1970");
System.Console.WriteLine("DOB entered: " + DOB.Day + "/" +
DOB.Month + "/" + DOB.Year + " (dd/mm/yyyy)");
AgeNextBirthday = DOBToAgeNextBirthday(DOB, MyCalendar);
System.Console.WriteLine("AgeNextBirthdayYears=" +
AgeNextBirthday + "\n");

Console.WriteLine("Test with DOB tommorrows date in 1970");
DOB = DateTime.MinValue;
DOB = DOB.AddYears(1970-1);
DOB = DOB.AddMonths(DateNow.Month-1);
DOB = DOB.AddDays(DateNow.Day);

System.Console.WriteLine("DOB entered: " + DOB.Day + "/" +
DOB.Month + "/" + DOB.Year + " (dd/mm/yyyy)");
AgeNextBirthday = DOBToAgeNextBirthday(DOB, MyCalendar);
System.Console.WriteLine("AgeNextBirthdayYears=" +
AgeNextBirthday + "\n");

Console.WriteLine("Test with DOB this day in 1970");
DOB = DateTime.MinValue;
DOB = DOB.AddYears(1970-1);
DOB = DOB.AddMonths(DateNow.Month-1);
DOB = DOB.AddDays(DateNow.Day-1);

System.Console.WriteLine("DOB entered: " + DOB.Day + "/" +
DOB.Month + "/" + DOB.Year + " (dd/mm/yyyy) ... Happy Birthday!");
AgeNextBirthday = DOBToAgeNextBirthday(DOB, MyCalendar);
System.Console.WriteLine("AgeNextBirthdayYears=" +
AgeNextBirthday + "\n");

while(!(MyCalendar.IsLeapYear(DateNow.Year)))
DateNow = DateNow.AddYears(1);

System.Console.WriteLine("Testing with the next leap year date "
+ DateNow.Day + "/" + DateNow.Month + "/" + DateNow.Year + "
(dd/mm/yyyy)\n");
System.Console.WriteLine("Note: this DOBToAgeNextBirthday
function and test harness was written 3rd August 2004, which was a
leap year.");

Console.WriteLine("Test with DOB yesterdays date in 1970");
System.Console.WriteLine("DOB entered: " + DOB.Day + "/" +
DOB.Month + "/" + DOB.Year + " (dd/mm/yyyy)");
AgeNextBirthday = DOBToAgeNextBirthday(DOB, MyCalendar);
System.Console.WriteLine("AgeNextBirthdayYears=" +
AgeNextBirthday + "\n");

Console.WriteLine("Test with DOB tommorrows date in 1970");
DOB = DateTime.MinValue;
DOB = DOB.AddYears(1970-1);
DOB = DOB.AddMonths(DateNow.Month-1);
DOB = DOB.AddDays(DateNow.Day);

System.Console.WriteLine("DOB entered: " + DOB.Day + "/" +
DOB.Month + "/" + DOB.Year + " (dd/mm/yyyy)");
AgeNextBirthday = DOBToAgeNextBirthday(DOB, MyCalendar);
System.Console.WriteLine("AgeNextBirthdayYears=" +
AgeNextBirthday + "\n");

Console.WriteLine("Test with DOB this day in 1970");
DOB = DateTime.MinValue;
DOB = DOB.AddYears(1970-1);
DOB = DOB.AddMonths(DateNow.Month-1);
DOB = DOB.AddDays(DateNow.Day-1);

System.Console.WriteLine("DOB entered: " + DOB.Day + "/" +
DOB.Month + "/" + DOB.Year + " (dd/mm/yyyy) ... Happy Birthday!");
AgeNextBirthday = DOBToAgeNextBirthday(DOB, MyCalendar);
System.Console.WriteLine("AgeNextBirthdayYears=" +
AgeNextBirthday + "\n");

}

private static int DOBToAgeNextBirthday(DateTime DOB,
System.Globalization.Calendar ThisCalendar)
{
int DaysPassedInYear;
DateTime Now;
int YearIndex;
int DiffDays;

Now = DateTime.Now;
DiffDays = (int)Now.Subtract(DOB).TotalDays;
YearIndex = 0;
DaysPassedInYear = CalcDaysPassedInYear(Now, DOB, YearIndex,
ThisCalendar);
while(DiffDays > DaysPassedInYear)
{
DiffDays = DiffDays - DaysPassedInYear;
YearIndex++; // on to next year
DaysPassedInYear = CalcDaysPassedInYear(Now, DOB, YearIndex,
ThisCalendar);
}
// Now handle last part year
if (DiffDays > 0) // if still some days to account for
{
int DaysPassedToBirthday;
DaysPassedInYear = CalcDaysPassedInYear(Now, DOB, -1,
ThisCalendar);
DaysPassedToBirthday =
CalcDaysPassedInYear(DOB.AddYears(YearIndex), DOB, -1, ThisCalendar);
if (DaysPassedInYear >= DaysPassedToBirthday)
YearIndex++; // birthday has passed this year
}
return YearIndex;
}

private static int CalcDaysPassedInYear(DateTime Now, DateTime
DOB, int YearIndex, System.Globalization.Calendar ThisCalendar)
{
DateTime PartYearStartDate; // 1st Jan <PartYear>
int YearDaysPassed;
int DaysPassedInYear;
if (YearIndex == 0) // days in starting (DOB) part year
{
PartYearStartDate = DateTime.MinValue;
PartYearStartDate = PartYearStartDate.AddYears(DOB.Year-1);
YearDaysPassed =
(int)DOB.Subtract(PartYearStartDate).TotalDays;
DaysPassedInYear = ThisCalendar.GetDaysInYear(DOB.Year) -
YearDaysPassed;
}
else if (YearIndex == -1) // -1 used to indicate last year in
period, i.e. Now.Year
{
PartYearStartDate = DateTime.MinValue;
PartYearStartDate.AddYears(Now.Year);
DaysPassedInYear =
(int)Now.Subtract(PartYearStartDate).TotalDays;
}
else // a year within the period
{
DaysPassedInYear = ThisCalendar.GetDaysInYear(DOB.Year +
YearIndex);
}
return DaysPassedInYear;
}
}
}
</code>
Nov 16 '05 #1
7 15451
Adrian,

I am curious, why are you against linking to Microsoft.VisualBasic.dll?
It's distributed as part of the framework, it contains code you know works,
it is managed code, and you save the cost of developing, writing, and
maintaining the code yourself?
--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard.caspershouse.com

"Adrian" <ad****@camdaw.net> wrote in message
news:73**************************@posting.google.c om...
I hit on this problem converting a VB.NET insurance application to C#.
Age next birthday calculated from date of birth is often needed in
insurance premium calculations.
Originally done using DateDiff in VB.NET which is only available in C#
if you don't mind linking in Microsoft.VisualBasic.dll to your C#
application.
I wanted to avoid this so set about a pure C# solution which uses a
combination of TimeSpan in whole days and the
System.Globalizarion.Calendar class GetDaysInYear() function to work
it out.
The added advantage here over DateDiff is this function should work
with all the different System.Globalization.Calendar types (Japanese
etc.), however I have only tested it with GregorianCalendar.

Here is the C# source code which includes a console application test
harness.
To get "Age" rather than "Age next birthday" just subtract 1 from this
result (sorry for pointing out the obvious!)

<code>
using System;

namespace WorkbenchCSConsole
{
/// <summary>
/// Summary description for AgeNextBirtdatCalculator.
/// </summary>
class AgeNextBirtdatCalculator
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main(string[] args)
{
//
// Test harness for AgeNextBirthday function
//
int AgeNextBirthday;

DateTime DOB;
DateTime DateNow;
System.Globalization.Calendar MyCalendar = new
System.Globalization.GregorianCalendar(); // should work with other
calendars
DateNow = DateTime.Now;
System.Console.WriteLine("Calendar independant date of birth to
age NEXT birtday function (commonly required in the insurance
industry) for C# written by Adrian Hilder, Camdaw Limited
www.camdaw.net. You are free to use and distribute this function in
your applications, you may not sell it for profit as a stand alone
utility without prior consent from Camdaw Limited.\nThis function is
provided as is in the hope it is usefull with no warrantee of any
kind. You should test this function to your satisfaction before using
it in your applications.\nIf you do find any faults please tell
me!\nIf you use this please tell me, I'm interested to know if anyone
uses it (it was about 3 hours work). (contact details at
www.camdaw.net)\n\n");

DOB = DateTime.MinValue;
DOB = DOB.AddYears(1970-1);
DOB = DOB.AddMonths(DateNow.Month-1);
DOB = DOB.AddDays(DateNow.Day-2);
System.Console.WriteLine("Calendar type: " +
MyCalendar.ToString() + "\n");

System.Console.WriteLine("Testing with todays date " +
DateNow.Day + "/" + DateNow.Month + "/" + DateNow.Year + "
(dd/mm/yyyy)\n");

Console.WriteLine("Test with DOB yesterdays date in 1970");
System.Console.WriteLine("DOB entered: " + DOB.Day + "/" +
DOB.Month + "/" + DOB.Year + " (dd/mm/yyyy)");
AgeNextBirthday = DOBToAgeNextBirthday(DOB, MyCalendar);
System.Console.WriteLine("AgeNextBirthdayYears=" +
AgeNextBirthday + "\n");

Console.WriteLine("Test with DOB tommorrows date in 1970");
DOB = DateTime.MinValue;
DOB = DOB.AddYears(1970-1);
DOB = DOB.AddMonths(DateNow.Month-1);
DOB = DOB.AddDays(DateNow.Day);

System.Console.WriteLine("DOB entered: " + DOB.Day + "/" +
DOB.Month + "/" + DOB.Year + " (dd/mm/yyyy)");
AgeNextBirthday = DOBToAgeNextBirthday(DOB, MyCalendar);
System.Console.WriteLine("AgeNextBirthdayYears=" +
AgeNextBirthday + "\n");

Console.WriteLine("Test with DOB this day in 1970");
DOB = DateTime.MinValue;
DOB = DOB.AddYears(1970-1);
DOB = DOB.AddMonths(DateNow.Month-1);
DOB = DOB.AddDays(DateNow.Day-1);

System.Console.WriteLine("DOB entered: " + DOB.Day + "/" +
DOB.Month + "/" + DOB.Year + " (dd/mm/yyyy) ... Happy Birthday!");
AgeNextBirthday = DOBToAgeNextBirthday(DOB, MyCalendar);
System.Console.WriteLine("AgeNextBirthdayYears=" +
AgeNextBirthday + "\n");

while(!(MyCalendar.IsLeapYear(DateNow.Year)))
DateNow = DateNow.AddYears(1);

System.Console.WriteLine("Testing with the next leap year date "
+ DateNow.Day + "/" + DateNow.Month + "/" + DateNow.Year + "
(dd/mm/yyyy)\n");
System.Console.WriteLine("Note: this DOBToAgeNextBirthday
function and test harness was written 3rd August 2004, which was a
leap year.");

Console.WriteLine("Test with DOB yesterdays date in 1970");
System.Console.WriteLine("DOB entered: " + DOB.Day + "/" +
DOB.Month + "/" + DOB.Year + " (dd/mm/yyyy)");
AgeNextBirthday = DOBToAgeNextBirthday(DOB, MyCalendar);
System.Console.WriteLine("AgeNextBirthdayYears=" +
AgeNextBirthday + "\n");

Console.WriteLine("Test with DOB tommorrows date in 1970");
DOB = DateTime.MinValue;
DOB = DOB.AddYears(1970-1);
DOB = DOB.AddMonths(DateNow.Month-1);
DOB = DOB.AddDays(DateNow.Day);

System.Console.WriteLine("DOB entered: " + DOB.Day + "/" +
DOB.Month + "/" + DOB.Year + " (dd/mm/yyyy)");
AgeNextBirthday = DOBToAgeNextBirthday(DOB, MyCalendar);
System.Console.WriteLine("AgeNextBirthdayYears=" +
AgeNextBirthday + "\n");

Console.WriteLine("Test with DOB this day in 1970");
DOB = DateTime.MinValue;
DOB = DOB.AddYears(1970-1);
DOB = DOB.AddMonths(DateNow.Month-1);
DOB = DOB.AddDays(DateNow.Day-1);

System.Console.WriteLine("DOB entered: " + DOB.Day + "/" +
DOB.Month + "/" + DOB.Year + " (dd/mm/yyyy) ... Happy Birthday!");
AgeNextBirthday = DOBToAgeNextBirthday(DOB, MyCalendar);
System.Console.WriteLine("AgeNextBirthdayYears=" +
AgeNextBirthday + "\n");

}

private static int DOBToAgeNextBirthday(DateTime DOB,
System.Globalization.Calendar ThisCalendar)
{
int DaysPassedInYear;
DateTime Now;
int YearIndex;
int DiffDays;

Now = DateTime.Now;
DiffDays = (int)Now.Subtract(DOB).TotalDays;
YearIndex = 0;
DaysPassedInYear = CalcDaysPassedInYear(Now, DOB, YearIndex,
ThisCalendar);
while(DiffDays > DaysPassedInYear)
{
DiffDays = DiffDays - DaysPassedInYear;
YearIndex++; // on to next year
DaysPassedInYear = CalcDaysPassedInYear(Now, DOB, YearIndex,
ThisCalendar);
}
// Now handle last part year
if (DiffDays > 0) // if still some days to account for
{
int DaysPassedToBirthday;
DaysPassedInYear = CalcDaysPassedInYear(Now, DOB, -1,
ThisCalendar);
DaysPassedToBirthday =
CalcDaysPassedInYear(DOB.AddYears(YearIndex), DOB, -1, ThisCalendar);
if (DaysPassedInYear >= DaysPassedToBirthday)
YearIndex++; // birthday has passed this year
}
return YearIndex;
}

private static int CalcDaysPassedInYear(DateTime Now, DateTime
DOB, int YearIndex, System.Globalization.Calendar ThisCalendar)
{
DateTime PartYearStartDate; // 1st Jan <PartYear>
int YearDaysPassed;
int DaysPassedInYear;
if (YearIndex == 0) // days in starting (DOB) part year
{
PartYearStartDate = DateTime.MinValue;
PartYearStartDate = PartYearStartDate.AddYears(DOB.Year-1);
YearDaysPassed =
(int)DOB.Subtract(PartYearStartDate).TotalDays;
DaysPassedInYear = ThisCalendar.GetDaysInYear(DOB.Year) -
YearDaysPassed;
}
else if (YearIndex == -1) // -1 used to indicate last year in
period, i.e. Now.Year
{
PartYearStartDate = DateTime.MinValue;
PartYearStartDate.AddYears(Now.Year);
DaysPassedInYear =
(int)Now.Subtract(PartYearStartDate).TotalDays;
}
else // a year within the period
{
DaysPassedInYear = ThisCalendar.GetDaysInYear(DOB.Year +
YearIndex);
}
return DaysPassedInYear;
}
}
}
</code>

Nov 16 '05 #2
Nicholas Paldino [.NET/C# MVP] <mv*@spam.guard.caspershouse.com> wrote:
I am curious, why are you against linking to Microsoft.VisualBasic.dll?
It's distributed as part of the framework, it contains code you know works,
it is managed code, and you save the cost of developing, writing, and
maintaining the code yourself?


There are often good reasons for not using Microsoft.VisualBasic.dll:

1) It's unfamiliar to many C# developers (hey, it's not even documented
in the same place as the main framework, and you don't get to see the
documentation unless you've got VB.NET in your filter)

2) There are often more idiomatic ways of doing things using the
standard framework classes

3) The Microsoft.VisualBasic.dll is less likely to be fully implemented
in other frameworks (such as Mono) than things like DateTime and
TimeSpan

Occasionally a function in the MS.VB assembly does exactly what you
want and it would be a pain to do it using the "normal" .NET classes,
but I would suggest avoiding it in other situations.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
Nov 16 '05 #3
I agree witht this somewhat.

Granted, if there is an alternative in the framework itself outside of
MSVB.dll, then I would take that, assuming I get the behavior I want.

However, if there is a solution that only exists in MSVB.dll, which
would require me to write code otherwise, then I can't see the
justification. The maintenance of code is just not worth it (no matter how
small).

From what I can tell, the DateDiff functionality offers a little more
than what the TimeSpan structure offers (also, the original poster indicated
a specific need for the functionality in DateDiff).
--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard.caspershouse.com

"Jon Skeet [C# MVP]" <sk***@pobox.com> wrote in message
news:MP************************@msnews.microsoft.c om...
Nicholas Paldino [.NET/C# MVP] <mv*@spam.guard.caspershouse.com> wrote:
I am curious, why are you against linking to Microsoft.VisualBasic.dll? It's distributed as part of the framework, it contains code you know works, it is managed code, and you save the cost of developing, writing, and
maintaining the code yourself?


There are often good reasons for not using Microsoft.VisualBasic.dll:

1) It's unfamiliar to many C# developers (hey, it's not even documented
in the same place as the main framework, and you don't get to see the
documentation unless you've got VB.NET in your filter)

2) There are often more idiomatic ways of doing things using the
standard framework classes

3) The Microsoft.VisualBasic.dll is less likely to be fully implemented
in other frameworks (such as Mono) than things like DateTime and
TimeSpan

Occasionally a function in the MS.VB assembly does exactly what you
want and it would be a pain to do it using the "normal" .NET classes,
but I would suggest avoiding it in other situations.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too

Nov 16 '05 #4
For the pragmatic C# programmer who has no interest calculating age or date
differences in anything other than the Gregorian calendar there is little
reason (as far as I can see) why DateDiff in
Microsoft.VisualBasic.DateAndTime should not be used.
I have even read reports (see
http://www.dotnet247.com/247referenc.../14/72863.aspx) that provided you
avoid using legacy methods (e.g. Len(MyString) instead of MyString.Length())
there is no significant measurable peformance penalty in using whats in
Microsoft.VisualBasic since it appears to be "native" to the .NET framework.
I really think that these usefull functions should have been put in a
namespace where everyone can find them whatever the .NET language used.

My reasons for a "pure" C# solution:

1. Microsoft.VisualBasic.DateAndTime.DateDiff are not found located when you
search on DateDiff and filter by C# in Vis.Studio.NET. so I spent a few
minutes thinking and researching about how I would code it in C# before
searching the newsgroups where I found Microsoft.VisualBasic.DateAndTime
existed, by which time I had (re)learned of the globalized calender types.
Having the luxury of time I became attracted to the idea of a solution which
"should" work for other calendar types in System.Globalization which may be
usefull for a future project I have in mind.
2. The application dll is 4K bigger going the DateDiff route (OK hardly
significant).
3. It might be irrational but there are some people out there who insist on
a "pure" C# solution avoiding the Microsoft.VisualBasic namespace, I became
curious to see if anyone would use a "pure" C# solution and if they were
doing it for reasons other than calendar globalization and what those
reasons might be.

TimeSpan might be the nearest C# equivalent to DateDiff, but TimeSpan will
not give you a date difference in months or years, I needed difference in
years to work out age / age next birthday.

If I was pushed for time and found it in MSDN in what I consider a sensible
place I would have gone the Microsoft.VisualBasic.DateAndTime.DateDiff route
and worried about calendar globalization when the need arose.

I have just returned to C# after 2 years programming with VB.NET, I've come
home, stupid I know but I really hate typing "Dim x As Integer" instead of
"int x"; etc. etc. VB.NET makes my fingers ache with all that extra typing.

"Nicholas Paldino [.NET/C# MVP]" <mv*@spam.guard.caspershouse.com> wrote in
message news:eA**************@TK2MSFTNGP09.phx.gbl...
I agree witht this somewhat.

Granted, if there is an alternative in the framework itself outside of
MSVB.dll, then I would take that, assuming I get the behavior I want.

However, if there is a solution that only exists in MSVB.dll, which
would require me to write code otherwise, then I can't see the
justification. The maintenance of code is just not worth it (no matter how small).

From what I can tell, the DateDiff functionality offers a little more
than what the TimeSpan structure offers (also, the original poster indicated a specific need for the functionality in DateDiff).
--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard.caspershouse.com

"Jon Skeet [C# MVP]" <sk***@pobox.com> wrote in message
news:MP************************@msnews.microsoft.c om...
Nicholas Paldino [.NET/C# MVP] <mv*@spam.guard.caspershouse.com> wrote:
I am curious, why are you against linking to Microsoft.VisualBasic.dll? It's distributed as part of the framework, it contains code you know works, it is managed code, and you save the cost of developing, writing, and
maintaining the code yourself?


There are often good reasons for not using Microsoft.VisualBasic.dll:

1) It's unfamiliar to many C# developers (hey, it's not even documented
in the same place as the main framework, and you don't get to see the
documentation unless you've got VB.NET in your filter)

2) There are often more idiomatic ways of doing things using the
standard framework classes

3) The Microsoft.VisualBasic.dll is less likely to be fully implemented
in other frameworks (such as Mono) than things like DateTime and
TimeSpan

Occasionally a function in the MS.VB assembly does exactly what you
want and it would be a pain to do it using the "normal" .NET classes,
but I would suggest avoiding it in other situations.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too


Nov 16 '05 #5
OK I've fixed my name now ooops.

"news.newnet.co.uk" <ad***********@nojunk.camdaw.net> wrote in message
news:41***********************@reader.news.newnet. co.uk...
For the pragmatic C# programmer who has no interest calculating age or date differences in anything other than the Gregorian calendar there is little
reason (as far as I can see) why DateDiff in
Microsoft.VisualBasic.DateAndTime should not be used.
I have even read reports (see
http://www.dotnet247.com/247referenc.../14/72863.aspx) that provided you avoid using legacy methods (e.g. Len(MyString) instead of MyString.Length()) there is no significant measurable peformance penalty in using whats in
Microsoft.VisualBasic since it appears to be "native" to the .NET framework. I really think that these usefull functions should have been put in a
namespace where everyone can find them whatever the .NET language used.

My reasons for a "pure" C# solution:

1. Microsoft.VisualBasic.DateAndTime.DateDiff are not found located when you search on DateDiff and filter by C# in Vis.Studio.NET. so I spent a few
minutes thinking and researching about how I would code it in C# before
searching the newsgroups where I found Microsoft.VisualBasic.DateAndTime
existed, by which time I had (re)learned of the globalized calender types.
Having the luxury of time I became attracted to the idea of a solution which "should" work for other calendar types in System.Globalization which may be usefull for a future project I have in mind.
2. The application dll is 4K bigger going the DateDiff route (OK hardly
significant).
3. It might be irrational but there are some people out there who insist on a "pure" C# solution avoiding the Microsoft.VisualBasic namespace, I became curious to see if anyone would use a "pure" C# solution and if they were
doing it for reasons other than calendar globalization and what those
reasons might be.

TimeSpan might be the nearest C# equivalent to DateDiff, but TimeSpan will
not give you a date difference in months or years, I needed difference in
years to work out age / age next birthday.

If I was pushed for time and found it in MSDN in what I consider a sensible place I would have gone the Microsoft.VisualBasic.DateAndTime.DateDiff route and worried about calendar globalization when the need arose.

I have just returned to C# after 2 years programming with VB.NET, I've come home, stupid I know but I really hate typing "Dim x As Integer" instead of
"int x"; etc. etc. VB.NET makes my fingers ache with all that extra typing.
"Nicholas Paldino [.NET/C# MVP]" <mv*@spam.guard.caspershouse.com> wrote in message news:eA**************@TK2MSFTNGP09.phx.gbl...
I agree witht this somewhat.

Granted, if there is an alternative in the framework itself outside of MSVB.dll, then I would take that, assuming I get the behavior I want.

However, if there is a solution that only exists in MSVB.dll, which
would require me to write code otherwise, then I can't see the
justification. The maintenance of code is just not worth it (no matter

how
small).

From what I can tell, the DateDiff functionality offers a little more than what the TimeSpan structure offers (also, the original poster

indicated
a specific need for the functionality in DateDiff).
--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard.caspershouse.com

"Jon Skeet [C# MVP]" <sk***@pobox.com> wrote in message
news:MP************************@msnews.microsoft.c om...
Nicholas Paldino [.NET/C# MVP] <mv*@spam.guard.caspershouse.com> wrote: > I am curious, why are you against linking to

Microsoft.VisualBasic.dll?
> It's distributed as part of the framework, it contains code you know

works,
> it is managed code, and you save the cost of developing, writing, and > maintaining the code yourself?

There are often good reasons for not using Microsoft.VisualBasic.dll:

1) It's unfamiliar to many C# developers (hey, it's not even documented in the same place as the main framework, and you don't get to see the
documentation unless you've got VB.NET in your filter)

2) There are often more idiomatic ways of doing things using the
standard framework classes

3) The Microsoft.VisualBasic.dll is less likely to be fully implemented in other frameworks (such as Mono) than things like DateTime and
TimeSpan

Occasionally a function in the MS.VB assembly does exactly what you
want and it would be a pain to do it using the "normal" .NET classes,
but I would suggest avoiding it in other situations.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too



Nov 16 '05 #6
news.newnet.co.uk <ad***********@nojunk.camdaw.net> wrote:
For the pragmatic C# programmer who has no interest calculating age or date
differences in anything other than the Gregorian calendar there is little
reason (as far as I can see) why DateDiff in
Microsoft.VisualBasic.DateAndTime should not be used.
I have even read reports (see
http://www.dotnet247.com/247referenc.../14/72863.aspx) that provided you
avoid using legacy methods (e.g. Len(MyString) instead of MyString.Length())
there is no significant measurable peformance penalty in using whats in
Microsoft.VisualBasic since it appears to be "native" to the .NET framework.
It depends on exactly what you're doing - sometimes there *is* a
performance penalty because some VB functions do a lot more than you
need them to. (Other times they do exactly what you need and no more.)
I really think that these usefull functions should have been put in a
namespace where everyone can find them whatever the .NET language used.


I think some of them should possibly have been included in
TimeSpan/DateTime etc. A lot of other ones have direct equivalents in
the library already.

<snip>

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
Nov 16 '05 #7
Adrian

So, your just after something in C# to work out the ANB.

Apologies if i've gotten the wrong end of the stick.

/// <summary>
/// Returns the age next birthday

/// Note that if the current day is the birthday then the younger age will
be taken

/// this is to keep in line with both the LAP and POS systems.

/// </summary>

/// <param name="dob"></param>

/// <returns></returns>

public static int AgeNextBirthday(DateTime dob)

{

return AgeNextBirthday(DateTime.Now, dob);

}

public static int AgeNextBirthday(DateTime fromDate, DateTime dob)

{

int yearDifference = fromDate.Year - dob.Year;

int ageNextBirthday;

if(fromDate.Month > dob.Month)

{

ageNextBirthday = yearDifference + 1;

}

else if (fromDate.Month == dob.Month)

{

if (fromDate.Day > dob.Day)

{

ageNextBirthday = yearDifference + 1;

}

else

{

ageNextBirthday = yearDifference;

}

}

else

{

ageNextBirthday = yearDifference;

}
return ageNextBirthday;

}

Glenn

"Adrian" <ad****@camdaw.net> wrote in message
news:73**************************@posting.google.c om...
I hit on this problem converting a VB.NET insurance application to C#.
Age next birthday calculated from date of birth is often needed in
insurance premium calculations.
Originally done using DateDiff in VB.NET which is only available in C#
if you don't mind linking in Microsoft.VisualBasic.dll to your C#
application.
I wanted to avoid this so set about a pure C# solution which uses a
combination of TimeSpan in whole days and the
System.Globalizarion.Calendar class GetDaysInYear() function to work
it out.
The added advantage here over DateDiff is this function should work
with all the different System.Globalization.Calendar types (Japanese
etc.), however I have only tested it with GregorianCalendar.

Here is the C# source code which includes a console application test
harness.
To get "Age" rather than "Age next birthday" just subtract 1 from this
result (sorry for pointing out the obvious!)

<code>
using System;

namespace WorkbenchCSConsole
{
/// <summary>
/// Summary description for AgeNextBirtdatCalculator.
/// </summary>
class AgeNextBirtdatCalculator
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main(string[] args)
{
//
// Test harness for AgeNextBirthday function
//
int AgeNextBirthday;

DateTime DOB;
DateTime DateNow;
System.Globalization.Calendar MyCalendar = new
System.Globalization.GregorianCalendar(); // should work with other
calendars
DateNow = DateTime.Now;
System.Console.WriteLine("Calendar independant date of birth to
age NEXT birtday function (commonly required in the insurance
industry) for C# written by Adrian Hilder, Camdaw Limited
www.camdaw.net. You are free to use and distribute this function in
your applications, you may not sell it for profit as a stand alone
utility without prior consent from Camdaw Limited.\nThis function is
provided as is in the hope it is usefull with no warrantee of any
kind. You should test this function to your satisfaction before using
it in your applications.\nIf you do find any faults please tell
me!\nIf you use this please tell me, I'm interested to know if anyone
uses it (it was about 3 hours work). (contact details at
www.camdaw.net)\n\n");

DOB = DateTime.MinValue;
DOB = DOB.AddYears(1970-1);
DOB = DOB.AddMonths(DateNow.Month-1);
DOB = DOB.AddDays(DateNow.Day-2);
System.Console.WriteLine("Calendar type: " +
MyCalendar.ToString() + "\n");

System.Console.WriteLine("Testing with todays date " +
DateNow.Day + "/" + DateNow.Month + "/" + DateNow.Year + "
(dd/mm/yyyy)\n");

Console.WriteLine("Test with DOB yesterdays date in 1970");
System.Console.WriteLine("DOB entered: " + DOB.Day + "/" +
DOB.Month + "/" + DOB.Year + " (dd/mm/yyyy)");
AgeNextBirthday = DOBToAgeNextBirthday(DOB, MyCalendar);
System.Console.WriteLine("AgeNextBirthdayYears=" +
AgeNextBirthday + "\n");

Console.WriteLine("Test with DOB tommorrows date in 1970");
DOB = DateTime.MinValue;
DOB = DOB.AddYears(1970-1);
DOB = DOB.AddMonths(DateNow.Month-1);
DOB = DOB.AddDays(DateNow.Day);

System.Console.WriteLine("DOB entered: " + DOB.Day + "/" +
DOB.Month + "/" + DOB.Year + " (dd/mm/yyyy)");
AgeNextBirthday = DOBToAgeNextBirthday(DOB, MyCalendar);
System.Console.WriteLine("AgeNextBirthdayYears=" +
AgeNextBirthday + "\n");

Console.WriteLine("Test with DOB this day in 1970");
DOB = DateTime.MinValue;
DOB = DOB.AddYears(1970-1);
DOB = DOB.AddMonths(DateNow.Month-1);
DOB = DOB.AddDays(DateNow.Day-1);

System.Console.WriteLine("DOB entered: " + DOB.Day + "/" +
DOB.Month + "/" + DOB.Year + " (dd/mm/yyyy) ... Happy Birthday!");
AgeNextBirthday = DOBToAgeNextBirthday(DOB, MyCalendar);
System.Console.WriteLine("AgeNextBirthdayYears=" +
AgeNextBirthday + "\n");

while(!(MyCalendar.IsLeapYear(DateNow.Year)))
DateNow = DateNow.AddYears(1);

System.Console.WriteLine("Testing with the next leap year date "
+ DateNow.Day + "/" + DateNow.Month + "/" + DateNow.Year + "
(dd/mm/yyyy)\n");
System.Console.WriteLine("Note: this DOBToAgeNextBirthday
function and test harness was written 3rd August 2004, which was a
leap year.");

Console.WriteLine("Test with DOB yesterdays date in 1970");
System.Console.WriteLine("DOB entered: " + DOB.Day + "/" +
DOB.Month + "/" + DOB.Year + " (dd/mm/yyyy)");
AgeNextBirthday = DOBToAgeNextBirthday(DOB, MyCalendar);
System.Console.WriteLine("AgeNextBirthdayYears=" +
AgeNextBirthday + "\n");

Console.WriteLine("Test with DOB tommorrows date in 1970");
DOB = DateTime.MinValue;
DOB = DOB.AddYears(1970-1);
DOB = DOB.AddMonths(DateNow.Month-1);
DOB = DOB.AddDays(DateNow.Day);

System.Console.WriteLine("DOB entered: " + DOB.Day + "/" +
DOB.Month + "/" + DOB.Year + " (dd/mm/yyyy)");
AgeNextBirthday = DOBToAgeNextBirthday(DOB, MyCalendar);
System.Console.WriteLine("AgeNextBirthdayYears=" +
AgeNextBirthday + "\n");

Console.WriteLine("Test with DOB this day in 1970");
DOB = DateTime.MinValue;
DOB = DOB.AddYears(1970-1);
DOB = DOB.AddMonths(DateNow.Month-1);
DOB = DOB.AddDays(DateNow.Day-1);

System.Console.WriteLine("DOB entered: " + DOB.Day + "/" +
DOB.Month + "/" + DOB.Year + " (dd/mm/yyyy) ... Happy Birthday!");
AgeNextBirthday = DOBToAgeNextBirthday(DOB, MyCalendar);
System.Console.WriteLine("AgeNextBirthdayYears=" +
AgeNextBirthday + "\n");

}

private static int DOBToAgeNextBirthday(DateTime DOB,
System.Globalization.Calendar ThisCalendar)
{
int DaysPassedInYear;
DateTime Now;
int YearIndex;
int DiffDays;

Now = DateTime.Now;
DiffDays = (int)Now.Subtract(DOB).TotalDays;
YearIndex = 0;
DaysPassedInYear = CalcDaysPassedInYear(Now, DOB, YearIndex,
ThisCalendar);
while(DiffDays > DaysPassedInYear)
{
DiffDays = DiffDays - DaysPassedInYear;
YearIndex++; // on to next year
DaysPassedInYear = CalcDaysPassedInYear(Now, DOB, YearIndex,
ThisCalendar);
}
// Now handle last part year
if (DiffDays > 0) // if still some days to account for
{
int DaysPassedToBirthday;
DaysPassedInYear = CalcDaysPassedInYear(Now, DOB, -1,
ThisCalendar);
DaysPassedToBirthday =
CalcDaysPassedInYear(DOB.AddYears(YearIndex), DOB, -1, ThisCalendar);
if (DaysPassedInYear >= DaysPassedToBirthday)
YearIndex++; // birthday has passed this year
}
return YearIndex;
}

private static int CalcDaysPassedInYear(DateTime Now, DateTime
DOB, int YearIndex, System.Globalization.Calendar ThisCalendar)
{
DateTime PartYearStartDate; // 1st Jan <PartYear>
int YearDaysPassed;
int DaysPassedInYear;
if (YearIndex == 0) // days in starting (DOB) part year
{
PartYearStartDate = DateTime.MinValue;
PartYearStartDate = PartYearStartDate.AddYears(DOB.Year-1);
YearDaysPassed =
(int)DOB.Subtract(PartYearStartDate).TotalDays;
DaysPassedInYear = ThisCalendar.GetDaysInYear(DOB.Year) -
YearDaysPassed;
}
else if (YearIndex == -1) // -1 used to indicate last year in
period, i.e. Now.Year
{
PartYearStartDate = DateTime.MinValue;
PartYearStartDate.AddYears(Now.Year);
DaysPassedInYear =
(int)Now.Subtract(PartYearStartDate).TotalDays;
}
else // a year within the period
{
DaysPassedInYear = ThisCalendar.GetDaysInYear(DOB.Year +
YearIndex);
}
return DaysPassedInYear;
}
}
}
</code>

Nov 16 '05 #8

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

20
by: Gav | last post by:
I have a database with date of births stored dd/mm/yyyy (english dating system) and =date() returns a date in the same format in my server. how do i find the persons age using these two pieces of...
3
by: Alan Mews | last post by:
Hi All Being a Newbie and tried very hard to get my Database (Access) to calculate the age of a person, in years, from the Date of Birth. The Fields are: DateofBirth minus Today's Date =Age,...
4
by: Jan Szymczuk | last post by:
I'm creating an MS Access 2000 database where I have a number of people entered using simple basic fields, Surname: SMITH Forenames: John DoB: 09/09/1958 Age:...
8
by: TJS | last post by:
what namespaces are required so I can do a simple calculate age from date of birth ?
2
by: David Garamond | last post by:
What would be the more proper way of storing birthday data? It will be used to send out birthday messages for customers ("Happy 30th birthday, Sam!"). But the date of birth is not necessarily known...
6
by: birchw | last post by:
Hi, I downloaded a function from the Microsoft Knowledge base to calculate a persons age as at the current date based on DOB. The function is as follows: Function Age(varBirthDate As Variant)...
8
by: helpless | last post by:
Access 2003 - I am trying to calculate the difference between a specific date 5/1/2007 (not in a data field) and other dates that ARE in a field called Birth Date. I am trying to have it fill into...
9
by: howzit | last post by:
I have a set date in my MySQL database that records when a Sales Lead is established and I echo that date as $row_rsLead; I need to be able to calculate how many days that lead has existed....
15
by: student4lifer | last post by:
Hello, I have 2 time fields dynamically generated in format "m/d/y H:m". Could someone show me a good function to calculate the time interval difference in minutes? I played with strtotime() but...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.