Post

Java Standard - 날짜와 시간 & 형식화

...

Java Standard - 날짜와 시간 & 형식화

Calendar와 Date

발전 순서와 내용

  1. JDK 1.0 - Date : 빈약함
  2. JDK 1.1 - Calendar : Date 보완 했지만 몇가지 단점 존재
  3. JDK 1.8 - java.time 패키지 : 기존 단점들을 개선한 새로운 클래스들이 추가됨

마지막에 새로 추가된 java.time 패키지만 배우면 좋겠지만, Calendar와 Date가 20년 넘게 사용되어왔고, 지금도 계속해서 사용되고 있으므로 알고 있어야함

Calendar

Calendar
추상 클래스, 메서드를 통해 완전히 구현된 클래스의 인스턴스를 얻어야함
  • 구현 클래스 : GregorianCalendarBuddhistCalendar , BuddhistCalendar은 태국만 사용
  • Calendar의 static 메서드 getInstance()를 통해 구현된 인스턴스를 얻어야함
    • 시스템의 국가와 지역설정을 확인해 태국 외에는 GregorianCalendar 의 인스턴스 반환

    어떻게 이런 코드가 가능할까? (처음에 이해 안되서 정리해놓음)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    
    public static Calendar getInstance(){
      String 국가 = 시스템 설정에서 가져옴;
      String 지역설정 = 시스템 설정에서 가져옴;
        
      if(국가.equals("태국") && 지역설정.equals("태국")){
        return new BuddhistCalendar(); // 태국 구현 클래스
      }else{
        return new GregorianCalendar(); // 태국 외의 구현 클래스
      }
    }
    
    • new가 아닌 메서드로 인스턴스 생성한 이유: 최소한의 변경으로 동작하기 위해서

    만약 new로 인스턴스를 생성했다면? 다른 종류의 인스턴스를 필요로 하는 경우(ex, 새로운 구현 클래스 추가 등) Application 코드(= Calendar를 사용하는 코드) 를 수정해야함 메서드로 인스턴스를 생성한다면, 해당 메서드의 내용만 수정하면 됨!

Calendar와 Date 간의 변환

Date클래스는 Calendar가 추가 되면서 대부분의 메서드가 deprecated (=더이상 사용을 권장하지 않음) 되어 잘 사용되지 않지만, Date를 필요로하는 메서드가 있기 때문에 변환할 일이 생김

  • Calendar → Date

    1
    2
    
      Calendar cal = Calendar.getInstance();
      Date d = new Date(cal.getTimeInMills()); //Date(long date);
    
  • Date → Calendar

    1
    2
    3
    
      Date d = new Date();
      Calendar cal = Calendar.getInstance();
      cal.setTime(d);
    

메서드

  • getInstance() : 현재 시스템의 날짜와 시간 정보를 담고 있음
  • get(): 매개변수로 사용되는 int는 Calendar에 정의된 static상수를의미
  • set(): 날짜와 시간을 원하는 값으로 변경
  • clear(): 모든 필드의 값을 지정된 값으로 초기화
  • getActualMaxium(): 매개변수로 들어온 필드의 최대값을 알 수 있음
  • 증가와 감소
    • add(): 지정한 필드값을 원하는 만큼 증가 또는 감소
      • 다른 필드에 영향을 미침 = 필드가 말일(end of month)에서 +1 → 필드: 증가
    • roll(): 지정한 필드값을 원하는 만큼 증가 또는 감소
      • 다른 필드에 영향을 미치지 않음 = 필드가 말일(end of month)에서 +1 → 필드: 증가 안함
      • 예외: 필드가 말일(end of month)에서 필드의 값 변경시, 필드에 영향

날짜의 계산

  • 차이: 두 날짜를 최소단위인 초단위로 변경 → 차이를 구함 → 단위변경(큰 단위부터)
  • 시간상의 전후 비교
    • after() before() 을 사용
    • 두 날의 차이가 양수인지 음수인지 비교

형식화 클래스

특징
숫자, 날짜, 텍스트를 일정한 형식에 맞춰 표현할 수 있는 방법을 객체지향적으로 설계해 표준화
형식화에 사용될 패턴을 정의함

