Java

날짜와 시간

밍구밍구밍 2024. 4. 1. 04:48

01_ 날짜와 데이터 시간

* java.time.* 패키지 사용 (import)

 

- 타임존 :  [ Asia/Seoul ] 과 같은 지역 정보, 세계의 각 타임존은 UTC(협정 세계시)로부터의 시간 차이로 정의

>> UTC : 1970년 01월 01일 자정을 0밀리초로 설정하여 기준을 삼아 그 후로 시간의 흐름을 밀리초로 계  

- 오프셋 (offSet) : 처음 주어진 요소나 지점까지의 변위차를 나타냄

- 일광절약시간(DST) : 일광 절약 시간이 적용 되는 경우, 타임존 차이가 변할 수 있음 

 

1) LocalDate : 날짜만 표현 할 때 ex) 2013-11-21

 

2) LocalTime : 시간만을 표현 할 때 ex) 08:20:30.213

 

3) LocalDateTime : 위의 LocalDate, LocaTime 을 합한 것 (날짜와 시간)

- 시차 정보가 없기 때문에 다른 위치에 있는 서버에서 동시 저장 시 다른 시간으로 저장

- 같은 시간이라는 것을 알 수 없음

 

※ 모든 날짜 객체는 불변이므로 변경 발생 시 새로운 객체 생성 후 그 객체에 반환 값을 받아 출력

 

* 계산

- .plusDays(10) = 특정 날짜에 +10일 더함

 

ex) 코드 참조 (불변 객체이기 때문에 새로운 ofdate = ofdate.plusDays(10) 객체 생성)

public class LocalDateMain {

    public static void main(String[] args) {

        LocalDate nowdate = LocalDate.now();
        System.out.println("오늘 날짜 : " + nowdate);
        LocalDate ofdate = LocalDate.of(2013,11,21);
        System.out.println("지정 날짜 : " + ofdate);

        // 계산 불변
        // ofdate의 경우 enum 이기 때문에 반환값 ofdate = ofdate.plusDays() 를 통해 새로운 객체를 생성 해서 10일 더한 날짜를 출력한다.
        ofdate = ofdate.plusDays(10);
        System.out.println("지정 날짜 + 10일 : " + ofdate); // 새로운 객체 ofdate
    }
}

(ofdate 의 새로운 객체 생성)

 

4) 날짜 비교 < isEqual() vs equal() >

 

5) ZondDateTime

- "Asia/Seoul" 같은 타임존 안에는 일광 절약 시간제에 대한 정보와 UTC + 9:00 와 같은 UTC로 부터 시간 차이인 오프셋 정보를 모두 포함 (시차 및 지역 정보 확인 가능)

 

 

6) OffsetDateTime

- ZondDateTime 과 유사하지만 타임존 정보는 안나옴 [Asia/Seoul] 

 

7) Instant

- Instant 내부에는 초(sec) 데이터만 들어 있음 (나노 sec 포함)

- UTC 기준, 시간대(고정)에 영향을 받지 않음

- 시간 계산 및 비교가 명확하고 일관성이 있음

>> 날짜와 시간에 대한 계산 필요 시 LocalDateTime 및 ZondDateTime 사용

>> 초(sec) 단위에 대한 계산 필요 시 Instant 사용

 

참고) Epoch 시간 (UTC 기준)

- 1970년 01월 01일 이후로 현재까지 경과한 전체 초(sec) 의 수로, 시간대에 영향을 받지 않는 절대적인 시간 표현 방식

(Instant 는 이 Epoch 시간을 다루는 클래스이다)

 

8) Duration(시간), Period(날짜) - 시간의 간격(기간)을 표현하는데 사용

Duration 주요 메서드에서 Hours 와 Minutes() 만 to 를 사용하는 이유 = 실제 자바의 Duration 클래스에는 Seconds 와 Nano에 대한 정의만 final 로 정의 되어 있기 때문에 Hours 와 Minutes 는 사용자가 직접 계산을 해야 하기 때문 to 사용

ex) 

 

- 별도 : .toMinutes() 와 .toMinutesPart() 차이 코드 참조

public static void main(String[] args) {

        Duration duration = Duration.ofMinutes(30);
        System.out.println("duration = " + duration);



        LocalTime lt = LocalTime.of(1, 0);
        System.out.println("lt = " + lt);

        // 계산에 사용
        LocalTime plusTime = lt.plus(duration);
        System.out.println("plusTime = " + plusTime);

        LocalTime start = LocalTime.of(9, 0);
        LocalTime end = LocalTime.of(10, 0);
        Duration between = Duration.between(start, end);
        System.out.println("차이 : " + between.getSeconds());
        // between.toMinutes : 전체 60분을 돌려주는 것
        // between.toMinutesParts : toHours(시간)을 빼고 남은 분(min) 을 되돌려 줌
        System.out.println("근무 시간 : " + between.toHours() + "시간 : " + between.toMinutesPart() + "분");
    }
}

