根据工作日和小时数 + 节假日添加工作时间以更正价格类别



我想将正确的小时数绑定到正确的工作时间。工作周为周一至周日。根据一天中的时间,工作有不同的价格。基于一天中完成的时间的工作价格称为期间。我们使用 24 小时时间格式。

例:

  • 时段 1:周一至周五,00:00 - 07:00
  • 时段2:周一至周五,07:00 - 20:00
  • 时段3:周一至周五,20:00 - 22:00
  • 时段4:周一至周五,22:00 - 23:59(午夜)
  • 时段5:周六至周日,00:00 - 07:00
  • 时段6:周六至周日,07:00 - 22:00
  • 时段7:周六至周日,22:00 - 23:59(午夜)
  • 期间8:节假日,00:00 - 23:59

句点表示如下:

public class Period
{
public Period()
{
}
public string Name { get; set; }
public int Days { get; set; }
public bool Holiday { get; set; }
public TimeSpan Start { get; set; }
public TimeSpan End { get; set; }
}

days 是 int,但值将来自这个枚举:

[Flags]
public enum Workweek
{
Sunday = 1,
Monday = 2,
Tuesday = 4,
Wednesday = 8,
Thursday = 16,
Friday = 32,
Saturday = 64
}

何时Days属性的期间62这意味着期间从星期一到星期五有效,当天数为:65期间为星期六至星期日。当天数为:6期间为星期一到星期二。

如果Holiday为 true,则表示该期间仅在节假日有效。假日日优先于正常日或周末。

工作班次表示如下:

public class Work
{
public Work()
{
}
public string Name { get; set; }
public DateTime Start { get; set; }
public DateTime End { get; set; }
}

假设我有List<Work>List<Period>如何将工作时间绑定到正确的时间段?每个时期都有不同的定价。

例:

情况 1:如果您在周一 15:00 和 23:00 之间轮班,那么该工作班次将是这样的:

  • 周期2:5小时
  • 周期3: 2小时
  • 时段4:1小时

案例 1.1:如果该特定星期一是假期,那么它将是:

  • 周期8: 8 小时

情况 2:如果工作在星期一 20:00 开始,到第二天 04:00 结束,结果将是:

  • 周期3: 2小时
  • 时段4: 2 小时
  • 周期1: 4 小时

案例2.2:如果该星期一是假期,它将是:

  • 时段8: 4 小时
  • 周期1: 4 小时

假期是List<DateTime>

如何匹配小时数以更正时间段?

到目前为止我尝试过:

Work work = new Work()
{
Name = Demo,
Star = new DateTime(2017,05,02,15,00,00);
End = new DateTime(2017,05,02,23,00,00);
};
List<Period> periods = new List<Period>();
foreach (var period in periods)
{
Workweek shiftDay = (Workweek)Enum.Parse(typeof(Workweek), work.Start.DayOfWeek, true); // i think this is wrong, because in the case where the end date is in the next day

Workweek periodDay = (Workweek)period.Days;
if ((shiftDay & periodDay) == shiftDay)
{
// the work matches the period
}
}

我想我应该使用 foreach 并在开始日期和结束日期之间循环每一秒,并检查该秒是否与周期日匹配。

像这样:

public static IEnumerable<DateTime> EachSecond(this Work work)
{
DateTime currentSecond = new DateTime(work.Start.Year, work.Start.Month, work.Start.Day, work.Start.Hour, work.Start.Minute, work.Start.Second, work.Start.Millisecond);
while (currentSecond <= wor.kEnd)
{
yield return currentSecond;
currentSecond = currentSecond.AddSeconds(1);
}
}
Work work = new Work()
{
Name = Demo,
Star = new DateTime(2017,05,02,15,00,00);
End = new DateTime(2017,05,02,23,00,00);
};
List<Period> periods = new List<Period>();
foreach (var second in work.EachSecond())
{
Workweek shiftSecond = (Workweek)Enum.Parse(typeof(Workweek), second.DayOfWeek, true);
foreach (var period in periods)
{
Workweek periodDay = (Workweek)period.Days;
if ((shiftSecond & periodDay) == shiftSecond)
{
}
}
}