활용

  • 데이터를 형식화
  • 형식화된 데이터에서 원본 데이터 추출

DecimalFormat

특징

  • 숫자를 형식화 하는데 사용, 다양한 형식(정수, 부동소수점, 금액 등)
  • 일정한 형식을 가진 텍스트 → 숫자로 변환

    Integer와 같은 Wrapper 클래스는 구분자가 있으면 변환하지 못함

패턴 Build source

사용하는 방법

  • 형식화: 패턴을 작성해 인스턴스 생성 → 인스턴스의 format() 호출

    1
    2
    3
    4
    
      double number = 1234567.89;
          
      DecimalFormat df = new DecimalFormat("#.#E0"); //패턴을 작성해 인스턴스 생성
      String result = df.format(number);//format() 호출
    
  • 데이터 변환: 패턴을 작성해 인스턴스 생성 → 인스턴스의 parse() 호출

    1
    2
    3
    
      DecimalFormat df = new DecimalFormat("#.#E0"); //패턴을 작성해 인스턴스 생성
      Number num = df.parse("1234567.89");//parse() 호출
      double d = num.doubleValue();//형변환
    
  • Number 클래스: Interger, Double과 같은 숫자를 저장하는 래퍼 클래스의 조상

SimpleDateFormat

특징
Date와 Calendar만으로는 날짜데이터를 원하는 형식으로 다양하게 출력하는것은 복잡 → 날짜 데이터를 원하는 형식으로 다룰 수 있게 해줌
DateFormat은 추상클래스, static 메서드인 getInstance()를 이용해 구현체인 SimpleDateFormat을 얻어야함

패턴 Build source

사용하는 방법

  • 형식화: 패턴을 작성해 인스턴스 생성 → 인스턴스의 format() 호출

    1
    2
    3
    4
    
      Date today = new Date();
          
      SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd"); //패턴을 작성해 인스턴스 생성
      String result = df.format(today);//format() 호출
    

    Date인스턴스만 format()에 사용될 수 있어서 Calendar는 Date로 변환한뒤 호출

  • 데이터 변환: 패턴을 작성해 인스턴스 생성 → 인스턴스의 parse() 호출

    1
    2
    3
    4
    5
    6
    7
    8
    
      String strDate = "2015/02/15"
      Date inDate = null;
      SimpleDateFormat df = new SimpleDateFormat("yyyy/MM/dd"); //패턴을 작성해 인스턴스 생성
      try{
        inDate = df.parse(strDate);//parse() 호출
      }catch(ParseException e){
        // strDate가 지정패턴으로 입력되지 않은경우 오류 발생
      }
    

ChoiceFormat

특징

  • 특정 범위에 속하는 값을 문자열로 변환
  • 연속적 또는 불연속적인 범위의 값을 처리 → if나 switch문은 적절하지 못할 때가 있음

패턴

  • # : 경계를 포함시킴
  • < : 경계를 포함시키지 않음

사용하는 방법

  • 형식화: 패턴을 작성해 인스턴스 생성 → 인스턴스의 format() 호출

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    
      int[] data = {91, 90, 80, 88, 70, 52, 60};
          
      ChoiceFormat form = new ChoiceFormat("60#D|70#C|80<B|90#A");
      for(int score: data){
        System.out.println(data[i] + ":" +form.format(data[i]));
      }
          
      //결과
      91:A
      90:A
      80:C// #이 아니라 <로해서 80은 B에 포함되지 않음
      88:B
      70:C
      52:D
      60:D
    

MessageFormat

특징

  • 데이터를 정해진 양식에 맞게 출력 = 데이터가 들어갈 자리를 마련해 놓은 양식을 미리 작성후 데이터를 넣어 출력
  • 지정된 양식에서 데이터를 추출

패턴 {0} {1} 과같이 숫자로 표현된 곳이 데이터가 출력될 자리, 여러번 사용할 수 있음

  • 객체배열이기 때문에 String 외에도 다른 객체들이 지정될 수 있음

