Определите, находятся ли две даты в пределах допустимого промежутка времени - PullRequest
1 голос
/ 30 января 2020

Я получил StartDateTime и EndDateTime, которые я должен подтвердить .
Чтобы они были действительными, они должны быть в течение разрешенных часов , которые полностью настраиваемы .

// allowed hours
allowedStart = new TimeSpan(08, 00, 0);
allowedEnd   = new TimeSpan(20, 00, 0);

Теперь идут две даты (StartDateTime и EndDateTime) (некоторые примеры тестов)

    // Valid date
    obj1.StartDateTime = new DateTime(2020, 1, 30, 19, 10, 0);
    obj1.EndDateTime = new DateTime(2020, 1, 30, 19, 20, 0);

    // End date exceeding
    obj2.StartDateTime = new DateTime(2020, 1, 30, 19, 50, 0);
    obj2.EndDateTime = new DateTime(2020, 1, 30, 20, 15, 0);

    // Start and end date exceeding
    obj3.StartDateTime = new DateTime(2020, 1, 30, 20, 10, 0);
    obj3.EndDateTime = new DateTime(2020, 1, 30, 20, 35, 0);

    // Invalid (overnight) both exceeding
    obj4.StartDateTime = new DateTime(2020, 1, 30, 23, 50, 0);
    obj4.EndDateTime = new DateTime(2020, 1, 31, 0, 35, 0);

    // Start to early
    obj5.StartDateTime = new DateTime(2020, 1, 31, 7, 50, 0);
    obj5.EndDateTime = new DateTime(2020, 1, 31, 8, 15, 0);

Мне было интересно, не существует ли каких-нибудь уже реализована функция Я не нашел, так как мой мозг сейчас умирает. Я пытался реализовать это сам, как это, но obj4 testcase все еще убивает его :

    if ((obj.StartDateTime.Date.Add(allowedStart) <= obj.StartDateTime) &&
        (allowedEnd < allowedStart 
           ? obj.EndDateTime <= obj.EndDateTime.Date.AddDays(1).Add(allowedEnd) 
           : obj.EndDateTime <= obj.EndDateTime.Date.Add(allowedEnd)))) 
    {
        // valid
    } 
    else 
    {
        // invalid
    }

Ответы [ 2 ]

1 голос
/ 30 января 2020

Давайте начнем с одного value

private static bool WithinSpan(DateTime value, TimeSpan from, TimeSpan to) =>
  value >= value.Date.Add(from) && value <= value.Date.Add(to);

Теперь мы можем реализовать то же самое с двумя value с:

private static bool WithinSpan(DateTime startDate, DateTime endDate,
                               TimeSpan from, TimeSpan to) =>
// startDate <= endDate &&  // you may want to add this condition as well 
   startDate >= startDate.Date.Add(from) && startDate <= startDate.Date.Add(to) &&
     endDate >= startDate.Date.Add(from) &&   endDate <= startDate.Date.Add(to);

Демонстрация:

  TimeSpan allowedStart = new TimeSpan(08, 00, 0);
  TimeSpan allowedEnd = new TimeSpan(20, 00, 0);

  (DateTime, DateTime)[] tests = new (DateTime, DateTime)[] {
    (new DateTime(2020, 1, 30, 19, 10, 0), new DateTime(2020, 1, 30, 19, 20, 0)),
    (new DateTime(2020, 1, 30, 19, 50, 0), new DateTime(2020, 1, 30, 20, 15, 0)),
    (new DateTime(2020, 1, 30, 20, 10, 0), new DateTime(2020, 1, 30, 20, 35, 0)),
    (new DateTime(2020, 1, 30, 23, 50, 0), new DateTime(2020, 1, 31,  0, 35, 0)),
    (new DateTime(2020, 1, 31,  7, 50, 0), new DateTime(2020, 1, 31,  8, 15, 0)),
  };

  Func<DateTime, DateTime, string> within = 
    (t1, t2) => $"{(WithinSpan(t1, t2, allowedStart, allowedEnd) ? "Yes" : "No")}";

  string report = string.Join(Environment.NewLine, tests
    .Select(test => $"{test.Item1:yyyy-MM-dd HH:mm:ss} .. {test.Item2:yyyy-MM-dd HH:mm:ss} : {within(test.Item1, test.Item2)}"));

  Console.Write(report);

Результат:

2020-01-30 19:10:00 .. 2020-01-30 19:20:00 : Yes
2020-01-30 19:50:00 .. 2020-01-30 20:15:00 : No
2020-01-30 20:10:00 .. 2020-01-30 20:35:00 : No
2020-01-30 23:50:00 .. 2020-01-31 00:35:00 : No
2020-01-31 07:50:00 .. 2020-01-31 08:15:00 : No

