8

I have created a simple age calculator. I want to remove decimal places but the problem is when I substract now to bday.

example : I input 2012, 10 and 23 and the date now is 2014-10-22, So when 2014.1022 - 2012.1023 the result would be 1.9999... I want to remove all decimal places and remain the whole number 1, but the time I use String.Format("{0:00}" It rounds off the result to 02even when I use ConvertToInt32, I don't want to use split string it needs a lot of code.

Any Ideas?

 static void Main(string[] args)
        {
            string year, month, day = string.Empty;
            Console.WriteLine("Enter your Birthdate:");
            Console.WriteLine("Year :");
            year = Console.ReadLine();
            Console.WriteLine("Month :");
             month = Console.ReadLine();
            Console.WriteLine("Day :" );
            day = Console.ReadLine();
            try
            {
                DateTime date = Convert.ToDateTime(year + "-" + month + "-" + day);
                 var bday = float.Parse(date.ToString("yyyy.MMdd"));
                 var now = float.Parse(DateTime.Now.ToString("yyyy.MMdd"));
                 if (now < bday)
                 {
                     Console.WriteLine("Invalid Input of date");
                     Console.ReadLine();

                 }
                 Console.WriteLine("Your Age is " + (String.Format("{0:00}", (now - bday)))); //it rounds off my float
                 Console.ReadLine();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
                Console.ReadLine();
            }

        }

}

Awtszs
  • 323
  • 1
  • 8
  • 33
  • 1
    Why are you not using the TimeSpan class? – Krisztián Balla Oct 22 '14 at 09:17
  • 1. you can use `TimeSpan`. 2. get a look on this answer http://stackoverflow.com/questions/16671165/how-to-calculate-the-age-of-a-person to get idea how to calculate the date by yourself – AsfK Oct 22 '14 at 09:18
  • 1
    @JennyO'Reilly: You can't get from a TimeSpan to a number of years... – Jon Skeet Oct 22 '14 at 09:19
  • It's not clear to me what you expect the result to be - it doesn't make sense to have a fractional number of years, given that the length of a year varies. It makes much more sense to talk in terms of years, months and days. Additionally, treating a year-month-day value as a numeric value is a *really bad idea*. It simply won't behave as you want it to... don't do it. – Jon Skeet Oct 22 '14 at 09:21
  • @jon skeet but this is accurate I want to remove all decimal places and left the whole number as the result – Awtszs Oct 22 '14 at 09:24
  • The problem seems to be that the result is rounded up. So maybe you only need to use Math.Floor to solve the problem? – Krisztián Balla Oct 22 '14 at 09:24
  • @Awtszs: Fundamentally you're approaching time in a broken manner by trying to represent a date as a number like this. I would strongly suggest that you avoid doing this. And if you want to remove all decimal places, surely you just want an `int`... – Jon Skeet Oct 22 '14 at 09:28
  • See also [Handling Birthdays, and Other Anniversaries](http://codeofmatt.com/2014/04/09/handling-birthdays-and-other-anniversaries/) – Matt Johnson-Pint Oct 23 '14 at 01:26

3 Answers3

10

Contrary to the comments, TimeSpan does not help you here, because a year is not a fixed length of time. That in turn leads to your expressed aim being very strange indeed. You really shouldn't be representing a date as a fractional number with the first two digits being months and the third and fourth digits being days. Time just doesn't work like that. (Consider that the difference between 2014.0131 and 2014.0201 is much greater than the difference between 2014.0130 and 2014.0131, for example.)

It would be better to represent an age in terms of years, months and days. My Noda Time library makes that pretty simple:

LocalDate birthday = new LocalDate(1976, 6, 19); // For example
LocalDate today = LocalDateTime.FromDateTime(DateTime.Now).Date; // See below
Period period = Period.Between(birthday, today);
Console.WriteLine("You are {0} years, {1} months, {2} days old",
                  period.Years, period.Months, period.Days);

If you want to just determine a number of years, you could decide to just use period.Years, or possibly round the result based on period.Months as well.

I would recommend against using DateTime.Now in production code, however. In Noda Time, we have an IClock interface representing "a means of getting the current instant in time", with a SystemClock implementation in the main assembly and a FakeClock implementation in the testing assembly. Your code would accept an IClock (possibly with dependency injection) and then use that to determine the current date in whatever time zone you're interested in. That way, you can write tests for any situation you like, without changing your computer's clock. This is a good way of handling time-related tasks in general, IMO.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
3

In our framework we use the following methods:

    /// <summary>
    /// Calculates the age at the specified date.
    /// </summary>
    /// <param name="dateOfBirth">The date of birth.</param>
    /// <param name="referenceDate">The date for which the age should be calculated.</param>
    /// <returns></returns>
    public static int Age(DateTime dateOfBirth, DateTime referenceDate)
    {
        int years = referenceDate.Year - dateOfBirth.Year;
        dateOfBirth = dateOfBirth.AddYears(years);
        if (dateOfBirth.Date > referenceDate.Date)
            years--;
        return years;
    }

    /// <summary>
    /// Calculates the age at this moment.
    /// </summary>
    /// <param name="dateOfBirth">The date of birth.</param>
    /// <returns></returns>
    public static int Age(DateTime dateOfBirth)
    {
        return Age(dateOfBirth, DateTime.Today);
    }
Martin Mulder
  • 12,642
  • 3
  • 25
  • 54
-1

Here I found an answer to my question, I use LastIndexOf to remove all string after a certain character which is point(.), but before that I converted float to string.

It is accurate, try it. :)

   static void Main(string[] args)
    {
        string year, month, day = string.Empty;
        Console.WriteLine("Enter your Birthdate:");
        Console.WriteLine("Year :");
        year = Console.ReadLine();
        Console.WriteLine("Month :");
         month = Console.ReadLine();
        Console.WriteLine("Day :" );
        day = Console.ReadLine();
        try
        {
            DateTime date = Convert.ToDateTime(year + "-" + month + "-" + day);
             var bday = float.Parse(date.ToString("yyyy.MMdd"));
             var now = float.Parse(DateTime.Now.ToString("yyyy.MMdd"));
             if (now < bday)
             {
                 Console.WriteLine("Invalid Input of date");
                 Console.ReadLine();

             }
             string age = (now - bday).ToString(); 
             Console.WriteLine("Your Age is " + (age.Substring(0, age.LastIndexOf('.'))));
             Console.ReadLine();
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.ToString());
            Console.ReadLine();
        }





        }
