Сколько дней добавить для «полугодового» - PullRequest
6 голосов
/ 13 декабря 2011

У меня есть тип enum с именем PaymentFrequency, значения которого указывают, сколько платежей в год производится ... Итак, у меня есть

public enum PaymentFrequency
{
    None             = 0,
    Annually         = 1,
    SemiAnnually     = 2,
    EveryFourthMonth = 3,
    Quarterly        = 4,
    BiMonthly        = 6,
    Monthly          = 12,
    EveryFourthWeek  = 13,
    SemiMonthly      = 24,
    BiWeekly         = 26,
    Weekly           = 52
}

На основе NumberOfPayments, PaymentFrequency и FirstPaymentDate (типа DateTimeOffset) я хочу вычислить LastPaymentDate. Но у меня проблема с выяснением, сколько единиц времени (дней, месяцев) добавить в случае полугодия ...

    switch (paymentFrequency)
    {
        // add years...
        case PaymentFrequency.Annually:
            LastPaymentDate = FirstPaymentDate.AddYears(NumberOfPayments - 1); 
            break;
        // add months...
        case PaymentFrequency.SemiAnnually:
            LastPaymentDate = FirstPaymentDate.AddMonths((NumberOfPayments - 1) * 6); // 6 months
            break;
        case PaymentFrequency.EveryFourthMonth:
            LastPaymentDate = FirstPaymentDate.AddMonths((NumberOfPayments - 1) * 4); // 4 months
            break;
        case PaymentFrequency.Quarterly:
            LastPaymentDate = FirstPaymentDate.AddMonths((NumberOfPayments - 1) * 3); // 3 months
            break;
        case PaymentFrequency.BiMonthly:
            LastPaymentDate = FirstPaymentDate.AddMonths((NumberOfPayments - 1) * 2); // 2 months
            break;
        case PaymentFrequency.Monthly:
            LastPaymentDate = FirstPaymentDate.AddMonths(NumberOfPayments - 1);
            break;
        // add days...
        case PaymentFrequency.EveryFourthWeek:
            LastPaymentDate = FirstPaymentDate.AddDays((NumberOfPayments - 1) * 4 * 7); // 4 weeks (1 week = 7 days)
            break;
        case PaymentFrequency.SemiMonthly:
            // NOTE: how many days in semi month? AddMonths (0.5) does not work :)
            LastPaymentDate = FirstPaymentDate.AddMonths((NumberOfPayments - 1) * 0.5); // 2 weeks (1 week = 7 days)
            break;
        case PaymentFrequency.BiWeekly:
            LastPaymentDate = FirstPaymentDate.AddDays((NumberOfPayments - 1) * 2 * 7); // 2 weeks (1 week = 7 days)
            break;
        case PaymentFrequency.Weekly:
            LastPaymentDate = FirstPaymentDate.AddDays((NumberOfPayments - 1) * 7); // 1 week (1 week = 7 days)
            break;
        case PaymentFrequency.None:
        default:
            throw new ArgumentException("Payment frequency is not initialized to valid value!", "paymentFrequency");
    }

Итак, сколько дней / месяцев я должен использовать при использовании SemiMonthly? Возможно ли это, даже не зная точного количества дней для каждого месяца между? Или это действительно просто, и у меня только что кончился кофеин, и я не вижу леса за деревьями:)

Ответы [ 4 ]

7 голосов
/ 13 декабря 2011

В течение полугодового месяца, если ваш первый платеж всегда был первым платежом месяца (то есть, в любое время с 1-го по 13-е, начиная с 13-го, проблематично, как обсуждалось в комментариях), вы можете сделать так:следует:

 // assuming first payment will be 1st of month, add month for every 2 payments
 // num payments / 2 (int division, remainder is chucked)
 // then add 15 days if this is even payment of the month
 LastPaymentDate = FirstPaymentDate.AddMonths((NumberOfPayments - 1) / 2)
     .AddDays((NumberOfPayments % 2) == 0 ? 15 : 0);

Таким образом, для 1-го платежа это добавит 0 месяцев и 0 дней, поэтому будет 1-й датой оплаты.Для 2-го платежа это добавит 0 месяцев (int dividision, остаток отсчитывается) и 15 дней для 16-го числа месяца.Для 3-го платежа это добавит 1 месяц (1/3) и 0 дней для 1-го числа следующего месяца и т. Д.

Это предполагает, что FirstPaymentDate будет иметь значение 1-го числа данного месяца.Вы, вероятно, можете увидеть, куда идти отсюда, если вы хотите, чтобы 16-е было начальной датой и т. Д.

Имеет смысл?

Итак, чтобы проиллюстрировать, если бы у нас было:

DateTime LastPaymentDate, FirstPaymentDate = new DateTime(2011, 12, 5);

for(int numOfPayments=1; numOfPayments<=24; numOfPayments++)
{
    LastPaymentDate = FirstPaymentDate.AddMonths((numOfPayments - 1) / 2)
        .AddDays((numOfPayments % 2) == 0 ? 15 : 0);

    Console.WriteLine(LastPaymentDate);
}

Этот цикл даст нам:

12/5/2011 12:00:00 AM
12/20/2011 12:00:00 AM
1/5/2012 12:00:00 AM
// etc...
10/20/2012 12:00:00 AM
11/5/2012 12:00:00 AM
11/20/2012 12:00:00 AM
1 голос
/ 13 декабря 2011

Основными парами для полугодовых платежей являются:

  • 1 и 16 (1-й и 16-й день месяца)
  • 15 и (2 | 3)?(15-й и последний день месяца)

Загляните и выберите

1 голос
/ 13 декабря 2011

Поскольку месяцы имеют разную продолжительность, вы не можете просто добавить заранее заданное число.Вы должны знать, с каким месяцем вы имеете дело, и идти оттуда.

Если вы знаете, что 1-й и 16-й числа месяца являются датами исполнения, то последний платеж - 16 декабря (при условии, что вы рассчитываетеза календарный год).

0 голосов
/ 22 марта 2017

У меня недавно была та же проблема, но мне нужно было разрешить ввод любой даты.Это немного беспорядок и требует рефакторинга, но это то, что я придумал до сих пор.У февраля были некоторые проблемы, которые мне пришлось взломать.

Date returnDate;

if (numberOfPayments % 2 == 0)
{
   returnDate = date.AddMonths(numberOfPayments / 2);

    if (date.Day == DateTime.DaysInMonth(date.Year, date.Month))//Last day of the month adjustment
    {
        returnDate = new Date(returnDate.Year, returnDate.Month, DateTime.DaysInMonth(returnDate.Year, returnDate.Month));
    }
}
else
{
    returnDate = date.Day <= 15 ? date.AddDays(15).AddMonths((numberOfPayments - 1) / 2) : date.AddDays(-15).AddMonths((numberOfPayments + 1) / 2);
    if (date.Day == DateTime.DaysInMonth(date.Year, date.Month))//Last day of the month adjustment
    {
        returnDate = new Date(returnDate.Year, returnDate.Month, 15);
    }
    else if (date.Month == 2 && date.Day == 14)
    {
        returnDate = returnDate.AddMonths(-1);
        returnDate = new Date(returnDate.Year, returnDate.Month, returnDate.Month == 2 ? 28 : 29);
    }
    else if (date.Month == 2 && date.Day == 15)
    {
        returnDate = returnDate.AddMonths(-1);
        returnDate = new Date(returnDate.Year, returnDateMonth, DateTime.DaysInMonth(returnDate.Year, returnDate.Month));
    }
}

return returnDate;
...