사용하는 방법

  • 형식화: 패턴을 작성해 인스턴스 생성 → 인스턴스의 format() 호출

    1
    2
    
      Object[] data = {"공수정", "여자", 26};
      MessageFormat mf = MessageFormat.format("이름:{0}, 성별:{1}, 나이:{2}", data);
    
  • 데이터 변환: 패턴을 작성해 인스턴스 생성 → 인스턴스의 parse() 호출

    1
    2
    3
    
      String data = "이름:공수정, 성별:여자, 나이:26살"
      MessageFormat mf = MessageFormat.format("이름:{0}, 성별:{1}, 나이:{2}살");
      Object[] parseData = mf.parse(data);
    

    Object[]로 리턴

java.time 패키지

  • java.time패키지와 서브 패키지들
    • java.time: 날짜와 시간을 다루는데 필요한 핵심 클래스를 제공
    • java.time.chrono: 표준이 아닌 달력 시스템을 위한 클래스 제공
    • java.time.format: 날짜와 시간을 파싱하고, 형식화하기 위한 클래스 제공
    • java.time.temporal: 날짜와 시간을 필드와 단위를 위한 클래스 제공
    • java.time.zone: 시간대와 관련된 클래스 제공
  • 특징
    • 불변으로 다뤄짐 → 항상 새로운 객체를 반환
      • 기존 Calendar는 값이 변경됨

java.time 패키지의 핵심 클래스

Calendar에서는 날짜와 시간을 따로 다루지만, java.time패키지에서는 날짜와 시간을 별도의 클래스로 분리 Build source Build source

객체 생성

  • now() : 현재 날짜와 시간을 저장하는 클래스 생성
  • of() : 해당 필드 값을 순서대로 지정해주면, 설정값대로 생성

시간과 관련된 인터페이스

  • Temporal, TemporalAccessor, TemporalAdjuster: 날짜, 시간을 표현한 클래스들이 구현한 인터페이스
  • TemporalAmount: 날짜, 시간의 차이(Period, Duration)의 표현한 클래스들이 구현한 인터페이스
  • TemporalUnit: 날짜, 시간의 단위를 정의한 인터페이스
    • ChronoUnit: TemporalUnit인터페이스를 구현한 것, 열거형
  • TemporalField: 날짜와 시간의 필드를 정의한 인터페이스
    • ChronoField: TemporalField인터페이스를 구현한 것

메서드

  • get(): 특정 필드의 값을 얻음
  • plus(): 지정된 단위의 값을 더함
  • minus(): 지정된 단위의 값을 뺌

LocalDate와 LocalTime

가장 기본이 되는 클래스

생성방법

  • now(): static 메서드, 현재 날짜와 시간을 저장하는 클래스 생성
  • of(): static 메서드, 해당 필드 값을 순서대로 지정해주면, 설정값대로 생성, 여러 버전으로 오버라이딩 되어있음
  • parse(): 문자열을 날짜와 시간으로 변환 할 수 있음

메서드

  • 값을 조회
    • get(): 특정 필드의 값을 가져옴
  • 값 변경: 연산시마다 항상 새로운 객체를 생성해서 반환(=대입 연산자를 꼭 사용해야함)
    • with() : 특정 필드의 값을 변경
    • plus() : 특정 필드의 값을 더함
    • minus() : 특정 필드의 값을 뺌
    • truncatedTo(): 지정된 것보다 작은 단위의 필드를 0으로 설정
  • 비교: 두 날짜를 비교함
    • isAfter() : 이후
    • isBefore() : 이전
    • isEquals() : 연표가 다른 두 날짜를 비교, ex 음력과 양력의 비교
    • conpareTo() : 날짜를 비교하는 메서드, 이전, 이후, 같음 을 알려줌 (int)

Instant

에포크 타임부터 경과된 시간을 나노초로 표현

시간을 초 단위와 나노초 단위로 나누어 저장

에포크타임
1970-01-01 00:00:00 UTC부터 경과된 시간
UNIX의 시간이라고 하기도 함

특징

  • 항상 UTC(+00:00)을 기준으로 함 → 시간대를 고려해야하는 경우, OffsetDateTime을 사용하는 것이 더 나은 선택일 수 있음

생성

  • now(): 현재 날짜와 시간을 저장하는 클래스 생성
  • ofEpochSecond(): 설정값대로 생성