Community
  • 1
  • 1
Awtszs
  • 323
  • 1
  • 8
  • 33
  • I downvoted because there are several solutions posted and still you answer your own question with an utterly too complicated approach. – Krisztián Balla Oct 23 '14 at 06:22
  • @JennyO'Reilly,what in the world are you talking about. Still I did not get any solution to their answer. and I try to solve it my self – Awtszs Oct 23 '14 at 06:25
  • The solution you posted yourself was in fact already suggested by me (using Math.Floor) and Jon Skeet (casting to an integer) using a simpler way. So your solution makes no sense to me. In what way is your solution different? – Krisztián Balla Oct 23 '14 at 09:04
  • @JennyO'Reilly as I've said to my question, casting to an integer rounds off my number. All I want is to remove the decimal places and not to round it off. – Awtszs Oct 24 '14 at 00:49
  • What is the difference? 1.999 rounded of is 1. 1.999 without the decimal places is 1. 1 = 1. – Krisztián Balla Oct 24 '14 at 08:43
  • @JennyO'Reilly What? when you round off 1.99999 it become 2. – Awtszs Oct 24 '14 at 09:34
  • That is called "rounding up" and not "rounding off". You can force rounding off with Math.Floor(now - bday) as I suggested. Simply casting float to int also rounds off. int a = (int)1.9999; becomes 1 and not 2. – Krisztián Balla Oct 24 '14 at 09:42