C# DateTime验证:处理跨越午夜的活动转移时段

huangapple go评论72阅读模式
英文:

C# DateTime validation: Handling activity shift periods that span across midnight

问题

I am trying to resolve an issue in regard to an activity status function for a specific condition. The function is trying to check if a signature on the activity falls within a validity period of two dates within a shift.

活动状态函数针对特定条件尝试解决问题,该函数试图检查活动上的签名是否在班次内的两个日期的有效期内。

The activity has a stored start and finish DateTime as follows:

活动具有存储的开始和结束日期时间,如下所示:

var startDate = activity.Start; // ex. new DateTime(2023, 05, 25, 18, 00, 00, DateTimeKind.Utc)
var finishDate = activity.Finish; // ex. new DateTime(2023, 06, 01, 04, 00, 00, DateTimeKind.Utc)

In this instance, shifts would be between 18:00 - 04:00 each day (i.e. 25/05 18:00 -> 26/05 04:00, 26/05 18:00 -> 27/05 04:00 etc) which are stored against a shift integer based on the working day (this will usually be in the range of 1-7). If the time that the signature is made is within the validity period then it will go to a "Live" status, otherwise it will go to an "Awaiting Start" status.

在这种情况下,每天的班次将在18:00 - 04:00之间(例如,25/05 18:00 -> 26/05 04:00,26/05 18:00 -> 27/05 04:00等),这些班次存储在基于工作日的班次整数中(通常在1-7范围内)。如果签名时间在有效期内,则状态将变为“Live”,否则将变为“Awaiting Start”。

Currently the logic in place is as follows. This will return Live if now is after midnight within the validity period of a shift but if the signature time is before midnight, then it will return Awaiting Start.

目前的逻辑如下。如果“now”在班次的有效期内的午夜之后,则会返回“Live”,但如果签名时间在午夜之前,则会返回“Awaiting Start”。

public void SetStatus (T activity)
{
    //.... 
    if (startTime.Date <= DateTime.UtcNow.Date && finishTime.Date >= DateTime.UtcNow.Date)
    {
        if (finishTime.TimeOfDay < startTime.TimeOfDay)
            activity.Status = SetStatusIfShiftCrossesMidnight(startTime, finishTime);

        // ... other checks
    }
}

private string SetStatusIfShiftCrossesMidnight(DateTime startDate, DateTime finishDate)
{
    var now = DateTime.UtcNow;
    
    var start = new DateTime(now.Year, now.Month, now.Day - 1 , startDate.Hour, startDate.Minute, 
                startDate.Second, DateTimeKind.Utc);

    var finish = new DateTime(now.Year, now.Month, now.Day, finishDate.Hour, finishDate.Minute,
                finishDate.Second, DateTimeKind.Utc);

    if (start <= now && finish > now)
        return "Live"; 

    return "Awaiting Start";
}

Any recommendedations on the best way to tackle this?

有关解决此问题的最佳方法的任何建议?

英文:

I am trying to resolve an issue in regard to an activity status function for a specific condition. The function is trying to check if an signature on the activity falls within a validity period of two dates within a shift.

The activity has a stored start and finish DateTime as follows:

var startDate = activity.Start; // ex. new DateTime(2023, 05, 25, 18, 00, 00, DateTimeKind.Utc)
var finishDate = activity.Finish; // ex. new DateTime(2023, 06, 01, 04, 00, 00, DateTimeKind.Utc)

In this instance, shifts would be between 18:00 - 04:00 each day (i.e. 25/05 18:00 -> 26/05 04:00, 26/05 18:00 -> 27/05 04:00 etc) which are stored against a shift integer based on the working day (this will usually be in the range of 1-7). If the time that the signature is made is within the validity period then it will go to a "Live" status, otherwise it will go to a "Awaiting Start" status.

Currently the logic in place is as follows. This will return Live if now is after midnight within the validity period of a shift but if the signature time is before midnight, then it will return Awaiting Start.

public void SetStatus (T activity)
{
    //....
    if (startTime.Date &lt;= DateTime.UtcNow.Date &amp;&amp; finishTime.Date &gt;= DateTime.UtcNow.Date)
    {
        if (finishTime.TimeOfDay &lt; startTime.TimeOfDay)
            activity.Status = SetStatusIfShiftCrossesMidnight(startTime, finishTime);

        // ... other checks
    }
}

private string SetStatusIfShiftCrossesMidnight(DateTime startDate, DateTime finishDate)
{
    var now = DateTime.UtcNow;
    
    var start = new DateTime(now.Year, now.Month, now.Day - 1 , startDate.Hour, startDate.Minute, 
                startDate.Second, DateTimeKind.Utc);

    var finish = new DateTime(now.Year, now.Month, now.Day, finishDate.Hour, finishDate.Minute,
                finishDate.Second, DateTimeKind.Utc);

    if (start &lt;= now &amp;&amp; finish &gt; now)
        return &quot;Live&quot;; 

    return &quot;Awaiting Start&quot;;
}

