0
\$\begingroup\$

At the moment I have a Reminder Date. In the UI I have two fields to create the reminder date. The first field is an int and the second field is a combo box.

public int Frequency {get; set;}
public ReminderComboItems item {get; set;}

public enum ReminderComboItems
{
    Minutes, Hours, Days, Weeks, Months, Years
}

public static DateTime ReminderComboItem(ReminderComboItems item, DateTime activityDate, int frequency)
{
    switch (item)
    {
        case ReminderComboItems.Minutes:
            date = date.AddMinutes(frequency);
            return date;
        case ReminderComboItems.Hours:
            date = date.AddHours(frequency);
            return date;
        case ReminderComboItems.Days:
            date = date.AddDays(frequency);
            return date;
        case ReminderComboItems.Months:
            date = date.AddMonths(frequency);
            return date;
        case ReminderComboItems.Years:
            date = date.AddYears(frequency);
            return date;
        default:
            return date;
    }
}

Using the top function creates the Reminder Date, now I'm trying to do the reverse.

public static ReminderDTO ReverseAppointment(DateTime activityDate, DateTime reminderDate)
{
    for (int i = 0; i < 100; i++)
    {
        var incrementedDate = reminderDate.AddYears(-i);
        if (incrementedDate == activityDate)
            return new reminderDTO{ ReminderComboItem = ReminderComboItems.Years, i};
    }
    for (int i = 0; i < 100; i++)
    {
        var incrementedDate = reminderDate.AddMonths(-i);
        if (incrementedDate == activityDate)
            return new ReminderDTO{ ReminderComboItem = ReminderComboItems.Months, i};
    }

   ...
   iterative loop for weeks, days, hours, minutes
   ...

    //default
    var minutes = activityDate.Subtract(reminderDate).TotalMinutes
    return new ReminderDTO{ ReminderComboItem = ReminderComboItems.Months, minutes};
}

I'm trying to have something that's less iterative, the fact that years/months aren't static(diff month lengths and leap years) it makes it a bit difficult. May I get some thoughts/opinions on this please.

\$\endgroup\$

migrated from stackoverflow.com Nov 19 '15 at 22:20

This question came from our site for professional and enthusiast programmers.

  • 1
    \$\begingroup\$ Well you can subtract the years if the month and day and time are the same. You can subtract the months and add the year difference times 12 if the day and time are the same. The rest can be achieved by subtracting the dates and looking at the resulting TimeSpan. \$\endgroup\$ – juharr Nov 11 '15 at 17:32
  • \$\begingroup\$ Hi @juharr THANKS! that will definitely help. Thank you. \$\endgroup\$ – Master Nov 11 '15 at 17:39
1
\$\begingroup\$

Here's how I would do it. First make sure the reminderDate is after the activityDate. Then check if the month, day, and time are the same. If so you can do the year difference. If not then you check if just the day and time are the same and do the month difference (along with the year difference times 12). Otherwise subtract the dates and look at the TimeSpan. If the minutes are not zero then return the TotalMinutes. If the hours are not zero return the TotalHours. If the number of days is divisible by 7 then do the weeks. Otherwise just return the Days.

public static ReminderDTO ReverseAppointment(
    DateTime activityDate, DateTime reminderDate)
{
    if (reminderDate <= activityDate) 
        throw new ArgumentException("reminder cannot be <= activity");

    if (reminderDate.Month == activityDate.Month 
        && reminderDate.Day == activityDate.Day
        && reminderDate.TimeOfDay == activityDate.TimeOfDay)
    {
        return new ReminderDTO
                {
                    ReminderComboItem = ReminderComboItems.Years,
                    Frequency = reminderDate.Year - activityDate.Year
                };
    }

    if (reminderDate.Day == activityDate.Day 
        && reminderDate.TimeOfDay == activityDate.TimeOfDay)
    {
        return new ReminderDTO
                {
                    ReminderComboItem = ReminderComboItems.Months,
                    Frequency =
                        (reminderDate.Month - activityDate.Month)
                        + (12 * (reminderDate.Year - activityDate.Year))
                };

    }

    var difference = reminderDate - activityDate;

    if (difference.Minutes != 0)
    {
        return new ReminderDTO
                {
                    ReminderComboItem = ReminderComboItems.Minutes,
                    Frequency = (int)difference.TotalMinutes
                };
    }
    if (difference.Hours != 0)
    {
        return new ReminderDTO
                {
                    ReminderComboItem = ReminderComboItems.Hours,
                    Frequency = (int)difference.TotalHours
                };
    }

    if (difference.Days % 7 == 0)
    {
        return new ReminderDTO
        {
            ReminderComboItem = ReminderComboItems.Weeks,
            Frequency = difference.Days / 7
        };
    }

    return new ReminderDTO
            {
                ReminderComboItem = ReminderComboItems.Days,
                Frequency = difference.Days
            };
}

Note that if the dates differ by less than a minute you'll end up with 0 days, but I'm assuming all you're dates will differ by at least one minute based on how they are generated.

\$\endgroup\$
  • \$\begingroup\$ Almost, it's missing weeks. Thanks for the help! \$\endgroup\$ – Master Nov 11 '15 at 17:55
  • \$\begingroup\$ @Master Yeah, fixed it to include the weeks as well. \$\endgroup\$ – juharr Nov 11 '15 at 17:58
  • \$\begingroup\$ Any difference between using Days and TotalDays? \$\endgroup\$ – Master Nov 11 '15 at 17:59
  • \$\begingroup\$ @Master Well TotalDays will include a fraction portion for any hour/minute/second different, but since we've established there isn't a difference at those levels then the only difference is that one is int and the other is double. So better to use Days at that point. \$\endgroup\$ – juharr Nov 11 '15 at 18:00
  • \$\begingroup\$ Also you don't have a case for adding weeks. To do that you can just do date.AddDays(7 * frequency). And you could just reduce all of your cases to one return. \$\endgroup\$ – juharr Nov 11 '15 at 18:08

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy