-5

I am doing my lab hw. There is a part that I couldn't handle it: "The company wants to give bonus 200 TL to the employee if the current week is the one in which the employee’s birthday occurs." I am trying to write a method that returns boolean, if the birth date in the current week. Then, I realised that the method I have done is just checking if the current day is equalt to birth date. What I want is if the current payment week if inculdes someone's birthdate. I think I need to use a calendar or something like that. Since the program is temp, each day will be payment day. I mean if the birthday is in the same week with DateTime.Today then return true. And add 200 TL more to the salary.

 protected bool isBirthDay()
        {
            try
            {
                string today = DateTime.Today.
                string birth_date = birthDate.ToString("d");
                if (today[0]== birth_date[0] && today[1]== birth_date[1] && today[3]==birth_date[3] && today[4]==birth_date[4])
                    return true;
                return false;
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
                throw;
            }
            
        }

Demir
  • 799
  • 3
  • 16
  • Also, don't compare dates as strings. Compare them as dates. – mjwills Dec 26 '20 at 13:56
  • I couldn't find a method to compare them as datetime. I am a beginner sorry about that. – Demir Dec 26 '20 at 13:57
  • `I couldn't find a method to compare them as datetime.` == will work, just like you do with strings. – mjwills Dec 26 '20 at 13:57
  • We don't know which daya they are going to get paid. Every sunday the salary paid. If the my birthday in that week before then i will get paid 200 more. There is no specific date – Demir Dec 26 '20 at 14:00
  • 1
    What qualifies as "the week" for 29 December 2020? Be explicit. – mjwills Dec 26 '20 at 14:01
  • == this operator is not working because "12/26/1990" and "12/26/2020" if i compera them the result will be false however it must be true. There is a difference btw 2020 and 1990 – Demir Dec 26 '20 at 14:02
  • Then extract the `Month` and `Day` properties and compare those. No need to convert to string. – mjwills Dec 26 '20 at 14:02
  • Also consider what happens for someone who has a birthday on 29th February. – mjwills Dec 26 '20 at 14:03
  • The program is temp .So that each day is payment day. :) If I run it today today will be payment day. datetime.Today is the payment day. – Demir Dec 26 '20 at 14:08
  • 1
    If you get the week number, you know the answer right? Here is how. https://stackoverflow.com/a/11155102/1987258 – Daan Dec 26 '20 at 14:55
  • @Daan I don't think so. The same month and day can be in different weeks of the year in different years. – juharr Dec 26 '20 at 16:14
  • Tell me when Jan 8th is in any other week than the 2nd week of the year. – LarryBud Dec 26 '20 at 16:25

2 Answers2

0

This is more complex than I initially thought. Fortunately the DateTime structure has a method called DayOfYear that could simplify our calculation because we can remove the Year problem and the leap year checks

bool isBirthWeek(DateTime birthDate)
{
    DateTime dtStart = DateTime.Today;

    // Find the previous monday
    while (dtStart.DayOfWeek != DayOfWeek.Monday)
    {
        dtStart = dtStart.AddDays(-1);
    }

    DateTime dtEnd = dtStart.AddDays(7);

    int dayStart = dtStart.DayOfYear;
    int dayEnd = dtEnd.DayOfYear;
    int birthDay = birthDate.DayOfYear;
    return (birthDay >= dayStart && birthDay < dayEnd);

}

A more generic version could replace the DateTime.Today with a custom date passed from the caller

bool isBirthWeek(DateTime dtStart, DateTime birthDate)
{
    // Find the previous monday
    while (dtStart.DayOfWeek != DayOfWeek.Monday)
    {
        dtStart = dtStart.AddDays(-1);
    }

    DateTime dtEnd = dtStart.AddDays(7);

    int dayStart = dtStart.DayOfYear;
    int dayEnd = dtEnd.DayOfYear;
    int birthDay = birthDate.DayOfYear;
    return (birthDay >= dayStart && birthDay < dayEnd);

}

but if you just want to know if the birthdate is inside the range of 6 day before the payment date you could write

