如何从日期开始获得正确的工资期?

我觉得这比数学问题更重要。 我公司的员工遍布全国各地。 公司的某些部分处于“奇怪的”工资周期,有些部分处于“均匀”状态。 我将给定支付期的开始日期称为“payperiod”。 我需要做两件事:

1)确定给定日期下降的工资期

//Something like this: public static DateTime getPayPeriodStartDate(DateTime givenDate, string EvenOrOdd) { .. } 

2)获取两个日期之间的工资期列表:

 //Something like this: public static List getPayPeriodsBetween(DateTime start, DateTime end, string EvenOrOdd) { .. } 

我使用几个日期作为固定标准,以此作为未来支付期的日期。 偶数和奇数的固定标准日期如下:

  • 甚至 – 01/04/09
  • 奇怪 – 01/11/09

每个支付期从本周的星期日开始,持续两周。 例如,使用上述标准日期,第一个均匀支付期从2009年4月1日开始,到2009年1月17日结束。 第一个奇数支付期从09年11月1日开始,到2009年1月24日结束。 如您所见,有一些重叠。 我们有数千名员工,因此有必要将他们分开。

我有一个基于周数的解决方案,但它很笨重,每个新的一年都必须“修复”。 我想知道你将如何处理这个问题。

没有完全优化或测试,但这是我提出的:

 const int DaysInPeriod = 14; static IEnumerable GetPayPeriodsInRange(DateTime start, DateTime end, bool isOdd) { var epoch = isOdd ? new DateTime(2009, 11, 1) : new DateTime(2009, 4, 1); var periodsTilStart = Math.Floor(((start - epoch).TotalDays) / DaysInPeriod); var next = epoch.AddDays(periodsTilStart * DaysInPeriod); if (next < start) next = next.AddDays(DaysInPeriod); while (next <= end) { yield return next; next = next.AddDays(DaysInPeriod); } yield break; } static DateTime GetPayPeriodStartDate(DateTime givenDate, bool isOdd) { var candidatePeriods = GetPayPeriodsInRange(givenDate.AddDays(-DaysInPeriod), givenDate.AddDays(DaysInPeriod), isOdd); var period = from p in candidatePeriods where (p <= givenDate) && (givenDate < p.AddDays(DaysInPeriod)) select p; return period.First(); } 

我没有测试过很多测试用例,但我认为这符合要求:

 public static DateTime getPayPeriodStartDate(DateTime givenDate, string EvenOrOdd) { DateTime newYearsDay = new DateTime(DateTime.Today.Year, 1, 1); DateTime firstEvenMonday = newYearsDay.AddDays((8 - (int)newYearsDay.DayOfWeek) % 7); DateTime firstOddMonday = firstEvenMonday.AddDays(7); TimeSpan span = givenDate - (EvenOrOdd.Equals("Even") ? firstEvenMonday : firstOddMonday); int numberOfPayPeriodsPast = span.Days / 14; return (EvenOrOdd.Equals("Even") ? firstEvenMonday : firstOddMonday).AddDays(14 * numberOfPayPeriodsPast); } public static List getPayPeriodsBetween(DateTime start, DateTime end, string EvenOrOdd) { DateTime currentPayPeriod = getPayPeriodStartDate(start, EvenOrOdd); if (currentPayPeriod < start) currentPayPeriod = currentPayPeriod.AddDays(14); List dtList = new List(); while (currentPayPeriod <= end) { dtList.Add(currentPayPeriod); currentPayPeriod = currentPayPeriod.AddDays(14); } return dtList; } 

我相信它可以改进。

我需要做类似的事情,并且能够使用LINQ轻松完成。 只需构建偶数和奇数列表,然后根据需要在奇数/偶数之间查询。 此外,我建议你移动到一个emum的EvenOrOdd参数,你有固定的值。

几个月前我遇到了类似的问题,最后我写了一个快速脚本,在每个付费期间在数据库中创建条目,所以我从来没有真正做过数学计算。 这样,系统的工作速度相同,并且每次请求周期时都不需要进行任何慢速迭代。

话虽这么说,你总是可以采取开始日期,并且一遍又一遍地增加两周(或者你的期间长),直到你到达你在函数调用中指定的日期。 这有点难看,它在生产中的时间越长,它就越慢(因为日期越来越远)。

这两种方式都很容易实现,这只是你手头有什么样的资源来解决这个问题。

因此,对于数字1:从1/4/2009或1/11/2009开始(取决于偶数/奇数支付周)并添加2周,直到给定日期小于您正在测试的日期+ 2周。 那是这个时期的开始。

对于2号:同样的事情,从日期开始并添加2周,直到你在日期范围内。 当你在那里时,将每个项目添加到列表中。 一旦你超过了最后一个日期,就要打开循环并返回shiny的新列表。

如果您使用我的方法并使用数据库来存储所有这些信息,它将变为2个简单查询:

1) SELECT * FROM payperiods WHERE startdate<=givenDate ORDER BY startdate LIMIT 1

2) SELECT * FROM payperiods WHERE startdate>=givenDate AND enddate<=givenDate ORDER BY startdate

它完美地运作。 我测试过了。

  public static DateTime GetFirstDayOfWeek(DateTime dayInWeek) { CultureInfo _culture = (CultureInfo)CultureInfo.CurrentCulture.Clone(); CultureInfo _uiculture = (CultureInfo)CultureInfo.CurrentUICulture.Clone(); _culture.DateTimeFormat.FirstDayOfWeek = DayOfWeek.Monday; _uiculture.DateTimeFormat.FirstDayOfWeek = DayOfWeek.Monday; System.Threading.Thread.CurrentThread.CurrentCulture = _culture; System.Threading.Thread.CurrentThread.CurrentUICulture = _uiculture; // CultureInfo defaultCultureInfo = CultureInfo.CurrentCulture; DayOfWeek firstDay = _culture.DateTimeFormat.FirstDayOfWeek; DateTime firstDayInWeek = dayInWeek.Date; // Logic Of getting pay period Monday(Odd monday) int i = Convert.ToInt32(firstDay); while (firstDayInWeek.DayOfWeek != firstDay) if (i % 2 != 0) { firstDayInWeek = firstDayInWeek.AddDays(-1); } else { firstDayInWeek = firstDayInWeek.AddDays(-2); } return firstDayInWeek; }