SOITZ

dayjs 기본 사용법과 상대시간 설정하기

Published on

dayjs는 JavaScript에서 날짜와 시간을 다루기 위한 가볍고 사용하기 좋은 라이브러리입니다. moment.js와 유사한 API를 제공하지만 훨씬 작은 크기가 특징입니다.

먼저 dayjs 라이브러리를 사용하기 위해서는 설치가 필요합니다. 만약 이미 프로젝트에 설치되어 있지 않다면, 다음 명령어로 설치할 수 있습니다.

설치

npm install dayjs
# 또는
yarn add dayjs

import

import dayjs from 'dayjs';
import 'dayjs/locale/ko';
import relativeTime from 'dayjs/plugin/relativeTime';

dayjs.locale('ko'); // 한국어 사용
dayjs.extend(relativeTime); // 상대시간 (1시간 전)

1. 기본 사용법

1-1. 기본 날짜 생성 및 출력

// 현재 날짜와 시간
const now = dayjs();
console.log(now.format()); // 2024-01-13T19:17:53+09:00

1-2. 특정 포맷으로 날짜 출력

console.log(now.format('YYYY-MM-DD HH:mm:ss'));
// 2024-01-13T19:18:40+09:00

1-3. 특정 날짜와 시간 파싱

// 문자열로부터 날짜 생성
const someDate = dayjs('2024-01-08');
console.log(someDate.format('YYYY-MM-DD')); // 2024-01-08

1-4. 날짜 조작

// 날짜에 일(day) 더하기 (2024-01-13)const in10Days = now.add(10, "day");
console.log(in10Days.format('YYYY-MM-DD')); // 2024-01-23

// 날짜에서 달(month) 빼기
const lastMonth = now.subtract(1, 'month');
console.log(lastMonth.format('YYYY-MM-DD')); // 2023-12-13

1-5. 날짜 비교

const date1 = dayjs('2024-01-08');
const date2 = dayjs('2024-02-08');

// date2가 date1 이후인지 확인
console.log(date1.isBefore(date2)); // true

// date1과 date2가 같은 날인지 확인
console.log(date1.isSame(date2)); // false

날짜 유효성 검사

const validDate = dayjs('2024-01-08');
const invalidDate = dayjs('Not a date');

console.log(validDate.isValid()); // true
console.log(invalidDate.isValid()); // false

2. Format

2-1. 연도, 월, 일:

  • YYYY: 4자리 연도 (예: 2024)
  • YY: 2자리 연도 (예: 24)
  • MMMM: 전체 월 이름 (예: January | 1월)
  • MMM: 3글자 월 이름 (예: Jan | 1월)
  • MM: 2자리 월 (예: 01)
  • M: 월 (예: 1)
  • DD: 2자리 일 (예: 02)
  • D: 일 (예: 2)
console.log(dayjs().format('YYYY-MM-DD')); // 2024-01-13
console.log(dayjs().format('YY-MMM-D')); // 24-Jan-13 | 24-1월-13

2-1. 시간:

  • HH: 24시간 형식의 2자리 시간 (예: 03 | 15)
  • H: 24시간 형식의 시간 (예: 3 | 15)
  • hh: 12시간 형식의 2자리 시간 (예: 03)
  • h: 12시간 형식의 시간 (예: 3)
  • mm: 2자리 분 (예: 05 | 30)
  • m: 1자리 분 (예: 5 | 30)
  • ss: 2자리 초 (예: 06 | 45)
  • s: 1자리 초 (예: 6 | 45)
  • A: 대문자 AM/PM, 오전/오후
  • a: 소문자 am/pm, 오전/오후
console.log(dayjs().format('HH:mm')); // 15:30
console.log(dayjs().format('h:mm A')); // 3:30 PM | 3:30 오후

2-3. 주와 요일:

  • dddd: 전체 요일 이름 (예: Monday | 월요일)
  • ddd: 3글자 요일 이름 (예: Mon | 월)
  • d: 요일 번호 (0 = 일요일, 6 = 토요일)
console.log(dayjs().format('YYYY년 MM월 DD일 dddd')); // 2024년 01월 13일 토요일

2-4. 기타 포맷:

  • ZZ: UTC와의 시차를 +HHmm 또는 -HHmm 형식으로 표시 (예: +0900)
  • Z: UTC와의 시차를 +HH:mm 또는 -HH:mm 형식으로 표시 (예: +09:00)
console.log(dayjs().format('YYYY년 MMMM D일 HH:mm:ss [UTC]Z')); // 2024년 1월 13일 15:30:45 UTC+0900

3. 예시

dayjs 몇가지 예시를 정리해보았습니다.

const now = dayjs('2024-01-13 20:01:25');

// 2024-01-13 20:01:25
console.log(now.format('YYYY-MM-DD HH:MM:ss'));

// 2024.01.13 20:01:25
console.log(now.format('YYYY.MM.DD HH:MM:ss'));