bool isBirthWeek(DateTime payDate, DateTime birthDate)
{
    DateTime dtStart = payDate.AddDays(-6);
    DateTime dtEnd = payDate;
    int dayStart = dtStart.DayOfYear;
    int dayEnd = dtEnd.DayOfYear;
    int birthDay = birthDate.DayOfYear;
    return (birthDay >= dayStart && birthDay < dayEnd);

}
Steve
  • 213,761
  • 22
  • 232
  • 286
  • Thanks this worked for me. But I want the payment to be today. Since the program temp. Then DateTime.Today is the payment day. So, if birth date is in the 6 before days. Then return true. You are excepting the payment date is the middle of the week. The method works like if the birth date is in the 3 days before or 3 days after then return true. – Demir Dec 26 '20 at 14:22
  • This method gives you true if the Birthdate passed here is in the same week of Today. It has no knowledge of rules about payment date. Of course if you want a generic version that doesn't take in consideration DateTime.Today then you just need to add another parameter that replace the Today used here – Steve Dec 26 '20 at 14:27
  • And also, a week is considered starting on monday. If you just want 7 days before the _dtStart_ then you could just replace the loop with _dtStart = dtStart.AddDays(-6)_ and set dtEnd equal dtStart before the subtraction – Steve Dec 26 '20 at 14:30
  • 1
    I think this needs a bit of work to handle leap years as a birth day in a leap yeat after Febuary will have a `DayOfYear` that is 1 greater than that same month and day in a non leap year. – juharr Dec 26 '20 at 16:06
  • Yes that's could be an improvement just to equalize every year to the same 365 days count. We could add a check on the leap year and decrement by one dates after 28 of february unless the payment date is on a leap year itself. Of course we could decide to pay the extra only every 4 years to the poor fellow. :-) – Steve Dec 26 '20 at 16:36
  • `DayOfYear` could be problematic for calendars which have variable number of months (e.g. Hebrew). Pedantic - yes. ;) – mjwills Dec 27 '20 at 03:31
0

I think people are making this too difficult.

    /// <summary>
    /// Returns True birthdate is in the same week as the compareDate, with Sunday being the start of the week
    /// </summary>
    /// <param name="compareDate"></param>
    /// <param name="birthdate"></param>
    /// <returns></returns>
    public static bool IsInSameWeek(DateTime compareDate, DateTime birthdate)
    {
        var startDate = compareDate.AddDays(-(int)compareDate.DayOfWeek); //get the Sunday of the week

        if (!DateTime.IsLeapYear(startDate.Year) && birthdate.Month == 2 && birthdate.Day == 29)
            birthdate = birthdate.AddDays(-1);

        var compareBd = new DateTime(startDate.Year, birthdate.Month, birthdate.Day); //get the birth date of the compare year

        var totalDays = (compareBd - startDate).TotalDays; //number of days between the dates.
        return (totalDays >= 0 && totalDays <= 6); //Are we within 6 days of each other
    }

As the comments point out, we get the start of the week of "compareDate", with Sunday being defined as the start of the week.

We then create a new DateTime with the birth month and day of the year of "compareDate". Then we make sure the new birthday is equal to the compare date, but no more than 6 days older.

LarryBud
  • 990
  • 9
  • 20
  • Will this work if they were born on 29th February? – mjwills Dec 26 '20 at 22:31
  • Not out of the box, but you'll have to decide how to handle Feb 29th in your business rules first. e.g do you "count" that as Feb 28th or Mar 1st? – LarryBud Dec 27 '20 at 03:04
  • Whatever my decision is, this code (as is) won't work (it will throw an exception) in most years (and I suspect it won't handle the Hebrew calendar well either). That is my point. This is why I find `I think people are making this too difficult.` a little frustrating as a comment. Sure, dates are simple - as long as you ignore the difficult parts. :) – mjwills Dec 27 '20 at 03:10
  • Point taken, I added the single conditional which would prevent the exception and will "count" a Feb 29th which doesn't exist as Feb 28 (or you could add a day to "count" it as Mar 1). Looking at how .NET adds dates, I would count it as Feb 28th to be consistent. (i.e. if you add a year to a Feb 29th date, it comes back as feb 28th of the following year) Obviously I'm not putting complete error handling in the code, I would hope the OP could do that himself. – LarryBud Dec 27 '20 at 03:18
  • Awesome, a great improvement. Still likely won't handle Hebrew leap years, but an improvement nonetheless. – mjwills Dec 27 '20 at 03:20
  • Should I modify the method for julian dates too? How about BC? ;-) I mean, whether you need to handle other globalizations isn't really in the purview of S.O., is it? – LarryBud Dec 27 '20 at 03:29
  • It is your answer, you can do whatever you like. But what I would argue you _can't_ do is say `I think people are making this too difficult.` and then provide an answer that is half baked. Dates are hard. – mjwills Dec 27 '20 at 03:30
  • My answer isn't half baked unless the OP is specifically asking for Hebrew dates. He's doing lab homework after all. – LarryBud Dec 27 '20 at 03:33