工作示例:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Diagnostics;
public class Program
{
public static void Main( string[] args )
{
var periods = new List<Period> {
new Period( "1", Days.Workdays, TimeSpan.FromHours(0), TimeSpan.FromHours(7) ),
new Period( "2", Days.Workdays, TimeSpan.FromHours(7), TimeSpan.FromHours(20) ),
new Period( "3", Days.Workdays, TimeSpan.FromHours(20), TimeSpan.FromHours(22) ),
new Period( "4", Days.Workdays, TimeSpan.FromHours(22), TimeSpan.FromHours(24) ),
new Period( "5", Days.Weekend, TimeSpan.FromHours(0), TimeSpan.FromHours(7) ),
new Period( "6", Days.Weekend, TimeSpan.FromHours(7), TimeSpan.FromHours(22) ),
new Period( "7", Days.Weekend, TimeSpan.FromHours(22), TimeSpan.FromHours(24) ),
new Period( "8", Days.Holiday, TimeSpan.FromHours(0), TimeSpan.FromHours(24) ),
};
var holidays = new List<DateTime> {
new DateTime( 2017, 1, 1 ),
new DateTime( 2017, 1, 3 ),
new DateTime( 2017, 1, 6 ),
};
var sc = new ShiftCalculator( periods, holidays );
var shiftperiods = sc.GetShiftPeriods( new DateTime( 2016, 12, 31, 22, 00, 00 ), new DateTime( 2017, 01, 07, 08, 00, 00 ) ).ToList();
foreach ( var sp in shiftperiods )
{
Console.WriteLine( "{0} - {1} - {2} - {3:00.00}h", sp.Period.Name, sp.Period.Days, sp.Start, sp.Duration.TotalHours );
}
}
}
[Flags]
enum Days : byte
{
Sunday = 1,
Monday = 2,
Tuesday = 4,
Wednesday = 8,
Thursday = 16,
Friday = 32,
Saturday = 64,
Holiday = 128,
Workdays = Monday | Tuesday | Wednesday | Thursday | Friday,
Weekend = Saturday | Sunday,
}
[DebuggerDisplay("{Name}: {Days} ({Start}-{End})")]
class Period
{
public Period( string name, Days days, TimeSpan start, TimeSpan end )
{
if ( days.HasFlag( Days.Holiday ) && days != Days.Holiday )
throw new ArgumentException( "days" );
if ( start > end )
throw new ArgumentException( "end" );
Name = name;
Days = days;
Start = start;
End = end;
}
public string Name { get; private set; }
public Days Days { get; private set; }
public TimeSpan Start { get; private set; }
public TimeSpan End { get; private set; }
}
class ShiftPeriod
{
public Period Period { get; set; }
public DateTime Start { get; set; }
public TimeSpan Duration { get; set; }
}
class ShiftCalculator
{
private readonly List<Period> _periods;
private readonly List<DateTime> _holidays;
public ShiftCalculator( IEnumerable<Period> periods, IEnumerable<DateTime> holidays )
{
_periods = periods.ToList();
_holidays = holidays.Select( e => e.Date ).ToList();
}
public IEnumerable<ShiftPeriod> GetShiftPeriods( DateTime start, DateTime end )
{
if ( start > end ) throw new ArgumentException( "end" );
var current = start;
while ( current < end )
{
var period = GetPeriodByDateTime( current );
var next = current.Date + period.End;
if ( next > end )
{
next = end;
}
yield return new ShiftPeriod
{
Period = period,
Start = current,
Duration = next - current,
};
current = next;
}
}
private Days GetDayFromDateTime( DateTime datetime )
{
Days day;
if ( _holidays.Contains( datetime.Date ) )
{
day = Days.Holiday;
}
else
{
switch ( datetime.DayOfWeek )
{
case DayOfWeek.Sunday:
day = Days.Sunday;
break;
case DayOfWeek.Monday:
day = Days.Monday;
break;
case DayOfWeek.Tuesday:
day = Days.Tuesday;
break;
case DayOfWeek.Wednesday:
day = Days.Wednesday;
break;
case DayOfWeek.Thursday:
day = Days.Thursday;
break;
case DayOfWeek.Friday:
day = Days.Friday;
break;
case DayOfWeek.Saturday:
day = Days.Saturday;
break;
default:
throw new InvalidOperationException();
}
}
return day;
}
private Period GetPeriodByDateTime( DateTime datetime )
{
var day = GetDayFromDateTime( datetime );
var timeOfDay = datetime.TimeOfDay;
var period = _periods.Where(
e => e.Days.HasFlag( day ) && e.Start <= timeOfDay && e.End > timeOfDay )
.FirstOrDefault();
if ( period == null )
{
throw new InvalidOperationException();
}
return period;
}
}

.net 小提琴

生成的输出

