1

I need help to display something like this. If you recognize, this our membership duration of Stack Overflow account.

member for  2 years, 3 months

I need a slight modification in the same. My conditions and display format are as follows:

  Conditions              Display Format
1. Below 7 days  ->       Days (5 days)
2. 7 -30 days    ->       Weeks, days   ( 2 Weeks, 3 Days) in case of 17 days.
3. 30 - 365      ->       Months, Weeks, Days (4Months, 2Weeks, 2Days) in case of 136 days
3. 365 or grter  ->       Years, Months only (2years, 3 Months)

What I did:

I am using Timespan to get the date difference. But I am not satisfied with my output. I have a member whose registration's going to 2 months old after 2-3 days, but still its showing 1 month ago. Here is my code:

 TimeSpan ts = DateTime.Now - Convert.ToDateTime(company.RegistrationDate);

                 if (ts.Days > 365)
                    membersince.InnerText = string.Format("{0} years", (ts.Days / 365));
                else if (ts.Days < 30)
                    membersince.InnerText = string.Format("{0} days", ts.Days);
                     else if(ts.Days > 30)
                    membersince.InnerText = string.Format("{0} months", (ts.Days/30));
  • Have you gone through it with a debugger? – John H Apr 08 '12 at 14:19
  • In your question, it is given that "I have a member whose registration's going to 2 months old after 2-3 days, but still its showing 1 month ago." As it is not yet 2 months, shouldn't the output of 1 month correct? – Anil Mathew Apr 08 '12 at 14:24
  • Duplicate http://stackoverflow.com/questions/9594583/birthday-age-calculation-but-also-for-number-of-months-and-days/9594788#9594788 – Serj-Tm Apr 08 '12 at 14:27
  • Do you intend to have some rounding off. Foe example: if the number of days is > 55, consider the month as 2 instead of 1? – Anil Mathew Apr 08 '12 at 14:27

4 Answers4

2

You can use the DateDiff class of the Time Period Library for .NET library:

// ----------------------------------------------------------------------
public void DateDiffSample()
{
  DateTime date1 = new DateTime( 2009, 11, 8, 7, 13, 59 );
  Console.WriteLine( "Date1: {0}", date1 );
  // > Date1: 08.11.2009 07:13:59
  DateTime date2 = new DateTime( 2011, 3, 20, 19, 55, 28 );
  Console.WriteLine( "Date2: {0}", date2 );
  // > Date2: 20.03.2011 19:55:28

  DateDiff dateDiff = new DateDiff( date1, date2 );

  // elapsed
  Console.WriteLine( "DateDiff.ElapsedYears: {0}", dateDiff.ElapsedYears );
  // > DateDiff.ElapsedYears: 1
  Console.WriteLine( "DateDiff.ElapsedMonths: {0}", dateDiff.ElapsedMonths );
  // > DateDiff.ElapsedMonths: 4
  Console.WriteLine( "DateDiff.ElapsedDays: {0}", dateDiff.ElapsedDays );
  // > DateDiff.ElapsedDays: 12
  Console.WriteLine( "DateDiff.ElapsedHours: {0}", dateDiff.ElapsedHours );
  // > DateDiff.ElapsedHours: 12
  Console.WriteLine( "DateDiff.ElapsedMinutes: {0}", dateDiff.ElapsedMinutes );
  // > DateDiff.ElapsedMinutes: 41
  Console.WriteLine( "DateDiff.ElapsedSeconds: {0}", dateDiff.ElapsedSeconds );
  // > DateDiff.ElapsedSeconds: 29
} // DateDiffSample
1

Why is this a problem? If one's age is 57 days, then 57 / 30 == 1. If you are expecting to get 2 out of this, then you should

1) make sure the result of your division is double (simply divide by 30.0 instead of 30). The reason is that int / int is also an int.

Simple test:
(57 / 30).GetType().Name == Int32
(57 / 30.0).GetType().Name == Double

Also (int)1.9 == 1.

2) Math.Round() the result. This would be actual mathematical rounding, as opposed to just dropping everything after decimal point.

Ilia G
  • 10,043
  • 2
  • 40
  • 59
1

Just use the TotalDays which will give you double (and is more 'politically' correct as Days is just the component, though in your case is similar), and Math.Round() as already suggested by @Ilia to the 'nearest'.

Math.Round(ts.TotalDays);

...or

String.Format("{0:0.##}", ts.TotalDays);  

...which should give you like 1.7 months (as I recall from my head or test for your winning format)

It's more a logical and user-interface problem, how to 'present' to the user.

EDIT: use just TotalDays to format as 1.7 - or use Math.Round to get a round month

NSGaga-mostly-inactive
  • 14,052
  • 3
  • 41
  • 51
0
static public string calculateAge(DateTime birthDate, DateTime now)
{
  birthDate = birthDate.Date;
  now = now.Date;

  var days = now.Day - birthDate.Day;
  if (days < 0)
  {
    var newNow = now.AddMonths(-1);
    days += (int)(now - newNow).TotalDays;
    now = newNow;
  }
  var weeks = days / 7;
  days = days - weeks * 7;
  var months = now.Month - birthDate.Month;
  if (months < 0)
  {
    months += 12;
    now = now.AddYears(-1);
  }
  var years = now.Year - birthDate.Year;

  if (years > 0)
  {
    if (months > 0)
      return string.Format("{0} Years, {1} Months", years, months);
    else
      return string.Format("{0} Years", years);
  }
  if (months > 0)
  {
    var builder = new StringBuilder();
    builder.AppendFormat("{0} Months", months);
    if (weeks > 0)
      builder.AppendFormat(", {0} Weeks", weeks);
    if (days > 0)
      builder.AppendFormat(", {0} Days", days);
    return builder.ToString();
  }
  if (weeks > 0)
  {
    if (days > 0)
      return string.Format("{0} Weeks, {1} Days", weeks, days);
    return string.Format("{0} Weeks", weeks);
  }

  return string.Format("{0} Days", days);
}
Serj-Tm
  • 16,581
  • 4
  • 54
  • 61