728x90
반응형
개발을 하던 중 쿼리파라미터를 입력받아 해당 쿼리에 맞는 데이터를 HBase에서 추출하는 요구사항을 만났다.
쿼리파라미터에는 시작일~종료일 사이의 데이터만을 뽑아내는 옵션도 존재했는데, 이 변수가 참 애매하게 잡혀있었다. 설명하자면 너무 복잡해지고 보안상 좋지 않을 수 있으므로 일단 설명은 패스하겠다.
어찌됐든 DB에 쿼리를 날릴 때 startDate와 endDate는 무조건 있어야 겠다는 생각이 들었다. 그래서 코드를 짤 때 막연하게 이렇게 생각했다.
"쿼리에 startDate와 endDate가 입력되지 않은 상태면... 그냥 대충 startDate는 1900년 01월 01일로 하고 endDate는 오늘날짜로 하면 되겠다!"
그래서 얼추 아래와 비슷하게 코드를 구현해놓았다.
Calendar startCal = Calendar.getInstance();
startCal.set(1900, 00, 01);
Date startDate = new Date(startCal.getTimeInMillis());
Date endDate = new Date();
이렇게 해놓고 별 생각없이 HBase Scan에 해당 시간 내 데이터 탐색 조건을 추가하고 테스트를 하는데 에러가 발생했다.
에러를 분석하니, 시간 관련 쿼리에 음수가 입력된 것을 확인했다.
그래서 이게 뭐지... 왜 음수가 나왔지? 하고 잘 분석해보니, startDate이 음수가 된 것을 확인할 수 있었다.
System.out.println(startDate.getTime());
처음보는 상황이 신기해서 구글링을 해보았고, 그 결과 다음 링크에서 답을 얻을 수 있었다.
초기 버전의 유닉스는 시스템 시간을 1/60초 간격으로 측정했다. 이것은 32비트 부호 없는 정수가 829일 미만의 시간 범위를 나타낼 수 있다는 것을 의미했다. 이러한 이유로, 숫자 0으로 표현되는 시간(에포크라고 함)은 아주 최근에 설정되어야 했다. 이것이 1970년대 초반이었기 때문에, 그 시대는 1971-01-01로 설정되었다.
이후 시스템 시간은 매초마다 증가하도록 변경되었으며, 이는 32비트 부호 없는 정수로 표현될 수 있는 시간 범위를 약 136년으로 증가시켰다. 매초를 계산대에서 빼내는 것이 더 이상 중요하지 않았기 때문에, 그 시대는 가장 가까운 10년으로 반올림되어 1970-01-01이 되었다. 이것이 1971-01-01보다 조금 더 간결하게 고려되었다고 가정해야 한다.
1970-01-01을 에포크로 사용하는 32비트 부호 정수는 2038-01-19까지의 날짜를 나타낼 수 있으며, 이 날짜는 1901-12-13으로 마무리된다.
요즘들어 기계적으로 코딩을 하다보니, 생각이라는 걸 안하고 코딩을 하게되는 경우가 많이 생기는 것 같다.
앞으로는 실행에 앞서 조금씩은 생각을 하고, 구글링을 통해 내 생각이 맞는지 확인을 하는 과정이 다시 필요할 것 같다.
참고로 파이썬과 JS에서도 같은 현상이 발생함을 확인했다.
*두 경우 모두 0이 출력된다.
import datetime as dt
import time
start_date = dt.datetime(1970, 1, 1);
end_date = dt.datetime.now();
print(time.mktime(start_date.timetuple()) * 1000);
start_date= new Date("1970-1-1")
console.log(start_date.getTime())
728x90
반응형
'언어 > JAVA' 카테고리의 다른 글
Checked Exception과 Unchecked Exception (0) | 2024.05.08 |
---|---|
[JAVA] 코테용 함수들 (0) | 2023.07.08 |
JDBC 사용법 (0) | 2022.07.25 |
리눅스 OS에 명령어 보내기 (0) | 2022.07.21 |
[JAVA] 온점 단위 Split (0) | 2022.03.10 |