Java 날짜, 시간 표현하기

GoshK·2021년 9월 25일
0

Java의 날짜와 시간 API 참고 링크

1.Java 날짜, 시간 API

java.util.Date -> java.util.Calendar -> java.time.(LocalDate, LocalTime, LocalDateTIme)

Java 초기에는 Date 와 Calendar 를 사용해서 날짜와 시간을 표현했지만 Java 8 부터는 java.time API 가 제공되어 보다 개선된 방법으로 날짜와 시간을 표현할 수 있습니다.

2.이전의 Date 와 Calendar 의 문제점

  • 불변 객체가 아니다.
    Calendar 와 Date 클래스에 set() 메서드를 호출해서 날짜를 지정하여 세팅하면 연산 결과는 같은 인스턴스에 저장됩니다. 이러한 이유로 Calendar 객체나 Date 객체가 여러 곳에서 공유되면 한 곳에서 바꾼 값이 다른 곳에 영향을 미치는 부작용이 발생할 수 있습니다.

  • int 상수 필드의 남용

public class Main {
    public static void main(String[] args) {
        Calendar calendar = Calendar.getInstance();

        calendar.add(Calendar.JULY, 1);

        System.out.println(calendar.getTime());
    }
}

첫 번째 매개변수 자리(년, 월, 일 등 의 필드의 자리)에 Calendar.JULY 와 같이 전혀 전혀 어울리지 않는 상수가 들어가도 컴파일 시점에서 확인할 방법이 없습니다. 이 뿐만 아니라 Calendar 클래스에는 많은 int 상수가 쓰였는데 이러한 요인이 많은 혼란을 유발합니다.

  • 실수를 유발하는 월 세팅
    Calendar 에서 월 은 1월을 0으로 표현합니다. 때문에 월을 세팅하는 과정에서 많은 실수가 나온다고 합니다.
public class Main {
    public static void main(String[] args) {
        Calendar calendar = Calendar.getInstance();

        calendar.set(2000, 10, 10); //10 월 세팅

        DateFormat df = new SimpleDateFormat("yyyy-MM-dd");

        String format = df.format(calendar.getTime());

        System.out.println(format);
        //2000-11-10
    }
}

3.Java 8 부터 지원되는 새로운 날짜/시간 API(LocalTime, LocalDate, LocalDateTime)

LocalTime, LocalDate, LocalDateTime 클래스는 객체를 생성하기 위해 now(), of() 메서드를 제공합니다.
now() 는 현재의 날짜나 시간을 이용하여 새로운 객체를 만들어 반환합니다.
of() 는 날짜나 시간을 매개변수로 세팅값을 지정하여 지정된 값으로 생성하여 반환합니다.

public class Main {
    public static void main(String[] args) {
        LocalDateTime ldt = LocalDateTime.now();
        LocalDate ld = LocalDate.now();
        LocalTime lt = LocalTime.now();

        Calendar calendar = Calendar.getInstance();

        calendar.set(2000, 13, 10);
        //Sat Feb 10 02:22:16 KST 2001

        System.out.println(calendar.getTime());

        LocalDate ldOf = LocalDate.of(2000, 13, 10);
        //Exception in thread "main" java.time.DateTimeException: Invalid value for MonthOfYear (valid values 1 - 12): 13
        
        //Calendar 는 존재하지 않는 월(13) 을 세팅해도 별다른 오류가 없는 반면 LocalDate 는 컴파일 에서 오류를 잡아줍니다.
    }
}

새로운 날짜/시간 API 의 특징

  • Calendar 와 Date 를 혼용해서 사용하던 전과 달리 LocalDate 만 사용하기 때문에 혼동할 여지가 없습니다.
  • 13월 과 같이 잘못된 월이 설정되면 컴파일시 IllegalFieldValueException 이 발생합니다.
  • 잘못된 TimeZone 설정에도 마찬가지로 컴파일시 IllegalArgumentException 이 발생합니다.
  • 월을 1부터 세어 실수를 줄여줍니다.
  • Calendar 와 Date 는 밀리초 까지의 정밀성을 가졌던 반면 새로운 API 는 나노초 까지 다룰 수 있습니다.

4.새로운 날짜/시간 API 활용

Calendar 와 Date 를 사용할 때는 날짜 차이를 구하기 위해서 밀리세컨드 단위로 바꾸고 빼고 다시 곱하고 하는 복잡한 과정을 통해서 계산하였지만 java.time 에서 제공하는 Period, Duration 등 을 이용하여 쉽게 계산할 수 있습니다.

public class Main {
    public static void main(String[] args) {
        LocalDateTime ldt = LocalDateTime.now();
        LocalDateTime ldtOf = LocalDateTime.of(2020, 1, 26, 2, 40);

        //시간 크기 비교
        System.out.println(ldt.isBefore(ldtOf)); //ldt 가 ldtOf 보다 전 시간인지 false
        System.out.println(ldt.isAfter(ldtOf)); //ldt 가 ldtOf 보다 후의 시간인지 true

        //날짜/시간 차이 계산
        Period between = Period.between(ldtOf.toLocalDate(), ldt.toLocalDate());
        System.out.println(between.getYears() + " 년 " + between.getMonths() + " 개월 " + (between.getDays() == 0 ? "" : between.getDays() + "일 ") + "차이가 납니다.");
        //1 년 8 개월 차이가 납니다.

        LocalDate localDate = LocalDate.now();
        LocalDate localDateOf = LocalDate.of(2020, 1, 1);

        System.out.println(Math.abs(ChronoUnit.DAYS.between(localDate, localDateOf)) + " 일 차이가 납니다.");
        //634 일 차이가 납니다.

        LocalTime lt = LocalTime.now();
        LocalTime ltOf = LocalTime.of(00, 00);

        Duration duration = Duration.between(lt, ltOf);
        System.out.println(duration.abs().toSeconds()+ "s");
        //10293s
    }
}
public class Main {
    public static void main(String[] args) {
        //해당 날짜에 해당하는 월의 일 수 & 날짜
        YearMonth from = YearMonth.from(LocalDate.now());
        System.out.println(from.lengthOfMonth());
        //30
        
        System.out.println(from.atEndOfMonth());
        //2021-09-30


        //해당 주차 요일의 날짜 구하기
        LocalDate localDate = LocalDate.now()
                .with(IsoFields.WEEK_OF_WEEK_BASED_YEAR, 4)//올 해의 4주 차
                .with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY));//월요일

        System.out.println(localDate);
        //2021-01-25
    }
}

0개의 댓글