본문 바로가기
스터디/JAVA

[JAVA] 타임존 알아보기 Instant, LocalDateTime, ZonedDateTime

by zoodi 2024. 7. 2.
728x90

목차

     

     

     

    1. GMT, UTC

    GMT

    • 영국에 있는 그리니치 천문대 (경도 0도)를 기준으로하는 태양 시간
    • 쉽게 좌우로 15도씩 1시간 차이를 나타내며 동쪽으로 +1시간씩 서쪽으로는 -1시간 
    • 현재 한국은 동쪽으로 약 135도에 위치해있으며 GMT 기준으로 9시간이 차이가 난다.
    • 그래서 보통 한국의 타임존은 GMT+09:00으로 표현된다.

    UTC

    • 지구의 자전주기의 흐름이 점점 늦어지고 있는 문제를 해결하기 위해 나온 시간대이다.
    • 소프트웨어를 사용할 때에는 UTC가 더 정확하다.

     

    2. Instant

    • Instant는 1970년 부터 현재 시간까지를 계산한 nano초 동안의 시간이며 하나의 순간을 나타냅니다.
    • 대부분의 로직과 데이터들은 UTC와 같은 정확한 시간으로 계산되어야 하므로 자주 사용하는 클래스입니다.

    <Instant 생성>

    public class DateTimeTest {
        public static void main(String[] args) {
            Instant instant = Instant.now();
            System.out.println(instant); // 2022-09-05T15:17:14.741133Z
        }
    }

     

    현재 시간은 9월 6일 오전 12시 17분이다. UTC 기준으로 시간이 출력되는 것을 확인할 수 있다.

    그렇다면 한국 시간으로 나오게 할려면 어떻게 해야할까?

    타임존을 넘겨주어 한국 시간으로 출력되게한다.

     

    public class DateTimeTest {
        public static void main(String[] args) {
            Instant instant = Instant.now();
            
            // 타임존 (한국/서울)의 ZoneId를 넘겨준다.
            ZonedDateTime zonedDateTime = instant.atZone(TimeZone.getDefault().toZoneId());
            System.out.println(zonedDateTime);  // 2022-09-06T00:18:48.519207+09:00[Asia/Seoul]
        }
    }

     

     

     

    3. ZonedDateTime = Instant + ZoneId

    • LocalDateTime에 시간대를 추가하면 ZoneDateTime이 된다.
    • 새로운 패키지에서는 ZoneId라는 클래스를 사용하는데 ZoneId는 일광 절약 시간(Daylight Saving Time)을 자동적으로 처리해주어 더 편하다.
    • 사용 가능한 ZoneId 목록은 ZoneId.getAvailableZoneIds()로 얻을 수 있음
    //뉴욕의 현재 시간
    public class DateTimeTest {
        public static void main(String[] args) {
            // 뉴욕의 현재 순간을 알아보자.
            ZoneId zoneId = ZoneId.of("America/New_York");
            ZonedDateTime newyork = ZonedDateTime.now(zoneId);
            System.out.println(newyork);
        }
    }
    
    //한국의 현재 시간
    ZoneId zid = ZoneId.of("Asia/Seoul");
    ZonedDateTime zdt = localDateTime.atZone(zid);
    System.out.println("ZonedDateTime = " + zdt);
    // ZonedDateTime = 2022-02-20T16:00:26.857433+09:00[Asia/Seoul]

     

    개발에서는...

    • 정확한 날짜의 순간을 계산하기 위해서는 UTC 형식이어야 한다.
    • 하지만 사용자가에게 나타낼때에는 현재 사용자가 위치한 지역에 맞게 보여줘야 하므로 이렇게 ZonedDateTime이 존재합니다.

     

    4. LocalDateTime = LocalDate + LocalTime

    • 로컬 pc의 날짜와 시간을 반환
    • LocalDate
      • YYYY-MM-DD
    • LocalTime
      • HH:MM:SS
    public class LocalDateTimeEx1 {
        public static void main(String[] args) {
    
            LocalDate localDate = LocalDate.now();
            System.out.println("localDate = " + localDate);
            // localDate = 2022-02-20
    
            LocalTime localTime = LocalTime.now();
            System.out.println("localTime = " + localTime);
            // localTime = 15:56:51.294833
    
            LocalDateTime localDateTime = LocalDateTime.now();
            System.out.println("localDateTime = " + localDateTime);
            // localDateTime = 2022-02-20T15:56:51.295105
        }
    }

     

    5. timestamp

    • java.sql.Timestamp는 sql의 TIMESTAMP 타입에 대응하기위해 만들어졌다.
    • Timestamp 클래스로 날짜, 시간과 관련한 데이터의 조작을 행하는 경우 이용한다.
    • Timestmp는 java.util.Date 클래스를 상속 받은 서브 클래스이다.
    • Timestamp의 생성자는 밀리초의 시간 값을 지정한다.
    • System 클래스의 currentTimeMillis() 메소드를 사용하면, 밀리세컨드로 표현되는 현재 시간을 리턴한다.
    Timestamp currentTimestamp = new Timestamp(System.currentTimeMillis());
    System.out.println(currentTimestamp);
    //2022-12-12 08:03:15.759

     

    - timestamp <-> String 변환

    Timestamp currentTimestamp = new Timestamp(System.currentTimeMillis());
    
    // Timestamp to String
    String currentTimestampToString = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").format(currentTimestamp);
    System.out.println(currentTimestampToString);

     

     

    6. 예시코드

    table name column type example
    task due_date DATETIME 2022-01-19 12:30:00.000
    user_config timezone VARCHAR Asia/Seoul

     

     

    // db에서 유저의 타임존 조회
    ZonedDateTime userTime = ZonedDateTime.now().withZoneSameInstant(userConfig.getTimezone());
    
    //LocalDate로 변환 (시간은 제외하고 날짜만 고려할 경우)
    LocalDate targetDueDate = userTime.toLocalDate();
    • user의 타임존을 user_config 테이블에 저장한다.
    • todo의 기한(due_date)을 mysql DATETIME 포맷으로 저장한다.
    • 리마인드 알림 발송 여부 체크 시 사용자의 타임존을 조회하여 LocalDate로 변환한 뒤 해당 날짜에 기한이 설정되어있는 todo가 있는지 조회한다.

    <참고>
    https://velog.io/@hazzang/LocalDateTime-vs-Instant-vs-ZonedDateTime

    https://d2.naver.com/helloworld/645609

     

    728x90

    댓글