在讨论问题的解决方案之前,我想尝试澄清对所传达内容的困惑。如果我们采用您的日程安排并将字母替换为我们得到的时间表
C, A, C, A
19:15 to 7:14, 7:15 to 19:14, 19:15 to 7:14, 7:15 to 19:14,
这个顺序看起来合乎逻辑,但你转向
D, B, D, B, A, C, A, C,
7:15 to 19:14, 19:15 to 7:14, 7:15 to 19:14, 19:15 to 7:14, 7:15 to 19:14, 19:15 to 7:14, 7:15 to 19:14, 19:15 to 7:14,
这个序列本身很好,但是当你结合这两个序列时就会出现问题。在组合点你得到
C, A, D, B
19:15 to 7:14, 7:15 to 19:14, 7:15 to 19:14, 19:15 to 7:14,
从
A, C, B, D
7:15 to 19:14, 19:15 to 7:14, 19:15 to 7:14, 7:15 to 19:14,
您仍然为自己辩护,这种看似不一致的情况可能是有原因的,即整个班次似乎都被跳过了。
其次你说你有 4 个班次,如果这完全正确,那么你可以有一个 C、B、C、B 的序列并且完全有效,但我猜情况并非如此,你实际上只有有 2 个班次,但您可能还有 2 个工作人员或其他影响,我还注意到他们似乎是成对的班次,因此您的第一张桌子可能会更好地显示为:
Shift A1 from 7:15 to 19:14
Shift A2 from 19:15 to 7:14
Shift B1 from 7:15 to 19:14
Shift B2 from 19:15 to 7:14
这仍然不能解释看似缺失的 Shifts,但它有助于澄清一些你正在努力的目标。
再次为您辩护,这些都没有任何区别,因为我们实际上只使用以下模式在哪一天工作的轮班工作:
C、A、C、A、D、B、D、B、A、C、A、C、B、D、B、D
当然,当 Matt Wilko 说您需要提供第一个班次的开始日期(19:15 到 7:14 或 C)时,他确实表示了函数的一个参数。
当然,只要为最终开发人员明确定义了所需的注意事项,这一切都不会限制人们为此创建函数:
使用 C# 语法和功能编写,因为我在 C# 中编码速度更快,但同时也是一名 VBA 程序员,我知道它可以很容易地翻译成 VBA
/*
Parameters: SeqStartDate (DateTime) - The date that the beginning of the schedule sequence falls upon (aka the date that the first C of C, A, C, A falls on)
RequstPeriod (DateTime) - The specific period you are wanting the schedule for.
Returns: Shift (int) - A numeric representation of the specific shift being worked, for the requested time period
(0 = No Shift, 1 = Shift A, 2 = Shift C, 3 = Shift D, 4 = Shift B)
Error: - If an error occurs it will return a negative number corresponding to the error
However for demonstration purposes it will for now just return -1
Assumptions: Since there are missing shifts a zero has been added to account for these
That only future shift schedules are desired
RequstPeriod must occur at least a day after the SeqStartDate
RequstPeriod must occur at least a day after this program is being run
Modification Note: This could be made more robust and eliminate some of the assumptions but
I think what is here should give the basic concept and I will leave the
modifying to fit the developers specific needs to the developer
*/
public int GetShift(SeqStartDate as DateTime, RequstPeriod as DateTime)
{
// First Validate Inputs
// Today’s Date 1 Second past Midnight
TodayIs = ((DateTime.Now()).Date).AddTicks(1);
TimeSpan SeqTSpan = RequstPeriod.Subtract(SeqStartDate)
if (SeqTSpan.Minutes < 1440)
{
return -1;
}
TimeSpan TodayTSpan = RequstPeriod.Subtract(TodayIs)
if (TodayTSpan.Minutes < 1440)
{
return -1;
}
long SchdMins = 0;
long SeqShftr = 0;
int SchdIndx = 0;
// A Zero represents a missing shift within the continuous schedule sequence
int ShftSchedSeq[] = {1,2,1,0,3,4,3,4,1,2,1,2,0,4,3,4,3,2};
long ShftSeqStartMins[] = {57,1155,1497,2595,2937,4035,4377,5475,5817,6915,7257,8355,5697,9795,10137,11235,11577,12675}
const long FirstStartTimeMin = 57;
const int IndxCnt = 18; // Note C# is a 0 based array thus the adjustment later
// The following assumes Integer division truncates and gives a number from 1 to 8 in SeqShftr
TimeSpan SeqShftrTSpan = TodayIs.Subtract((SeqStartDate.Date).AddTicks(1))
// Note % means Modulo to ease translation
SeqShftr = ((((SeqShftrTSpan.Minutes) / 1440) % 9) * 2);
SchdMins = SeqTSpan.Minutes % 12960
// Is the SchdMins less than smallest value in Shift Schedule Array?
if (SchdMins < FirstStartTimeMin)
{
// If yes then it is part of the previous sequence shift which would be the last sequence shift
ShftIndx = IndxCnt - 1;
}
else
{
// For Loop Counts Down from MaxIndx-1 to 0
for (int Indx = (IndxCnt-1); Indx => 0; Indx—-)
{
if (ShftSeqStartMins[Indx] <= SchdMins)
{
ShftIndx = Indx;
break;
}
}
}
ShftIndx = (ShftIndx + SeqShftr);
if (ShftIndx > (IndxCnt - 1))
{
ShftIndx = ShftIndx - (IndxCnt - 1);
}
return ShftSchedSeq[ShftIndx];
}
最后说明:看了你的一个 cmets,我发现你似乎有点困惑——仍然要调整上述程序,你需要做的就是调整 ScheduleSequence 数组(可能还有 ShftSeqStartMins 数组)中的值一旦你弄清楚你想要它是什么,它们应该是什么。正如您在我所指的评论中所说,早班也不能是夜班,反之亦然。