LandvibeDev / study-repo

스터디 repository 모음
0 stars 0 forks source link

[모던 자바 인 액션] 6주차 #8

Open so3500 opened 1 year ago

so3500 commented 1 year ago

스터디 날짜

2023.08.04 금 9:00-10:00

내용

챕터11. 널 대신 옵셔널 클래스 챕터12 새로운 날짜와 시간 API

공유

최승위

이성온

정민교

jeongminkyo commented 1 year ago

자바 8 이전의 날짜와 시간 API의 문제들

Date date = new Date(117, 8, 21) // Thu Sep 21 00:00:00 CET 2017

LocalDate와 LocalTime

LocalDate 인스턴스는 시간을 제외한 날짜를 표현하는 불변 객체다. LocalDate 객체는 어떤 시간대 정보도 포함하지 않는다. 정적 팩토리 메서드 of으로 LocalDate 인스턴스를 만들 수 있다.

LocalDate date = LocalDate.of(2020, 12, 22); // of
int year = date.getYear();
Month month = date.getMonth();
int day = date.getDayOfMonth();
LocalDate now = LocalDate.now(); // 현재 날짜 정보

시간에 대한 정보는 LocalTime 클래스로 표현할 수 있다. LocalTime도 정적 메서드 of로 인스턴스를 만들 수 있다.

LocalTime time = LocalTime.of(13, 45, 20); // 13:45:20
int hour = time.getHour();
int minute = time.getMinute();
int second = time.getSecond();

날짜와 시간 조합

LocalDateTime은 LocalDate와 LocalTime을 쌍으로 갖는 복합 클래스다. 날짜와 시간을 모두 표현할 수 있으며 정적 메서드 of로 인스턴스 또한 만들 수 있다.

LocalDateTime dateTime = LocalDateTime.of(2020, Month.DECEMBER, 22, 13, 45, 20);
LocalDateTime dateTime2 = LocalDateTime.of(date, time);

지금까지 살펴본 모든 클래스는 불변이다. 함수형 프로그래밍, 스레드 안정성과 도메인 모델의 일관성을 유지하는데 좋다.

날짜와 시간 객체 출력과 파싱

날짜와 시간 관련 작업에서 포매팅과 파싱은 필수적이다. java.time.format 패키지가 이를 지원한다.

parse 메서드를 통해 날짜와 시간 문자열로 LocalDate와 LocalTime의 인스턴스를 만들 수 있다.

LocalDate date = LocalDate.parse("2020-12-22");
LocalTime time = LocalTime.parse("13:45:20");

가장 중요하게 알아야 할 클래스는 DateTimeFormatter이다. 정적 팩토리 메서드와 상수를 이용해서 손쉽게 포매터를 만들 수 있다.

LocalDate date = LocalDate.of(2014, 3, 18);
String s1 = date.format(DateTimeFormatter.BASIC_ISO_DATE); // 20140318
String s2 = date.format(DateTimeFormatter.ISO_LOCAL_DATE); // 2014-03-18

기존 java.util.DateFormat 클래스와 달리 모든 DateTimeFormatter는 스레드에서 안전하게 사용할 수 있는 클래스다.

또한 DateTimeFormatter 클래스는 특정 패턴으로 포매터를 만들 수 있는 정적 팩토리 메소드도 제공한다.

DateTimeFormatter formatter = DateTimeFormatter.ofPatterm("dd/MM/yyyy");
LocalDate date = LocalDate.of(2014, 3, 18);
String formattedDate = date1.format(formatter);
LocalDate date2 = LocalDate.parse(formattedDate, formatter);

시간대 사용하기

표준이 같은 지역을 묶어서 시간대(time zone) 규칙 집합을 정의한다. ZoneRules 클래스에는 약 40개 정도의 시간대가 있다. ZoneId의 getRules()를 이용해서 해당 시간대의 규정을 획득할 수 있다.

ZoneId romeZone = ZoneId.of("Europe/Rome");

지역 ID는 '{지역}/{도시}' 형식으로 이루어 진다. 지역 집합 정보는 [IANA Time Zone Database](https://www.iana.org/time-zones)에서 제공하는 정보를 사용한다. getDefault() 메서드를 이용하면 기존의 TimeZone 객체를 ZoneId 객체로 변환할 수 있다.

ZoneId zoneId = TimeZone.getDefault().toZoneId();

ZoneId는 LocalDate, LocalTime, LocalDateTime과 같이 ZonedDateTime 인스턴스로 변환할 수 있다.

LocalDate date = LocalDate.of(2014, 13, 18);
ZonedDateTime zdt = date.atStartOfDay(romeZone);

UTC/Greenwich 기준의 고정 오프셋

때로는 UTC/GMT 를 기준으로 시간대를 표현한다. ZoneId의 서브클래스인 ZoneOffset 클래스로 런던의 그리니치 0도 자오선과 시간값의 차이를 표현할 수 있다. 서머 타임을 처리할 수 없으므로 권장하지 않는다.

ZoneOffset newYorkOffset = ZoneOffset.of("-05:00");

대안 캘린더 시스템 사용하기

ISO-8601 캘린더 시스템이 실질적으로 전 세계에서 통용되지만, 자바 8에서는 추가로 ThaiBuddhistDate, MinguoDate, JapaneseDate, HijrahDate가 추가되었다.

so3500 commented 1 year ago
import static org.assertj.core.api.AssertionsForClassTypes.*;

import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalTime;
import java.time.Period;

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

class DateTest {

    @DisplayName("duration 은 두 시간 사이의 간격을 나타낼 때 사용한다.")
    @Test
    void durationTest() {
        LocalTime lunchStartTime = LocalTime.of(11, 30);
        LocalTime lunchEndTime = lunchStartTime.plusHours(1).plusMinutes(30);

        Duration duration = Duration.between(lunchStartTime, lunchEndTime);

        assertThat(duration.toMinutes()).isEqualTo(90);
        System.out.println(duration.toString()); // quiz: 출력값이 PT1H30M 인 이유는?
    }

    @DisplayName("period 은 두 날짜 사이의 간격을 나타낼 때 사용한다.")
    @Test
    void periodTest() {
        LocalDate holidayStartDate = LocalDate.now();
        LocalDate holidayEndDate = holidayStartDate.plusWeeks(3);

        Period period = Period.between(holidayStartDate, holidayEndDate);

        assertThat(period.getDays()).isEqualTo(21);
        System.out.println(period.toString()); // quiz: 출력값이 P21D 인 이유는?
    }
}

Duration, Period 출력값이 아래와 같을 때 주의할 점은?

s5646s commented 1 year ago

marp: true theme: gaia class: invert paginate: true

Modern Java in Action

Week 6 발표자: 최승위


이번 주 범위


Java Optional vs Kotlin Nullable


선언되는 형태


안전하게 호출하는 방법

안전하게 외부메서드를 활용하여 호출하는 방법

가져다 쓸 때 Null이라면 예비값 넣기

코틀린의 Nullable이 왜 더 좋은가?