Nicklas Christensen
Nicklas Christensen

Reputation: 27

C# Datetime - Add days or month

I'm trying to add days or month to a datetime. What determines rather it should add days or month to the datetime is what dayOrMonth ends with. So for example if dayOrMonth ends with MM it should add month, if it ends with DD it should add days.

dayOrMonth could look like this "90DD" (should add 90 days) and "90MM" should add 90 month.

I'm thinking about creating an extension method of some kind, but I'm struggling abit with the approach to this, as adding more if statements is not an option.

                    //... Set payment dates.
                    string dayOrMonth;
                    for (int x = 0; x < installmentDates.Count; x++)
                    {
                        if (installmentDates.Count > 0)
                        {
                            installmentdDateRow[colName] = installmentdDateRow[colName] + Convert.ToDateTime(installmentDates[x]).ToString("dd'-'MM'-'yyyy") + "\n";

                            //... Future payment dates.
                            int futurePaymentColumn = installmentdFuturePayments.Table.Columns.IndexOf(colName);
                            if (colName == "1. rate" && installmentDates.Count - 1 == x)
                            {
                                installmentdFuturePayments[futurePaymentColumn + 1] = installmentdFuturePayments[futurePaymentColumn + 1] + Convert.ToDateTime(installmentDates[x]).AddMonths(3).ToString("dd'-'MM'-'yyyy") + "\n";
                            }
                            if (colName == "2. rate" && installmentDates.Count - 1 == x && Functions.GetProductInfo(unit.Key.ToString().Split('-')[0])[9] != "€ 0,00")
                            {
                                installmentdFuturePayments[futurePaymentColumn + 1] = installmentdFuturePayments[futurePaymentColumn + 1] + Convert.ToDateTime(installmentDates[x]).AddMonths(3).ToString("dd'-'MM'-'yyyy") + "\n";
                            }
                        }
                    }

Upvotes: 0

Views: 1979

Answers (3)

Matt Johnson-Pint
Matt Johnson-Pint

Reputation: 241525

You have described an input string composed of two parts:

  • An integer magnitude to apply to some operation
  • A two character string defining the operation to use

As such, you know there should always be at least three characters. You also know the trailing two characters define the operation, so you can use Substring to separate those characters from the rest of the string.

An extension method is a great idea. It should include tests to help enforce the format of the input string, and make it easy to parse the numeric component.

public static DateTime ApplyInput(this DateTime dt, string input)
{
    if (input == null)
    {
        throw new ArgumentNullException(nameof(input), "The input string must not be null.");
    }

    if (input.Length < 3)
    {
        throw new ArgumentException("The input string is too short to include both a number and an operation.", nameof(input));
    }

    string numberChars = input.Substring(0, input.Length - 2);
    if (!int.TryParse(numberChars, out int number))
    {
        throw new ArgumentException("The start of the input string must be an integer.", nameof(input));
    }

    string endingChars = input.Substring(input.Length - 2);
    switch (endingChars.ToUpperInvariant())
    {
        case "MM":
            return dt.AddMonths(number);
        case "DD":
            return dt.AddDays(number);
        default:
            throw new ArgumentException($"The characters {endingChars} were not recognized as a valid operation.", nameof(input));
    }
}

This approach will perform better than using RegEx, Contains, or Replace. It is also extensible by adding more case statement to the switch.

Note that .ToUpperInvariant() makes the operation characters case-insensitive so you can pass mm or dd if you like. If you don't wan't that behavior, then simply remove .ToUpperInvariant().

Upvotes: 2

Nicklas Christensen
Nicklas Christensen

Reputation: 27

I solved my problem by creating this extension method

  public static DateTime test1(this DateTime d, string inputType)
    {
        if (inputType.Contains("DD"))
        {
            d = d.AddDays(Convert.ToInt32(inputType.Replace("DD", "")));
        }
        if (inputType.Contains("MM"))
        {
            d = d.AddMonths(Convert.ToInt32(inputType.Replace("MM", "")));
        }
        return d;
    }

Upvotes: 0

davedno
davedno

Reputation: 349

Using StackOverflow - Seperating characters and numbers

You can use a regular expression to seperate the numbers from the characters in a given string like so:

Regex re = new Regex(@"([a-zA-Z]+)(\d+)");
Match result = re.Match(input);

string alphaPart = result.Groups[1].Value;
string numberPart = result.Groups[2].Value;

Then you can create a factory method or a project wide reference where you can use that code snippet to achieve what youre asking:

public DateTime AddDaysOrMonths(string input, DateTime dt)
{
     Regex re = new Regex(@"([a-zA-Z]+)(\d+)");
     Match result = re.Match(input);

     string alphaPart = result.Groups[1].Value;
     string numberPart = result.Groups[2].Value;

     if(alphaPart == "DD")
     {
       int days;
       if(Integer.TryParse(numberPart,out days) == true)
       {
           dt.AddDays(days)
       }
     }
     else if (alphaPart == "MM")
     {
       int months;
       if(Integer.TryParse(numberPart,out months) == true)
       {
           dt.AddMonths(months);
       }
     }
    return dt;
}

Ofcourse, you should implement more extenstive error/null checking and better string comparison but this should be enough to get you going in the right direction.

Upvotes: 0

Related Questions