7 - 周末 - 12/31/2016 10:00:00 PM - 02.00h 8 - 假日 - 1/1/2017 12:00:00 AM - 24.00h 1 - 工作日 - 1/2/2017 12:00:00 AM - 07.00h 2 - 工作日 - 1/2/2017 7:00:00 AM - 13.00h 3 - 工作日 - 1/2/2017 8:00:00 PM - 02.00h 4 - 工作日 - 1/2/2017 10:00:00 PM - 02.00h 8 - 假日 - 1/3/2017 12:00:00 AM - 24.00h 1 - 工作日 - 1/4/2017 12:00:00 AM - 07.00h 2 - 工作日 - 1/4/2017 7:00:00 AM - 13.00h 3 - 工作日 - 1/4/2017 8:00:00 PM - 02.00h 4 - 工作日 - 1/4/2017 10:00:00 PM - 02.00h 1 - 工作日 - 1/5/2017 12:00:00 AM - 07.00h 2 - 工作日 - 1/5/2017 7:00:00 AM - 13.00h 3 - 工作日 - 1/5/2017 8:00:00 PM - 02.00h 4 - 工作日 - 1/5/2017 10:00:00 PM - 02.00h 8 - 假日 - 1/6/2017 12:00:00 AM - 24.00h 5 - 周末 - 1/7/2017 12:00:00 AM - 07.00h 6 - 周末 - 1/7/2017 7:00:00 AM - 01.00h

试试这样的事情。 我不知道为什么当您可以使用标准星期几时,您需要自定义工作周。 无论如何,我还是按照你的要求去做了。

using System.Collections.ObjectModel;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
namespace ConsoleApplication57
{
class Program
{
static void Main(string[] args)
{
}
}
public class Period
{
public static List<Period> periods = new List<Period>() {
new Period() { Name = "Period1", Days =  new Workweek[] { Workweek.Monday, Workweek.Tuesday, Workweek.Wednesday, Workweek.Thursday, Workweek.Friday}, Holiday = false, Start = new TimeSpan(0,0,0), End = new TimeSpan(7,0,0)},
new Period() { Name = "Period2", Days =  new Workweek[] { Workweek.Monday, Workweek.Tuesday, Workweek.Wednesday, Workweek.Thursday, Workweek.Friday}, Holiday = false, Start = new TimeSpan(7,0,0), End = new TimeSpan(20,0,0)},
new Period() { Name = "Period3", Days =  new Workweek[] { Workweek.Monday, Workweek.Tuesday, Workweek.Wednesday, Workweek.Thursday, Workweek.Friday}, Holiday = false, Start = new TimeSpan(20,0,0), End = new TimeSpan(22,0,0)},
new Period() { Name = "Period4", Days =  new Workweek[] { Workweek.Monday, Workweek.Tuesday, Workweek.Wednesday, Workweek.Thursday, Workweek.Friday}, Holiday = false, Start = new TimeSpan(22,0,0), End = new TimeSpan(24,0,0)},
new Period() { Name = "Period5", Days =  new Workweek[] { Workweek.Saturday, Workweek.Sunday}, Holiday = false, Start = new TimeSpan(0,0,0), End = new TimeSpan(7,0,0)},
new Period() { Name = "Period6", Days =  new Workweek[] { Workweek.Saturday, Workweek.Sunday}, Holiday = false, Start = new TimeSpan(7,0,0), End = new TimeSpan(22,0,0)},
new Period() { Name = "Period7", Days =  new Workweek[] { Workweek.Saturday, Workweek.Sunday}, Holiday = false, Start = new TimeSpan(22,0,0), End = new TimeSpan(24,0,0)},
new Period() { Name = "Period8", Days = null, Holiday = true, Start = new TimeSpan(0,0,0), End = new TimeSpan(24,0,0)},
};
public string Name { get; set; }
public Workweek[] Days { get; set; }
public bool Holiday { get; set; }
public TimeSpan Start { get; set; }
public TimeSpan End { get; set; }
public static string GetName(DateTime startTime, DateTime endTime, Boolean holiday)
{
string name = "";
if (holiday)
{
name = "Period8";
}
else
{
foreach (Period period in periods)
{
Boolean dayMatch = period.Days.Select(x => x == (Workweek)(2 ^ (int)startTime.DayOfWeek)).Any();
if (dayMatch)
{
if ((startTime.TimeOfDay > period.Start) && (endTime.TimeOfDay < period.End))
{
name = period.Name;
break;
}
}
}
}
return name;
}
}
public enum Workweek
{
Sunday = 1,
Monday = 2,
Tuesday = 4,
Wednesday = 8,
Thursday = 16,
Friday = 32,
Saturday = 64
}
public class Work
{
public string Name { get; set; }
public DateTime Start { get; set; }
public DateTime End { get; set; }
}

}

最新更新