>> 결과 출력 

.toMinutes() - 근무 시간 : 1시간 60분

.toMinutesPart() - 근무 시간 :1시간 0분

 

02_ 날짜와 시간의 핵심 인터페이스

1) TemporalAccessor 인터페이스 (읽기)

- 날짜와 시간을 읽기 위한 기본 인터페이스

 

2) Temporal 인터페이스 (읽기, 쓰기)

- TemporalAccessor 의 하위 인터 페이스 

- 날짜와 시간을 읽고 쓰기 위한 인터페이스

 

3) TemporalAmount 인터페이스 (시간의 간격 더하기 빼기 등)

- 특정 날짜에 일정 기간을 더하거나 빼는데 사용

 

 

시간의 단위와 시간 필드 - 시간의 단위(Unit)와 필드(Field)를 구성하는 핵심 인터페이스 두 가지

4) TemporalUnit(상위 인터페이스), ChronoUnit (TeporalUnit의 구현체 ,enum Type)

- ChronoUnit : 다양한 시간 단위 제공

import java.time.LocalTime;
import java.time.temporal.ChronoUnit;

public class ChronoUnitMain {

    public static void main(String[] args) {

        ChronoUnit[] values = ChronoUnit.values();
        for (ChronoUnit value : values) {
            System.out.println("value = " + value);
        }

        System.out.println("ChronoUnit.HOURS = " + ChronoUnit.HOURS);
        System.out.println("HOURS.duration = " + ChronoUnit.HOURS.getDuration().getSeconds());
        System.out.println("ChronoUnit.DAYS = " + ChronoUnit.DAYS);
        System.out.println("DAYS.duration = " + ChronoUnit.DAYS.getDuration().getSeconds());

        // 차이 구하기
        LocalTime lt1 = LocalTime.of(1, 10, 0);
        LocalTime lt2 = LocalTime.of(1, 20, 0);

        long secondsBetween = ChronoUnit.SECONDS.between(lt1, lt2);
        System.out.println("secondsBetween = " + secondsBetween);

        long minutesbetween = ChronoUnit.MINUTES.between(lt1, lt2);
        System.out.println("minutesbetween = " + minutesbetween);
    }
}

 

5) TemporalField (날짜와 시간의 특정 부분, enum Type)

- 특정 날짜에서 원하는 필드의 데이터를 조회 

import java.time.temporal.ChronoField;

public class ChronoFieldMain {

    public static void main(String[] args) {

        ChronoField[] values = ChronoField.values();
        for (ChronoField value : values) {
            System.out.println("value = " + value + ", range = " + value.range());
        }
        
        System.out.println("ChronoField.MONTH_OF_YEAR.range() = " + ChronoField.MONTH_OF_YEAR.range()); // result : 1 - 12
        System.out.println("ChronoField.DAY_OF_MONTH.range() = " + ChronoField.DAY_OF_MONTH.range()); // result : 1 - 28/31
    }
}

 

03_ isSupported (사용자가 가져오고자 하는 날짜 데이터 출력 가능 여부 확인)

import java.time.LocalDate;
import java.time.temporal.ChronoField;

public class IsSupportedMain2 {

    public static void main(String[] args) {

        LocalDate now = LocalDate.now();

        // LocalDate 에서 SECOND_OF_NINUTE 를 사용 할 수 있는지 판단하는 isSupported 메서드 실행
        boolean supported = now.isSupported(ChronoField.SECOND_OF_MINUTE);
        System.out.println("supported = " + supported);

        // 조건문으로 가능 여부에 따른 출력 결과 작성
        if (supported) {
            int minute = now.get(ChronoField.SECOND_OF_MINUTE);
            System.out.println("minute = " + minute);
        } else {
            System.out.println("쓰지마세요");
        }

    }

}

 

 

04_ 날짜 및 시간 문자열 파싱과 포맷팅

- 포맷팅(format) : 날짜와 시간 데이터를 원하는 포맷의 문자열로 변경 하는 것 (Date -> String)

- 파싱(parse) : 문자열을 날짜와 시간 데이터로 변경 하는 것 (String -> Date)

 

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

public class FommattingMain2 {

    public static void main(String[] args) {

        // formatter 포맷팅 날짜와 시간을 문자로
        LocalDateTime now = LocalDateTime.of(2024, 12, 31, 13, 30, 59);
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); // 원하는 포맷 형식 지정 .ofPattern();
        String formattedDateTime = now.format(formatter); //
        System.out.println("날짜와 시간 포맷팅 : " + formattedDateTime);
        System.out.println(now); // ISO 국제 표준 날짜 시간


        // parse : 문자를 날짜와 시간으로 
        String dataTimeString = "2030-01-01 11:30:00";
        LocalDateTime parsedDateTime = LocalDateTime.parse(dataTimeString, formatter); // 원하는 파싱 형식 지정 .parse();
        System.out.println("parsedDateTime = " + parsedDateTime);
    }
}

>> 결과 코드