6

我有一个枚举类型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

4 回答 4

7

对于半月,如果您的第一笔付款也始终是当月的第一笔付款(即,从 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);

因此,对于第一次付款,这将增加 0 个月和 0 天,因此是第一次付款日期。对于第二次付款,这将增加 0 个月(整数除法,余数被丢弃)和第 16 个月的 15 天。对于第 3 次付款,这将增加 1 个月 (1 / 3) 和下个月 1 日的 0 天,依此类推。

这是假设 FirstPaymentDate 将在某个给定月份的第一天。如果您想将 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
于 2011-12-12T22:15:22.973 回答
1

因为月份有不同的长度,所以您不能只添加一个预定义的数字。你必须知道你正在处理哪个月份,然后从那里开始。

如果您知道一个月的 1 日和 16 日是到期日,那么最后一次付款是 12 月 16 日(假设您正在计算一个日历年)。

于 2011-12-12T22:09:17.877 回答
1

半月付款的基本配对是:

  • 1 和 16(一个月的第 1 天和第 16 天)
  • 15 和 (2|3)?(每月 15 日和最后一天)

偷看和选择

于 2011-12-12T22:11:23.843 回答
0

我最近遇到了同样的问题,但我需要允许输入任何日期。这有点乱,需要重构,但这是我到目前为止想出的。二月有一些我必须解决的问题。

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;
于 2017-03-22T18:22:49.013 回答