Java - 날짜와 시간 라이브러리

JeongHoHyun·2024년 12월 26일

Java

목록 보기
11/23

⭐️ LocalDate

  • 날짜만 표현할 때 사용한다. 년, 월, 일을 다룬다. ex) 2013-11-21
LocalDate nowDate = LocalDate.now(); // 현재 시간을 기준으로 생성
LocalDate ofDate = LocalDate.of(2013, 11, 21); // 특정 날짜를 기준으로 생성한다. 년, 월, 일 입력 가능

ofDate = ofDate.plusDays(10); // 특정일을 더한다. 다양한 plusXxx() 메서드가 존재한다.

⚠️ 주의

  • 모든 날짜 클래스는 불변이다. 변경이 발생하는 경우 새로운 객체를 생성해서 반환하므로 반환값을 꼭 받아야 한다!

⭐️ LocalTime

  • 시간만을 표현할 때 사용한다. 시, 분, 초를 다룬다. ex) 08:20:30.213
    • 초는 밀리초, 나노초 단위도 포함할 수 있다.
LocalTime nowTime = LocalTime.now(); // 현재 시간을 기준으로 생성
LocalTime ofTime = LocalTime.of(9, 10, 30); // 특정 시간을 기준으로 생성한다. 시, 분, 초, 나노초 입력 가능

ofTime = ofTime.plusSeconds(30); // 특정초를 더한다. 다양한 plusXxx() 메서드가 존재한다.

⭐️ LocalDateTime

  • LocalDate와 LocalTime을 합한 개념이다. ex) 2013-11-21T08:20:30.213
LocalDateTime nowDt = LocalDateTime.now();
LocalDateTime ofDt = LocalDateTime.of(2016, 8, 16, 8, 10, 1);

// 날짜와 시간 분리
LocalDate localDate = ofDt.toLocalDate();
LocalTime localTime = ofDt.toLocalTime();

// 날짜와 시간 합체
LocalDateTime localDateTime = LocalDateTime(localDate, localTime);

// 계산(불변)
LocalDateTime ofDtPlus = ofDt.plusDays(1000); // 1000일 더하기
LocalDateTime ofDtPlus1Year = ofDt.plusYears(1); // 1년 더하기

// 비교
boolean flag = nowDt.isBefore(ofDt)); // 현재 날짜시간이 지정 날짜 시간보다 이전인가? 리턴 true / false
boolean flag = nowDt.isAfter(ofD)); // 현재 날짜시간이 지정 날짜 시간보다 이후인가? 리턴 true / false
boolean flag = nowDt.isEquals(ofDt)); // 현재 날짜시간과 지정 날짜 시간이 같은가? 리턴 true / false

⚠️ 주의

isEqual() vs equals()

  • isEqual()
    • isEqual() 은 단순히 비교 대상이 시간적으로 같으면 true를 반환한다.
    • 객체가 다르고, 타임존이 달라도 시간적으로 같으면 true를 반환한다.
    • 시간을 계산해서 시간으로만 둘을 비교한다.
      • ex) 서울의 9시와 UTC의 0시는 시간적으로 같다. 이 둘을 비교하면 true를 반환한다.
  • equals()
    • equals()는 객체의 타입, 타임존 등 내부 데이터의 모든 구성요소가 같아야 true를 반환한다.
      • ex) 서울의 9시와 UTC의 0시는 시간적으로 같다. 이 둘을 비교하면 타임존의 데이터가 다르기 때문에 false를 반환한다.

📖 참고

  • 앞에 Local이 붙는 이유는 세계 시간대를 고려하지 않아서 타임존이 적용되지 않기 때문이다. 특정지역의 날짜와 시간만 고려할 떄 사용한다.
    • 애플리케이션 개발시 국내 서비스만 고려할 때.

📌 ZonedDateTime

  • 시간대를 고려한 날짜와 시간을 표현할 때 사용한다. 여기에는 시간대를 표현하는 타임존이 포함된다.
  • ex) 2013-11-21T09:20:30.213+9:00[Asia/Seoul]
  • +9:00은 UTC(세계 협정시)로 부터의 시간대 차이이다. 오프셋이라고 한다.
  • Asia/Seoul은 타임존이라 한다. 이 타임존을 알면 오프셋과 일광 절약 시간제에 대한 정보를 알 수 있다.
  • ✅일광 절약 시간제가 적용된다.
ZonedDateTime nowZdt = ZonedDateTime.now();

LocalDateTime ldt = LocalDateTime.of(2030, 1, 1, 13, 30, 50);
ZonedDateTime zdt1 = ZonedDateTime.of(ldt, ZoneId.of("Asia/Seoul"));
ZonedDateTime zdt2 = ZonedDateTime.of(2030, 1, 1, 13, 30, 50, 0, ZoneId.of("Asia/Seoul"));

// 같은시간의 다른지역 값 구하기
ZonedDateTime utcZdt = zdt2.withZoneSameInstant(ZoneId.of("UTC"));