// 2024-01-13 오후 08:01:25
console.log(now.format('YYYY-MM-DD A hh:MM:ss'));

// 2024-01-13 토 오후 08:01:25
console.log(now.format('YYYY-MM-DD ddd A hh:MM:ss'));

// 2024-01-13 토요일 오후 08:01:25
console.log(now.format('YYYY-MM-DD dddd A hh:MM:ss'));

// 2024년 01월 13일 토요일 오후 08:01:25
console.log(now.format('YYYY년 MM월 DD일 dddd A hh:MM:ss'));

4. 상대시간

.fromNow(withoutSuffix?:boolean)

dayjs 객체로부터 현재 시간까지의 상대적인 시간을 문자열로 반환합니다. 인자로 boolean 값을 받을 수 있는데, true를 전달할 경우 접두사 없이 (예를 들어, "2 hours ago" 대신 "2 hours") 결과를 반환합니다.

dayjs('2024-01-10T08:59:40+09:00').fromNow(); // 9일 전
dayjs('2024-01-10T08:59:40+09:00').fromNow(true); // 9일

.from(compared: Dayjs, withoutSuffix?:boolean)

첫 번째 인자로 주어진 dayjs 객체와의 상대적인 시간을 반환합니다. from 함수는 두 개의 인자를 받으며, 첫 번째는 비교 대상이 되는 dayjs 객체, 두 번째는 fromNow와 같은 boolean 값입니다.

dayjs("2024-01-10T08:59:40+09:00").from(dayjs()); // 9일 전
dayjs("2024-01-10T08:59:40+09:00").from(dayjs(), true)) // 9일

한국어

import dayjs from 'dayjs';
import 'dayjs/locale/ko';
import relativeTime from 'dayjs/plugin/relativeTime';

dayjs.locale('ko');
dayjs.extend(relativeTime);

dayjs('2024-01-10T08:59:40+09:00').fromNow(); // 9일 전
dayjs('2024-01-10T08:59:40+09:00').fromNow(true); // 9일
dayjs('2024-01-10T08:59:40+09:00').from(dayjs()); // 9일 전
dayjs('2024-01-10T08:59:40+09:00').from(dayjs(), true); // 9일

const date = '2024-01-10T09:00:00+09:00';

dayjs('2024-01-10T08:59:40+09:00').from(dayjs(date)); // 몇 초 전
dayjs('2024-01-10T08:59:10+09:00').from(dayjs(date)); // 1분 전
dayjs('2024-01-10T08:00:00+09:00').from(dayjs(date)); // 한 시간 전
dayjs('2024-01-10T07:00:00+09:00').from(dayjs(date)); // 2시간 전
dayjs('2024-01-10T03:00:00+09:00').from(dayjs(date)); // 6시간 전
dayjs('2024-01-09T15:00:00+09:00').from(dayjs(date)); // 18시간 전
dayjs('2024-01-09T07:00:00+09:00').from(dayjs(date)); // 하루 전
dayjs('2023-12-31T07:00:00+09:00').from(dayjs(date)); // 10일 전
dayjs('2023-12-20T07:00:00+09:00').from(dayjs(date)); // 21일 전
dayjs('2023-12-10T07:00:00+09:00').from(dayjs(date)); // 한 달 전
dayjs('2023-11-10T07:00:00+09:00').from(dayjs(date)); // 2달 전
dayjs('2023-03-10T07:00:00+09:00').from(dayjs(date)); // 10달 전
dayjs('2023-01-10T07:00:00+09:00').from(dayjs(date)); // 일 년 전
dayjs('2022-01-10T07:00:00+09:00').from(dayjs(date)); // 2년 전

// 접두사 삭제
dayjs('2024-01-10T08:59:40+09:00').from(dayjs(date), true)); // 몇 초
dayjs('2024-01-10T08:59:10+09:00').from(dayjs(date), true)); // 1분
dayjs('2024-01-10T08:00:00+09:00').from(dayjs(date), true)); // 한 시간
dayjs('2024-01-10T07:00:00+09:00').from(dayjs(date), true)); // 2시간
dayjs('2024-01-10T03:00:00+09:00').from(dayjs(date), true)); // 6시간
dayjs('2024-01-09T15:00:00+09:00').from(dayjs(date), true)); // 18시간
dayjs('2024-01-09T07:00:00+09:00').from(dayjs(date), true)); // 하루
dayjs('2023-12-31T07:00:00+09:00').from(dayjs(date), true)); // 10일
dayjs('2023-12-20T07:00:00+09:00').from(dayjs(date), true)); // 20일
dayjs('2023-12-10T07:00:00+09:00').from(dayjs(date), true)); // 한 달
dayjs('2023-11-10T07:00:00+09:00').from(dayjs(date), true)); // 2달
dayjs('2023-03-10T07:00:00+09:00').from(dayjs(date), true)); // 10달
dayjs('2023-01-10T07:00:00+09:00').from(dayjs(date), true)); // 일 년
dayjs('2022-01-10T07:00:00+09:00').from(dayjs(date), true)); // 2년