Any recommendedations on the best way to tackle this?

答案1

得分: 1

如果我理解正确,您有一个shift,它是一个范围

18:00 - 04:00

您有一个时间,比如

23:00

您想要检查该时间是否在这个班次内。如果这是您的任务,那么

// 只有时间,日期部分被忽略
private static bool WithinShift((TimeOnly start, TimeOnly end) shift, TimeOnly time) =>
  (shift.end >= shift.start) 
     ? time >= shift.start && time <= shift.end
     : time >= shift.start || time <= shift.end;

// 考虑日期组件
private static bool WithinShift((DateTime start, DateTime end) shift, DateTime time) =>
  time >= shift.start && time <= shift.end;

例如

var shift = (start : new TimeOnly(18, 0, 0), end : new TimeOnly(4, 0, 0));

var tests = new TimeOnly[] {
  new (23, 0, 0),
  new ( 0, 0, 0),
  new ( 3, 0, 0),
  new ( 5, 0, 0),
  new ( 9, 0, 0),
  new (12, 0, 0),
  new (17, 0, 0),
  new (20, 0, 0)
};

var report = string.Join(Environment.NewLine, tests
  .Select(test => $"{test,9} : {(WithinShift(shift, test) ? "Live" : "Awaiting Start")}}"));

Console.WriteLine(report);

// 日期组件
var now = DateTime.Now;

var currentShift = (
  now.Date + shift.start.ToTimeSpan(),
  now.Date + shift.end.ToTimeSpan());

report =
  $"time: {now:HH:mm} shift {currentShift} is {(WithinShift(currentShift, now) ? "Live" : "Awaiting Start")}";

Console.WriteLine();
Console.WriteLine(report);

输出:

 11:00 PM : Live
 12:00 AM : Live
  3:00 AM : Live
  5:00 AM : Awaiting Start
  9:00 AM : Awaiting Start
 12:00 PM : Awaiting Start
  5:00 PM : Awaiting Start
  8:00 PM : Live

time: 11:03 shift (5/26/2023 6:00:00 PM, 5/26/2023 4:00:00 AM) is Awaiting Start
英文:

If I understand you right, you have a shift, which is a range

18:00 - 04:00

and you have a time, say

23:00

and you want to check if the time is within the shift. If it's your task then

// Just time, Date part is ignored
private static bool WithinShift((TimeOnly start, TimeOnly end) shift, TimeOnly time) =&gt;
  (shift.end &gt;= shift.start) 
     ? time &gt;= shift.start &amp;&amp; time &lt;= shift.end
     : time &gt;= shift.start || time &lt;= shift.end;

// Date component is taken in to account
private static bool WithinShift((DateTime start, DateTime end) shift, DateTime time) =&gt;
  time &gt;= shift.start &amp;&amp; time &lt;= shift.end;

E.g.

var shift = (start : new TimeOnly(18, 0, 0), end : new TimeOnly(4, 0, 0));

var tests = new TimeOnly[] {
  new (23, 0, 0),
  new ( 0, 0, 0),
  new ( 3, 0, 0),
  new ( 5, 0, 0),
  new ( 9, 0, 0),
  new (12, 0, 0),
  new (17, 0, 0),
  new (20, 0, 0)
};

var report = string.Join(Environment.NewLine, tests
  .Select(test =&gt; $&quot;{test,9} : {(WithinShift(shift, test) ? &quot;Live&quot; : &quot;Awaiting Start&quot;)}&quot;));

Console.WriteLine(report);

// Date Component
var now = DateTime.Now;

var currentShift = (
  now.Date + shift.start.ToTimeSpan(),
  now.Date + shift.end.ToTimeSpan());

report =
  $&quot;time: {now:HH:mm} shift {currentShift} is {(WithinShift(currentShift, now) ? &quot;Live&quot; : &quot;Awaiting Start&quot;)}&quot;;

Console.WriteLine();
Console.WriteLine(report);

Output:

 11:00 PM : Live
 12:00 AM : Live
  3:00 AM : Live
  5:00 AM : Awaiting Start
  9:00 AM : Awaiting Start
 12:00 PM : Awaiting Start
  5:00 PM : Awaiting Start
  8:00 PM : Live

time: 11:03 shift (5/26/2023 6:00:00 PM, 5/26/2023 4:00:00 AM) is Awaiting Start

huangapple
  • 本文由 发表于 2023年5月26日 17:16:55
  • 转载请务必保留本文链接:https://go.coder-hub.com/76339361.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定