Редактировать:

Разработанная версия

private static bool WithinSpan(DateTime startDate, DateTime endDate,
                               TimeSpan from, TimeSpan to) {
  // Empty Period
  if (startDate > endDate)
    return false;

  // [from..to] within single day
  if (to >= from)
    return startDate >= startDate.Date.Add(from) && startDate <= startDate.Date.Add(to) &&
           endDate >= startDate.Date.Add(from) && endDate <= startDate.Date.Add(to);

  // [from..midnight..to]
  if (startDate.Day == endDate.Day)
    return startDate >= startDate.Date.Add(from) || endDate <= endDate.Date.Add(to);
  else {
    to = to.Add(TimeSpan.FromDays(1));

    return startDate >= startDate.Date.Add(from) && startDate <= startDate.Date.Add(to) &&
           endDate >= startDate.Date.Add(from) && endDate <= startDate.Date.Add(to);
  }
}

который удаляет пустые периоды и обрабатывает from > to TimeSpan как содержащий полночь.

Демонстрация:

  // from 22:00 to midnight and then up to 06:00
  TimeSpan allowedStart = new TimeSpan(22, 00, 00);
  TimeSpan allowedEnd   = new TimeSpan(06, 00, 00);

  (DateTime, DateTime)[] tests = new (DateTime, DateTime)[] {
    (new DateTime(2020, 1, 30, 19, 10, 0), new DateTime(2020, 1, 30, 19, 20, 0)),
    (new DateTime(2020, 1, 30, 19, 50, 0), new DateTime(2020, 1, 30, 20, 15, 0)),
    (new DateTime(2020, 1, 30, 20, 10, 0), new DateTime(2020, 1, 30, 20, 35, 0)),
    (new DateTime(2020, 1, 30, 23, 50, 0), new DateTime(2020, 1, 31,  0, 35, 0)),
    (new DateTime(2020, 1, 30, 23, 00, 0), new DateTime(2020, 1, 30, 23, 35, 0)),
    (new DateTime(2020, 1, 30,  3, 00, 0), new DateTime(2020, 1, 30,  4, 00, 0)),
    (new DateTime(2020, 1, 31,  4, 50, 0), new DateTime(2020, 1, 31,  8, 15, 0)),
  };

  Func<DateTime, DateTime, string> within =
    (t1, t2) => $"{(WithinSpan(t1, t2, allowedStart, allowedEnd) ? "Yes" : "No")}";

  string report = string.Join(Environment.NewLine, tests
    .Select(test => $"{test.Item1:yyyy-MM-dd HH:mm:ss} .. {test.Item2:yyyy-MM-dd HH:mm:ss} : {within(test.Item1, test.Item2)}"));

  Console.Write(report);

Результат:

2020-01-30 19:10:00 .. 2020-01-30 19:20:00 : No
2020-01-30 19:50:00 .. 2020-01-30 20:15:00 : No
2020-01-30 20:10:00 .. 2020-01-30 20:35:00 : No
2020-01-30 23:50:00 .. 2020-01-31 00:35:00 : Yes
2020-01-30 23:00:00 .. 2020-01-30 23:35:00 : Yes
2020-01-30 03:00:00 .. 2020-01-30 04:00:00 : Yes
2020-01-31 04:50:00 .. 2020-01-31 08:15:00 : No

Следующее редактирование:
Сокращенная магическая версиона:

if (startDate > endDate) {
  return false;
}
if (startDate.Day == endDate.Day && to < from) {
  return startDate >= startDate.Date.Add(from) || endDate <= endDate.Date.Add(to);
}
if (to < from) {
  to = to.Add(TimeSpan.FromDays(1));
}
return startDate >= startDate.Date.Add(from) && endDate <= startDate.Date.Add(to);
0 голосов
/ 30 января 2020

Ниже приведен точный фрагмент кода, который я использую для этой не точной цели в своей программе:

public bool IsInsideTimeframe(DateTime firstStart, DateTime firstEnd, DateTime secondStart, DateTime secondEnd)
{
    bool isInside;

    if (firstStart.Ticks >= secondStart.Ticks && firstEnd.Ticks <= secondEnd.Ticks)
        isInside = true;
    else
        isInside = false;

    return isInside;
}

Допустим, у вас есть два периода времени, один между 11: 00-14: 00 вторая - 10: 00-15: 00. Чтобы проверить, находится ли первый временной интервал внутри второго, вы используете функцию следующим образом: IsInsideTimeframe (11:00, 14:00, 10:00, 15:00)

Вы можете просто запустить это функция для обеих дат, которые вы sh хотите проверить, с "разрешенным интервалом времени" в качестве "второй" указанной даты.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...