주어진 날짜/시간이 두 날짜/시간 쌍 사이인지 확인하는 알고리즘
-
10-07-2019 - |
문제
나는 일주일 범위의 날짜가 비정상적인 방식으로 저장되어 있습니다.
날짜는이 숫자 형식으로 저장됩니다 : 12150
왼쪽에서 오른쪽으로:
첫 번째 숫자는 날을 나타냅니다 : 1 = 일요일, 2 = 월요일, 3 = 화요일, .... 7 = 토요일
다음 두 자릿수는 24 시간 시스템의 시간을 나타냅니다 : 00 = 자정, 23 = 11pm
다음 두 자리는 분을 나타냅니다 : 00-59
입력 날짜와 시작 날짜 및 종료 날짜가 주어지면 입력 날짜가 시작과 종료 날짜 사이에 있는지 알아야합니다.
지금은 알고리즘이 있습니다 생각한다 시간의 100% 작동하지만 확실하지 않습니다.
어쨌든, 나는 이것을 할 수있는 더 좋고 간단한 방법이있을 것이라고 생각하며, 그 알고리즘이 무엇인지 아는 사람이 궁금했습니다.
그렇지 않은 경우 누군가 내 작업을 두 번 확인하고 실제로 유효한 경우 100%에 대해 작동하는지 확인할 수 있다면 멋질 것입니다.
내가 지금 가지고있는 것은 다음과 같습니다.
if (startDate < inputDate &&
endDate > inputDate) {
inRange = yes;
}
else if (endDate < startDate) {
if((inputDate + 72359) > startDate &&
(inputDate + 72359) < endDate) {
inRange = yes;
}
else if((inputDate + 72359) > startDate &&
(inputDate + 72359) < (endDate + 72359)) {
inRange = yes;
}
}
해결책
어때
const int MAX = 72460; // Or anything more than the highest legal value
inRange = (MAX + inputDate - startDate) % MAX <
(MAX + endDate - startDate) % MAX;
이것은 물론 모든 날짜가 잘 형성되었다고 가정합니다 (사양에 따라).
이것은 시작이 "후"이후의 경우를 다룹니다. (예 : 시작이 수요일이고 끝이 월요일이면 금요일이 범위에 있습니다)
보는 데 1 초가 걸릴 수 있습니다 (아마도 가독성이 가장 중요하기 때문에 좋지 않을 것입니다). 그러나 나는 그것이 효과가 있다고 생각합니다.
기본 요령은 다음과 같습니다.
Legend: 0: Minimum time M: Maximum time S: Start time 1,2,3: Input Time test points E: End Time The S E => Not in range 2 In range 3 > E => Not in range The S > E case 0 M Original -1--E----2---S--3-- Add Max -------------------1--E----2---S--3-- Subtract StartDate ------1--E----2---S--3-- % Max S--3--1--E----2---- 1 In range 2 > E => Not in range 3 In range
당신이 정말로 견과를 원한다면 (그리고 해독하기가 더 어려워)
const int MAX = 0x20000;
const int MASK = 0x1FFFF;
int maxMinusStart = MAX - startDate;
inRange = (maxMinusStart + inputDate) & MASK <
(maxMinusStart + endDate) & MASK;
Max의 가치가 실제로 중요하지 않기 때문에 (최대 성형 된 값을 초과하는 한) 약간 더 빠르고 (약간의 경우, 약간의 거래 모듈러스 및 우리가 할 수있는), 우리는 자유롭게 선택할 수 있어야합니다. 계산을 쉽게 만듭니다.
(물론 당신은 교체 할 수 있습니다 <
a <=
그것이 당신이 정말로 필요한 것인지)
다른 팁
해당 형식의 날짜에는 논리 오류가 있습니다. 월과 연도 정보가 누락되었으므로 캘린더의 날이 누락 된 것을 알 수 없습니다. EG 50755는 2009 년 3 월 12 일 목요일 일지 모르지만 정확히 일주일 전 또는 18 주 앞서있을 수도 있습니다. 그것은 당신이 100% 확신 할 수 없습니다. 어느 해당 형식의 날짜는 사이입니다 어느 다른 2 날짜.
여기 내면의 상태 if
그 이후로는 결코 사실이 될 수 없습니다 endDate < startDate
:
if (endDate < startDate) {
if((inputDate + 72359) > startDate &&
(inputDate + 72359) < endDate) {
// never reached
inRange = yes;
}
첫 번째 부분은 항상 사실이고 두 번째 부분은 동일하기 때문에 다음은 최적이 될 수 없습니다. inputDate < endDate
:
if((inputDate + 72359) > startDate &&
(inputDate + 72359) < (endDate + 72359))
나는 당신이 다음과 같은 것을 원한다고 생각합니다.
if (startDate < endDate)
inRange = (startDate < inputDate) && (inputDate < endDate);
else
inRange = (startDate < inputDate) || (inputDate < endDate);
> = 및 <= 실제로 범위에서 원한다면 사용해야합니다.
이 날짜 10000 또는 72359를 선택했다고 가정 해 봅시다. 어떻게 처리할까요? 범위에 있습니까?
또한 초기화하지 않았기 때문에 StartDate 및 EndDate에 대한 가치를 알지 못했습니다. 내가 틀렸다면 수정하십시오. 초기화되지 않은 변수는 0 또는 null 또는 ''로 시작됩니다.
그래서 나는 startDate = 10000 및 EndDate 72359를 가정합니다.
btw 왜 이런 종류의 배열 (int 또는 문자열 값으로?)을 선택하는 이유는 무엇입니까? 날짜가 아님 예 :
010000-> 날짜 1 월 1 일 00:00
312359-> DATE DATE의 3 월 23:59
그러나 그것은 당신에게 달려 있습니다 : d
내가 틀렸다면 죄송합니다. 나는 대학에서만 알고리즘 수업을 들었고 5 년 전 : D
더 나은 접근 방식은 일주일의 하루 종일 값을 시작 날짜와 관련하여 데이터를 변환하는 것입니다. 이 같은:
const int dayScale = 10000; // scale factor for the day of the week
int NormalizeDate(int date, int startDay)
{
int day = (date / dayScale) - 1; // this would be a lot easier if Sunday was 0
int sday = startDay - 1;
if (day < sday)
day = (day + 7 - sday) % 7;
return ((day+1) * dayScale) + (date % dayScale);
}
int startDay = startDate / dayScale; // isolate the day of the week
int normalizedStartDate = NormalizeDate(startDate, startDay);
int normalizedEndDate = NormalizeDate(endDate, startDay);
int normalizedInputDate = NormalizeDate(inputDate, startDay);
inRange = normalizedInputDate >= normalizedStartDate &&
normalizedInputDate <= normalizedEndDate;
나는 이것이 서면으로 작동 할 것이라고 확신합니다. 어쨌든, 개념은 다중 비교보다 깨끗합니다.