diff --git a/src/enums/cluster.enum.ts b/src/enums/cluster.enum.ts index 37fb24f..398f655 100644 --- a/src/enums/cluster.enum.ts +++ b/src/enums/cluster.enum.ts @@ -3,6 +3,6 @@ */ enum Cluster { GAEPO = 'GAEPO', - SEOCHO = 'SEOCHO', + //SEOCHO = 'SEOCHO', } export default Cluster; diff --git a/src/external/where42/dto/where42.response.dto.ts b/src/external/where42/dto/where42.response.dto.ts index 2a40b1d..c6ae656 100644 --- a/src/external/where42/dto/where42.response.dto.ts +++ b/src/external/where42/dto/where42.response.dto.ts @@ -22,10 +22,4 @@ export class Where42ResponseDto { example: Cluster.GAEPO, }) cluster: Cluster; - - @ApiProperty({ - description: '마지막으로 태깅한 시간', - type: Date, - }) - tag_at: Date; } diff --git a/src/external/where42/where42.controller.ts b/src/external/where42/where42.controller.ts index 537c2cd..4274c33 100644 --- a/src/external/where42/where42.controller.ts +++ b/src/external/where42/where42.controller.ts @@ -59,7 +59,7 @@ export class Where42Controller { return this.where42Service.where42(login); } - @Post('where42All') + @Post('where42/where42All') async where42All(@Body() logins: string[]): Promise { this.logger.debug(`@where42All) where42All`); return this.where42Service.where42All(logins); diff --git a/src/external/where42/where42.module.ts b/src/external/where42/where42.module.ts index a89957f..62d39f3 100644 --- a/src/external/where42/where42.module.ts +++ b/src/external/where42/where42.module.ts @@ -4,6 +4,7 @@ import { DeviceInfo } from 'src/entities/device-info.entity'; import { TagLog } from 'src/entities/tag-log.entity'; import { TagLogRepository } from 'src/tag-log/repository/mysql/tag-log.repository'; import { UserModule } from 'src/user/user.module'; +import { DateCalculatorModule } from 'src/utils/data-calculator/data-calculator.module'; import { DeviceInfoRepository } from './repository/mysql/device-info.repository'; import { Where42Controller } from './where42.controller'; import { Where42Service } from './where42.service'; @@ -22,7 +23,11 @@ const deviceInfoRepo = { * 24Hane 기능 외 다른 서비스에서 사용하는 외부 API 모듈 */ @Module({ - imports: [UserModule, TypeOrmModule.forFeature([DeviceInfo, TagLog])], + imports: [ + UserModule, + TypeOrmModule.forFeature([DeviceInfo, TagLog]), + DateCalculatorModule, + ], controllers: [Where42Controller], providers: [tagLogRepo, deviceInfoRepo, Where42Service], }) diff --git a/src/external/where42/where42.service.ts b/src/external/where42/where42.service.ts index 7192200..88a5582 100644 --- a/src/external/where42/where42.service.ts +++ b/src/external/where42/where42.service.ts @@ -10,9 +10,12 @@ import { import { ITagLogRepository } from 'src/tag-log/repository/interface/tag-log-repository.interface'; import { IdLoginDto } from 'src/user/dto/id-login.dto'; import { UserService } from 'src/user/user.service'; +import { + DateCalculator, + START_DATE, +} from 'src/utils/data-calculator/date-calculator.component'; import { Where42ResponseDto } from './dto/where42.response.dto'; import { IDeviceInfoRepository } from './repository/interface/device-info.repository.interface'; -import Cluster from 'src/enums/cluster.enum'; @Injectable() export class Where42Service { @@ -24,6 +27,7 @@ export class Where42Service { private deviceInfoRepository: IDeviceInfoRepository, @Inject('ITagLogRepository') private tagLogRepository: ITagLogRepository, + private dateCalculator: DateCalculator, ) {} async where42(login: string): Promise { @@ -37,8 +41,8 @@ export class Where42Service { const cards = await this.userService.findCardsByUserId( user_id, - new Date('2019-01-01 00:00:00'), - new Date(), // NOTE: 대략 42 클러스터 오픈일부터 지금까지 조회 + START_DATE, + this.dateCalculator.getCurrentDate(), ); const last = await this.tagLogRepository.findLatestTagLog(cards); if (last === null) { @@ -56,13 +60,11 @@ export class Where42Service { login, inoutState: device.inoutState, cluster: device.cluster, - tag_at: last.tag_at, }; } @Post('where42All') async where42All(@Body() logins: string[]): Promise { - // todo: Where42ResponseDto의 inoutState, tag_at은 사라질 예정입니다. const res: Where42ResponseDto[] = []; const users = await this.userService.findUsersByLogins(logins); @@ -80,8 +82,8 @@ export class Where42Service { const cards = await this.userService.findCardsByUserId( user.user_id, - new Date('2019-01-01 00:00:00'), - new Date(), // NOTE: 대략 42 클러스터 오픈일부터 지금까지 조회 + START_DATE, + this.dateCalculator.getCurrentDate(), ); const last = await this.tagLogRepository.findLatestTagLog(cards); @@ -103,8 +105,7 @@ export class Where42Service { res.push({ login, inoutState: null, - cluster: Cluster.GAEPO, - tag_at: last.tag_at, + cluster: device.cluster, }); return; } @@ -112,16 +113,14 @@ export class Where42Service { res.push({ login, inoutState: device.inoutState, - cluster: Cluster.GAEPO, - tag_at: last.tag_at, + cluster: device.cluster, }); } catch (e) { this.logger.error(`정상적인 조회가 아님: ${login}`); res.push({ login, inoutState: null, - cluster: Cluster.GAEPO, - tag_at: new Date(), + cluster: null, }); } }), diff --git a/src/tag-log/tag-log.service.ts b/src/tag-log/tag-log.service.ts index 53defdf..f38b1bd 100644 --- a/src/tag-log/tag-log.service.ts +++ b/src/tag-log/tag-log.service.ts @@ -3,7 +3,10 @@ import InOut from 'src/enums/inout.enum'; import { StatisticsService } from 'src/statistics/statistics.service'; import { CardDto } from 'src/user/dto/card.dto'; import { UserService } from 'src/user/user.service'; -import { DateCalculator } from 'src/utils/data-calculator/date-calculator.component'; +import { + DateCalculator, + START_DATE, +} from 'src/utils/data-calculator/date-calculator.component'; import { DeviceInfoDto } from './dto/device-info.dto'; import { InOutDto } from './dto/inout.dto'; import { PairInfoDto } from './dto/pair-info.dto'; @@ -555,8 +558,8 @@ export class TagLogService { this.logger.debug(`@checkClusterById) ${userId}`); const cards = await this.userService.findCardsByUserId( userId, - new Date('2019-01-01 00:00:00'), - new Date(), // NOTE: 대략 42 클러스터 오픈일부터 지금까지 조회 + START_DATE, + this.dateCalculator.getCurrentDate(), ); const last = await this.tagLogRepository.findLatestTagLog(cards); const inCards = await this.pairInfoRepository.findInGates(); @@ -640,7 +643,7 @@ export class TagLogService { cutTime(duration: number): number { const resultDuration = this.dateCalculator.cutTimeByLimit(duration); return resultDuration > 12 - ? this.dateCalculator.getTwelveHoursInSeconds() + ? this.dateCalculator.getHalfDayInSeconds() : resultDuration; } } diff --git a/src/utils/data-calculator/date-calculator.component.ts b/src/utils/data-calculator/date-calculator.component.ts index 894f694..c8b9a50 100644 --- a/src/utils/data-calculator/date-calculator.component.ts +++ b/src/utils/data-calculator/date-calculator.component.ts @@ -1,5 +1,15 @@ import { Injectable, Logger } from '@nestjs/common'; +const SEC = 1000; +const MIN = SEC * 60; +const HOUR = MIN * 60; +const HALF_DAY = HOUR * 24; +const DAY = HOUR * 24; +const WEEK = DAY * 7; + +// NOTE: 42 클러스터의 대략적인 오픈일 +export const START_DATE = new Date('2019-01-01T00:00:00Z'); + /** * 날짜/시간 관련 연산을 하기 위한 모듈입니다. */ @@ -8,8 +18,10 @@ export class DateCalculator { private logger = new Logger(DateCalculator.name); /** - * 인자로 주어진 일에 대해 가장 이른 시간을 반환합니다. * NOTE: 서버의 로컬 시간에 맞게 동작함에 유의해야 함. + * + * @param date Date 객체 + * @returns 인자로 주어진 일에 대해 가장 이른 시간 */ getStartOfDate(date: Date): Date { const y = date.getFullYear(); @@ -19,21 +31,26 @@ export class DateCalculator { } /** - * 인자로 주어진 일에 대해 가장 늦은 시간을 반환합니다. * NOTE: 서버의 로컬 시간에 맞게 동작함에 유의해야 함. + * + * @param date Date 객체 + * @returns 인자로 주어진 일에 대해 가장 늦은 시간 */ getEndOfDate(date: Date): Date { const y = date.getFullYear(); const m = date.getMonth(); const d = date.getDate(); - const rtn = new Date(y, m, d + 1, 0, 0, 0, 0); - rtn.setTime(rtn.getTime() - 1); - return rtn; + const endOfDate = new Date(y, m, d + 1, 0, 0, 0, 0); + endOfDate.setTime(endOfDate.getTime() - 1); + return endOfDate; } + //todo: 리팩터릭 /** - * 인자로 주어진 일에 대해 바로 전날의 가장 늦은 시간을 반환합니다. * NOTE: 서버의 로컬 시간에 맞게 동작함에 유의해야 함. + * + * @param date Date 객체 + * @returns 인자로 주어진 일에 대해 바로 전날의 가장 늦은 시간 */ getEndOfLastDate(date: Date): Date { const rtn = new Date( @@ -50,65 +67,62 @@ export class DateCalculator { } /** - * 인자로 주어진 일에 대해 그 주의 첫 날짜(월요일)의 가장 빠른 시간을 반환합니다. * NOTE: 서버의 로컬 시간에 맞게 동작함에 유의해야 함. + * + * @param date Date 객체 + * @returns 인자로 주어진 일에 대해 그 주의 첫 날짜(월요일)의 가장 빠른 시간 */ getStartOfWeek(date: Date): Date { const dayOfWeek = date.getDay() - 1; const diff = dayOfWeek === -1 ? 6 : dayOfWeek; - const rtn = new Date( - date.getFullYear(), - date.getMonth(), - date.getDate() - diff, - ); - return rtn; + return new Date(date.getFullYear(), date.getMonth(), date.getDate() - diff); } + //todo: get, setTime대신 milliseconds를 써야하는가? /** - * 인자로 주어진 일에 대해 그 주의 마지막 날짜(일요일)와 가장 늦은 시간을 반환합니다. * NOTE: 서버의 로컬 시간에 맞게 동작함에 유의해야 함. + * + * @param date Date 객체 + * @returns 인자로 주어진 일에 대해 그 주의 마지막 날짜(일요일)의 가장 늦은 시간 */ getEndOfWeek(date: Date): Date { const startOfWeek = this.getStartOfWeek(date); - const rtn = new Date(startOfWeek); - rtn.setDate(startOfWeek.getDate() + 7); - rtn.setTime(rtn.getTime() - 1); - return rtn; + const endOfWeek = new Date(startOfWeek); + endOfWeek.setDate(startOfWeek.getDate() + 7); + endOfWeek.setTime(endOfWeek.getTime() - 1); + return endOfWeek; } /** - * 인자로 주어진 일에 대해 해당 월의 시작 시간을 반환합니다. * NOTE: 서버의 로컬 시간에 맞게 동작함에 유의해야 함. * - * @param date 임의의 시간 - * @returns date에 속한 월의 시작 시간 + * @param date Date 객체 + * @returns 인자로 주어진 일에 대해 해당 월의 시작 시간 */ getStartOfMonth(date: Date): Date { return new Date(date.getFullYear(), date.getMonth()); } /** - * 인자로 주어진 일에 대해 해당 월의 끝 시간을 반환합니다. * NOTE: 서버의 로컬 시간에 맞게 동작함에 유의해야 함. * - * @param date 임의의 시간 - * @returns date에 속한 월의 끝 시간 + * @param date Date 객체 + * @returns 인자로 주어진 일에 대해 해당 월의 끝 시간을 반환합니다. */ getEndOfMonth(date: Date): Date { - const rtn = new Date(date.getFullYear(), date.getMonth() + 1); - rtn.setTime(rtn.getTime() - 1); - return rtn; + const endOfMonth = new Date(date.getFullYear(), date.getMonth() + 1); + endOfMonth.setTime(endOfMonth.getTime() - 1); + return endOfMonth; } /** - * 두 date 객체가 동일한 날짜인지 체크합니다. * NOTE: 서버의 로컬 시간에 맞게 동작함에 유의해야 함. * - * @param date1 date 객체 1 - * @param date2 date 객체 2 + * @param date1 Date 객체 1 + * @param date2 Date 객체 2 + * @returns 두 date 객체가 동일한 날짜인지 체크합니다. */ checkEqualDay(date1: Date, date2: Date) { - //this.logger.debug(`@checkEqualDay) ${date1}, ${date2}`); return ( date1.getFullYear() === date2.getFullYear() && date1.getMonth() === date2.getMonth() && @@ -117,67 +131,70 @@ export class DateCalculator { } /** - * Date 객체가 가리키고 있는 시간을 타임스탬프로 반환합니다. - * * @param date Date 객체 - * @return number 타임스탬프 + * @return Date 객체가 가리키고 있는 시간의 초 단위 타임스탬프 */ toTimestamp(date: Date): number { - //this.logger.debug(`@toTimestamp) ${date}`); - return Math.floor(date.getTime() / 1000); + return Math.floor(date.getTime() / SEC); } /** - * 주어진 년, 월에 대해 일의 개수를 구합니다. - * - * @param year 년 + * @param year 연도 * @param month 월 - * @return days 해당 달의 일의 개수 + * @return 주어진 연도, 월에 대해 일의 개수 */ getDaysInMonth(year: number, month: number): number { - this.logger.debug(`@getDaysInMonth) ${year}, ${month}`); const date = new Date(year, month, 0); return date.getDate(); } /** - * 주어진 년도와 주차에 대해 날짜 범위를 구합니다. - * - * @param year 년 + * @param year 연도 * @param week 주차 - * @returns + * @returns 주어진 연도와 주차에 대해 날짜 범위를 구합니다. */ getDateOfWeek(year: number, week: number): Date { - const januaryFirst = new Date(year, 0, 1); - const dayOfWeek = januaryFirst.getDay(); + const firstDayOfYear = new Date(year, 0, 1); + const dayOfWeek = firstDayOfYear.getDay(); const daysToAdd = 7 - dayOfWeek; const secondSundayOfYear = new Date(year, 0, daysToAdd + 1); - const rtn = new Date( - secondSundayOfYear.getTime() + (week - 1) * 7 * 24 * 60 * 60 * 1000, - ); - return rtn; + return new Date(secondSundayOfYear.getTime() + (week - 1) * WEEK); } + /** - * 12시간을 초단위로 반환합니다. - * @returns 초 + * @returns 12시간을 초 단위로 변경한 것 */ + getHalfDayInSeconds(): number { + return HALF_DAY / SEC; + } - getTwelveHoursInSeconds(): number { - return 12 * 60 * 60; + /** + * @returns 하루를 초 단위로 변경한 것 + */ + getDayInSeconds(): number { + return DAY / SEC; } + /** - * 하루단위로 초를 계산하여 12시간으로 나눈 나머지를 리턴합니다. - * - * @param durationPerday 하루에 있었던 체류시간 - * @returns number + * @returns 현재 시간을 반환합니다. + */ + getCurrentDate(): Date { + return new Date(); + } + + /** + * @param durationPerday 하루에 있었던 체류시간 (초 단위) + * @returns 하루 단위로 초를 계산하여 12시간으로 나눈 나머지 */ cutTimeByLimit(durationPerday: number): number { - const twelveHoursInSeconds = this.getTwelveHoursInSeconds(); + const halfDayInSeconds = this.getHalfDayInSeconds(); + const dayInSeconds = this.getDayInSeconds(); + + //todo: 음수인 경우가 있나요? + //const seconds = durationPerday % dayInSeconds; const seconds = - ((durationPerday % (twelveHoursInSeconds * 2)) + - twelveHoursInSeconds * 2) % - (twelveHoursInSeconds * 2); - const remainder = seconds % twelveHoursInSeconds; - return remainder; + ((durationPerday % dayInSeconds) + dayInSeconds) % dayInSeconds; + + return seconds % halfDayInSeconds; } }