fffo
javascript로 d-day 만들 때 Math.floor를 쓰면 안되는 이유 본문
자바스크립트로 d-day를 표시하는 시계를 만들다가 헷갈리는 부분이 있어서 포스팅하겠습니다.
d-day를 만들기 위해서는 현재 시간을 불러오는 new Date() 생성자 함수, 그리고 d-day에 현재 시간을 빼고 남은 시간을 일, 시, 분, 초 단위로 나타낼 코드가 필요합니다. Date생성자 함수를 통해 얻어진 Date 객체끼리 뺄셈을 하면 시간을 ms단위로 반환하기 때문에 남은시간 역시 ms단위로 얻을 수 있습니다. 물론 Date객체 각각의 연월일 시분초를 얻어서 뺄셈할 수 있지만 이는 월의 마지막 날이 30일인지, 31일인지, 혹은 28일인지 29일인지를 구분하는 별도의 로직이 필요하기 때문에 더 복잡한 것 같습니다.
d-day의 Date객체와 현재 시간의 Date객체의 뺄셈으로 구해진 ms을 시간의 단위에 따라 나타낼 때 나누기 연산이 필요합니다. 예를 들어 3231ms 은 초로 환산하면 3231 / 1000으로 3.231초가 나옵니다.
이 때 소수점 뒤의 수를 버릴 필요가 있는데 두 가지 방법이 있습니다. 하나는 Math.floor()를 이용해 버림연산을 하는 것이고, 하나는 parseInt()를 통해 소수점 뒤의 수를 버리는 것입니다. 둘의 차이는 음수에서 나타납니다. 예를 들어 -1.123를 각각의 방법에 적용시키면 전자는 버림 연산이기 때문에 -2가 되고 후자는 단순히 소수점 뒤의 숫자를 날리는 것이기 때문에 -1이 됩니다.
일반적인 시계에서는 음수가 나오지 않지만 d-day를 계산하는 시계는 현재 날짜가 d-day를 지나면 음수가 되면서 d-day로부터 얼마나 지났는지를 알려줄 수 있습니다. 그렇다면 여기서 -1.12는 -2이 되어야 할까 -1이 되어야 할까요?
예를 들어보겠습니다. d-day의 시간이 되면 시계는 00일 00시 00분 00초가 됩니다. 이 때 1ms 후의 상황을 생각해 봅시다. 1ms 후는 남은 시간이 -1ms이고 이를 초로 나타내기 위해 1000으로 나누고 버림을 하면 -0.001에서 -1이 되어버립니다.
이는 사소해 보이지만 일, 시, 분 또한 같은 원리로 1ms 만 지나도 -1일 -1시 -1분이 되어버리기 때문에 큰 오차를 불러일으킵니다.
끝으로 제가 만든 d-day 시계 코드를 올리겠습니다. js-clock이라는 클래스를 가진 html요소의 innerText로 시계를 추가하는 코드입니다.
const clockTitle = document.querySelector(".js-clock");
const christmasEve = new Date("2021-12-24");
makeDDayCounter(clockTitle, christmasEve);
function makeDDayCounter (clock, dDay) {
printDDayCount(clock, dDay);
setInterval(()=> printDDayCount(clock, dDay), 1000);
}
function printDDayCount(clock, dDay) {
const nowDay = new Date();
const timeDiff = dDay - nowDay;
const SECOND_TIMES = 1000;
const MINUET_TIMES = SECOND_TIMES * 60;
const HOUR_TIMES = MINUET_TIMES * 60;
const DATE_TIMES = HOUR_TIMES * 24;
let restTime = 0;
const date = timeDiff === 0 ? 0 : parseInt(timeDiff / DATE_TIMES);
restTime += date * DATE_TIMES;
const hour =
restTime === 0
? parseInt(timeDiff / HOUR_TIMES)
: parseInt((timeDiff % restTime) / HOUR_TIMES);
restTime += hour * HOUR_TIMES;
const minute =
restTime === 0
? parseInt(timeDiff / MINUET_TIMES)
: parseInt((timeDiff % restTime) / MINUET_TIMES);
restTime += minute * MINUET_TIMES;
const second =
restTime === 0
? parseInt(timeDiff / SECOND_TIMES)
: parseInt((timeDiff % restTime) / SECOND_TIMES);
const [h, m, s] = [hour, minute, second].map(formatting);
const time = `${date}d ${h}h ${m}m ${s}s`;
clock.innerText = time;
}
function formatting(time) {
return time < 10 && time >= 0
? "0" + time
: time < 0 && time > -10
? `-0${Math.abs(time)}`
: time;
}
'Programming > Javascript' 카테고리의 다른 글
자바스크립트에서의 this 키워드 (0) | 2021.11.08 |
---|---|
브라우저 저장소들의 차이점 (로컬스토리지, 세션스토리지, 쿠키) (0) | 2021.11.05 |
배열 (0) | 2021.10.19 |
ES6 함수의 추가 기능 (0) | 2021.10.16 |
클래스 상속 (0) | 2021.10.15 |