📌 OffsetDateTime

  • 시간대를 고려한 날짜와 시간을 표현할 때 사용한다. 여기에는 타임존은 없고, UTC로 부터의 시간대 차이인 고정된 오프셋만 포함한다.
  • ex) 2013-11-21T08:20:30.213+9:00
  • ❌ 일광 절약 시간제가 적용되지 않는다.

📌 Instant

  • UTC를 기준으로 하는, 시간의 한 지점을 나타낸다.
  • 날짜와 시간을 나노초 정밀도로 표현하며, 1970년 1월 1일 0시 0분 0초(UTC)를 기준으로 경과한 시간으로 계산된다.
  • Instant내부에는 초 데이터만 들어있다. (나노초 포함)
  • 날짜와 시간을 계산에 사용할 때는 적합하지 않다.

✏️ Priod, Duration

  • 시간의 개념은 크게 2가지로 표현할 수 있다.

    특정 시점의 시간(시각)

    이 프로젝트는 2024년 12월 30일 까지 완료해야해.
    다음 회의는 14시 20분에 진행한다.
    내 생일은 5월 13일이야.

    시간의 간격(기간)

    앞으로 4년은 더 공부해야 해.
    이 프로젝트는 2개월 남았어.
    라면은 3분동안 끓여야 해.

  • Period, Duration은 시간의 간격(기간)을 표현하는데 사용된다.
  • 시간의 간격은 영어로 amount of time(시간의 양) 으로 불린다.

📌 Period

  • 두 날짜 사이의 간격을 년, 월, 일 단위로 나타낸다.
  • 주요 메소드 : getYears(), getMonths(), getDays()
package dateTime.period;

import java.time.LocalDate;
import java.time.Period;

public class periodMain {
    public static void main(String[] args) {
        // 생성
        Period period = Period.ofDays(10);
        System.out.println("period = " + period);

        // 계산에 사용
        LocalDate currentDate = LocalDate.of(2030, 1, 1);
        LocalDate plusDate = currentDate.plus(period);
        System.out.println("plusDate = " + plusDate);
        System.out.println("plusDate = " + plusDate);

        // 기간 차이
        LocalDate startDate = LocalDate.of(2030, 1, 1);
        LocalDate endDate = LocalDate.of(2030, 4, 2);
        Period between = Period.between(startDate, endDate);
        System.out.println("between = " + between);
        System.out.println("기간 : " + between.getMonths() + "개월 " + between.getDays() + "일");
    }
}

📌 Duration

  • 두 시간 사이의 간격을 시, 분, 초(나노초) 단위로 나타낸다.
  • 주요 메소드 : toHours(), toMinutes(), getSeconds(), getNano()
package dateTime.duration;

import java.time.Duration;
import java.time.LocalTime;

public class durationMain {
    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);

        // 시간 차이
        LocalTime start = LocalTime.of(9, 0);
        LocalTime end = LocalTime.of(10, 0);
        Duration between = Duration.between(start, end);
        System.out.println("차이 : " + between.getSeconds() + "초");
        // between.toMinutesPart() -> 시간계산을 하고 남은 분 (60분을 넘을 수 없음)
        // between.toMinutes() -> 전체 시간을 분으로 표현
        System.out.println("근무 시간 : " + between.toHours() + "시간 " + between.toMinutesPart() + "분");
        System.out.println("근무 시간 : " + between.toMinutes() + "분");
    }
}

⏱️ 시간 조회 및 조작

📌 ChronoField

package dateTime;

import java.time.LocalDateTime;
import java.time.temporal.ChronoField;

public class GetTimeMain {
    public static void main(String[] args) {
        LocalDateTime dt = LocalDateTime.of(2030, 1, 1, 13, 30, 59);
        // ChronoField 사용
        System.out.println("YEAR = " + dt.get(ChronoField.YEAR));
        System.out.println("MONTH = " + dt.get(ChronoField.MONTH_OF_YEAR));
        System.out.println("DAY_OF_MONTH = " + dt.get(ChronoField.DAY_OF_MONTH));
        System.out.println("HOUR_OF_DAY = " + dt.get(ChronoField.HOUR_OF_DAY));
        System.out.println("MINUTE_OF_HOUR = " + dt.get(ChronoField.MINUTE_OF_HOUR));
        System.out.println("SECOND_OF_MINUTE = " + dt.get(ChronoField.SECOND_OF_MINUTE));

        System.out.println("편의 메소드 제공");
        System.out.println("YEAR = " + dt.getYear());
        System.out.println("MONTH = " + dt.getMonth());
        System.out.println("DAY_OF_MONTH = " + dt.getDayOfMonth());
        System.out.println("HOUR_OF_DAY = " + dt.getHour());
        System.out.println("MINUTE_OF_HOUR = " + dt.getMinute());
        System.out.println("SECOND_OF_MINUTE = " + dt.getSecond());

        System.out.println("편의 메소드에 없음");
        System.out.println("MINUTE_OF_DAY = " + dt.get(ChronoField.MINUTE_OF_DAY));
        System.out.println("SECOND_OF_DAY = " + dt.get(ChronoField.SECOND_OF_DAY));
        System.out.println("DAY_OF_WEEK = " + dt.get(ChronoField.DAY_OF_WEEK));
    }
}