영어

dayjs('2024-01-10T08:59:40+09:00').fromNow(); // 9 days ago
dayjs('2024-01-10T08:59:40+09:00').fromNow(true); // 9 days
dayjs('2024-01-10T08:59:40+09:00').from(dayjs()); // 9 days ago
dayjs('2024-01-10T08:59:40+09:00').from(dayjs(), true); // 9 days

const date = '2024-01-10T09:00:00+09:00';

dayjs('2024-01-10T08:59:40+09:00').from(dayjs(date)); // a few seconds ago
dayjs('2024-01-10T08:59:10+09:00').from(dayjs(date)); // a minute ago
dayjs('2024-01-10T08:00:00+09:00').from(dayjs(date)); // an hour ago
dayjs('2024-01-10T07:00:00+09:00').from(dayjs(date)); // 2 hours ago
dayjs('2024-01-10T03:00:00+09:00').from(dayjs(date)); // 6 hours ago
dayjs('2024-01-09T15:00:00+09:00').from(dayjs(date)); // 18 hours ago
dayjs('2024-01-09T07:00:00+09:00').from(dayjs(date)); // a day ago
dayjs('2023-12-31T07:00:00+09:00').from(dayjs(date)); // 10 days ago
dayjs('2023-12-20T07:00:00+09:00').from(dayjs(date)); // 21 days ago
dayjs('2023-12-10T07:00:00+09:00').from(dayjs(date)); // a month ago
dayjs('2023-11-10T07:00:00+09:00').from(dayjs(date)); // 2 months ago
dayjs('2023-03-10T07:00:00+09:00').from(dayjs(date)); // 10 months ago
dayjs('2023-01-10T07:00:00+09:00').from(dayjs(date)); // a year ago
dayjs('2022-01-10T07:00:00+09:00').from(dayjs(date)); // 2 years ago

// 접두사 삭제
dayjs('2024-01-10T08:59:40+09:00').from(dayjs(date), true); // a few seconds
dayjs('2024-01-10T08:59:10+09:00').from(dayjs(date), true); // a minute
dayjs('2024-01-10T08:00:00+09:00').from(dayjs(date), true); // an hour
dayjs('2024-01-10T07:00:00+09:00').from(dayjs(date), true); // 2 hours
dayjs('2024-01-10T03:00:00+09:00').from(dayjs(date), true); // 6 hours
dayjs('2024-01-09T15:00:00+09:00').from(dayjs(date), true); // 18 hours
dayjs('2024-01-09T07:00:00+09:00').from(dayjs(date), true); // a day
dayjs('2023-12-31T07:00:00+09:00').from(dayjs(date), true); // 10 days
dayjs('2023-12-20T07:00:00+09:00').from(dayjs(date), true); // 21 days
dayjs('2023-12-10T07:00:00+09:00').from(dayjs(date), true); // a month
dayjs('2023-11-10T07:00:00+09:00').from(dayjs(date), true); // 2 months
dayjs('2023-03-10T07:00:00+09:00').from(dayjs(date), true); // 10 months
dayjs('2023-01-10T07:00:00+09:00').from(dayjs(date), true); // a year
dayjs('2022-01-10T07:00:00+09:00').from(dayjs(date), true); // 2 years

5. 1 분마다 상대시간 업데이트

새로고침이 아닌 페이지가 열려있는 상태에서도 시간을 업데이트 시켜주기

@/util/date.ts

import dayjs from 'dayjs';
import 'dayjs/locale/ko';
import relativeTime from 'dayjs/plugin/relativeTime';

dayjs.locale('ko');
dayjs.extend(relativeTime);

export function formatTime(date: string) {
  return dayjs(date).format('YYYY-MM-DD HH:mm:ss');
}

export function formatMeridiem(date: string) {
  return dayjs(date).format('YYYY. MM. DD A hh:MM:ss');
}
export function formatMeridiemWithShortWeekDay(date: string) {
  return dayjs(date).format('YYYY-MM-DD ddd A hh:MM:ss');
}

export function formatRelativeTime(date: string) {
  return dayjs(date).fromNow();
}

IntervalTimeCard.tsx

import { useEffect, useState } from 'react';
import { formatRelativeTime } from '@/util/date';

export default function IntervalTimeCard({ date }: { date: string }) {
  const [relativeTime, setRelativeTime] = useState(formatRelativeTime(date));

  useEffect(() => {
    // 1분마다 반복
    let interval = setInterval(() => {
      setRelativeTime(formatRelativeTime(date));
    }, 1000 * 60);

    return () => {
      if (interval !== undefined) clearInterval(interval);
    };
  }, [date]);

  return <div>{relativeTime}</div>;
}

사용

<IntervalTimeCard date="2024-01-19T08:45:50+09:00" />

https://day.js.org/en