메서드

  • 값을 조회
    • getEpochSecond() : 초단위의 조회
    • getNano() : 나노초 단위의 조회
  • 변환
    • static Date from(Instant instant): Instant → Date
    • Instant toInstant(): Date → Instant

LocalDateTime과 ZoneDateTime

  • LocalDateTime: 날짜와 시간이 같이 있는 클래스
  • ZoneDateTime: 날짜와 시간과 시간대까지 있는 클래스

생성

  • LocalDateTime
    • LocalDate + LocalTime
      • LocalDateTime.of(): LocalDate와 LocalTime의 인스턴스를 매개변수로 해 생성
      • of() : LocalDate의 인스턴스나 LocalTime의 인스턴스에서 of메서드를 사용해 생성
    • now() : 현재 날짜와 시간을 저장하는 클래스 생성
    • of() : 설정값대로 생성
  • ZoneDateTime
    • atZone(): LocalDateTime인스턴스에서 사용, 시간대를 추가해 생성

변환

  • toLocalDate(): LocalDateTime ->LocalDate
  • toLocalTime(): LocalDateTime ->LocalTime

ZoneDateTime과 OffsetDateTime

시간대까지 가지고있는 클래스

  • ZoneDateTime: 시간대를 ZoneId로 표현 → 시간대를 시간의 차이로만 구분= 위험함
  • OffsetDateTime: 시간대를 OffsetDateTime으로 표현 → 아무런 변화 없이 일관된 시계체계를 유지 = 안전함
    • OffsetDateTime: UTC로부터 얼마나 떨어져있는지를 표현

TemporalAdjusters

자주쓰일만한 날짜계산들을 대신해주는 메서드를 정의해놓은 클래스

Build source 구현되어있는 메서드 목록

직접 구현하기

보통은 정의되어있는 메서드로 충분하겠지만, 필요하면 자주 사용되는 메서드를 직접 만들 수 있다.

TemporalAdjuster인터페이스를 구현한 클래스의 객체를 매개변수로 제공해야한다.

@FunctionalInterface? 함수형 인터페이스, 추상 메서드가 딱 하나만 존재하는 인터페이스 람다식과 관련된 것 같음 → 람다 단원에서 다시 학습해보자!

Period와 Duration

날짜와 시간의 간격을 표현하기 위한 클래스

  • Period: 두 날짜간의 차이
  • Duraion: 두 시간의 차이

메서드

  • 차이 계산
    • between() : static 메서드, 두 날짜와 시간의 차이를 구하는 함수
      • 양수와 음수,0의 결과값으로 이전, 이후, 같음을 알 수 있음
    • until() : 인스턴스 메서드, 두 날짜와 시간의 차이를 구하는 함수
  • 생성
    • of() : 설정값대로 생성
  • 변경
    • with() : 특정 필드의 값을 변경
    • minus(): 빼기
    • plus() : 더하기
    • multipledBy() : 곱하기
  • 조회
    • get(): 특정 필드의 값을 가져옴
      • Period는 연도, 월, 일 필드값을 가져올 수 있고, Duration은 초와 밀리초 필드값을 가져옴
  • 확인
    • isNegative(): 음수인지 확인
    • isZero(): 0인지 확인
  • 단위 변환
    • to~(): 다른 단위의 값으로 변환하는데 사용

파싱과 포맷

특징

  • format패키지 중 가장 핵심이 되는 클래스
  • 다양한 형식들을 기본적으로 정의, 이외의 형식은 정의해서 사용할 수 있음

Build source 상수로 정의된 형식들

패턴 Build source Build source

사용하는 방법

  • 형식화: 패턴을 작성해 인스턴스 생성 → 인스턴스를 매개변수로 이용하는 format() 호출

    1
    2
    3
    4
    
      ZonedDateTime today = ZonedDateTime.now();
          
      DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd"); //패턴을 작성해 인스턴스 생성
      String result = today.format(df);//format() 호출
    
  • 데이터 변환: 패턴을 작성해 인스턴스 생성 → 인스턴스를 매개변수로 하는 parse() 호출

    1
    2
    
      DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy/MM/dd"); //패턴을 작성해 인스턴스 생성
      LocalDate newDate = LocalDate.parse("2015/02/15", df);//parse()호출
    
This post is licensed under CC BY 4.0 by the author.