📌 ChronoUnit

package dateTime;

import java.time.LocalDateTime;
import java.time.Period;
import java.time.temporal.ChronoUnit;

public class ChangeTimePlusMain {
    public static void main(String[] args) {
        LocalDateTime dt = LocalDateTime.of(2018, 1, 1, 13, 30, 59);
        System.out.println("dt = " + dt);

        // ChronoUnit 사용
        LocalDateTime plusDt1 = dt.plus(10, ChronoUnit.YEARS);
        System.out.println("plusDt1 = " + plusDt1);
        LocalDateTime plusDt2 = dt.plusYears(10);
        System.out.println("plusDt2 = " + plusDt2);

        Period period = Period.ofYears(10);
        LocalDateTime plusDt3 = dt.plus(period);
    }
}

📖 참고

  • 모든 시간 필드를 다 조회할 수 있는 것은 아니다. 아래 코드를 참고하면 조회 가능 한 경우만 로직을 태울 수 있다.
  • isSupported(ChronoField 또는 ChronoUnit)
package dateTime;

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

public class IsSupportedMain {
    public static void main(String[] args) {
        LocalDate now = LocalDate.now();

        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);
        }
    }
}

📌 with()

package dateTime;

import java.time.DayOfWeek;
import java.time.LocalDateTime;
import java.time.temporal.ChronoField;
import java.time.temporal.TemporalAdjusters;

public class ChangeTimeWithMain {
    public static void main(String[] args) {
        LocalDateTime dt = LocalDateTime.of(2018, 1, 1, 13, 30, 59);
        System.out.println("dt = " + dt);

        LocalDateTime changedDt1 = dt.with(ChronoField.YEAR, 2020);
        System.out.println("changedDt1 = " + changedDt1);

        LocalDateTime changedDt2 = dt.withYear(2020);
        System.out.println("changedDt2 = " + changedDt2);

        // TemporalAdjuster 사용
        // 다음주 금요일
        LocalDateTime with1 = dt.with(TemporalAdjusters.next(DayOfWeek.FRIDAY));
        System.out.println("기준 날짜 : " + dt);
        System.out.println("다음 금요일 : " + with1);

        // 이번 달의 마지막 일요일
        LocalDateTime with2 = dt.with(TemporalAdjusters.lastInMonth(DayOfWeek.SUNDAY));
        System.out.println("같은 달의 마지막 일요일 : " + with2);
    }
}

📌 TemporalAdjuster

  • with()는 아주 단순한 날짜만 변경할 수 있다.
  • 다음주 금요일, 이번 달의 마지막 일요일 같은 복잡한 날짜를 계산하고 싶다면 TemporalAdjuster를 사용하면 된다.

⭐️ TemporalAdjusters 클래스가 제공하는 주요 기능

  • dayOfWeekInMonth : 주어진 요일이 몇 번째인y지에 따라 날짜를 조정한다.
  • firstDatOfMonth : 해당 월의 첫째 날로 조정한다.
  • firstDatOfNextMonth : 다음 달의 첫째 날로 조정한다.
  • firstDayOfNextYear : 다음 해의 첫번 째 날로 조정한다.
  • firstDayOfYear : 해당 해의 첫째 날로 조정한다.
  • firstInMonth : 주어진 요일 중 해당 월의 첫 번째 요일로 조정한다.
  • lastDayOfMonth : 해당 월의 마지막 날로 조정한다.
  • lastDayOfNextMonth : 다음 달의 마지막 날로 조정한다.
  • lastDayOfNextYear : 다음 해의 마지막 날로 조정한다.
  • lastDayOfYear : 해당 해의 마지막 날로 조정한다.
  • lastInMonth : 주어진 요일 중 해당 월의 마지막 요일로 조정한다.
  • next : 주요진 요일 이후의 가장가까운 요일로 조정한다.
  • nextOrSame : 주어진 요일 이후 가장 가까운 요일로 조정하되, 현재 날짜가 주어진 요일인 경우 현재 날짜를 반환한다.
  • previous : 주어진 요일 이전의 가장 가까운 요일로 조정한다.
  • previousOrSame : 주어진 요일 이전의 가장 가까운 요일로 조정하되, 현재 날짜가 주어진 요일인 경우 현재 날짜를 반환한다.

⭐️ 문자열 파싱과 포맷팅

package dateTime;

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

public class FormatterMain1 {
    public static void main(String[] args) {
        // 포맷팅 : 날짜를 문자로
        LocalDateTime date = LocalDateTime.of(2024, 12, 31, 13, 30, 59);
        System.out.println("date = " + date);
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        String formattedDate = date.format(formatter);
        System.out.println("날짜와 시간 포맷팅 = " + formattedDate);

        // 파싱 : 문자를 날짜로
        String input = "2030-01-01 11:30:00";
        LocalDateTime parsedDate = LocalDateTime.parse(input, formatter);
        System.out.println("문자열 파싱 날짜와 시간 : " + parsedDate);
    }
}
profile
Java Back-End 2022.11.01 💻~ing

0개의 댓글