본문 바로가기
☕ Java 웹 프로그래밍/Java

[프로그래머스] Java(자바) 중급 | Part 4. 날짜와 시간

by 일단연 2023. 5. 13.

 Date 

날짜와 시간을 구하기 위한 java.util 패키지의 클래스 (java.util.Date)

  • Date클래스는 JDK 1.0에 만들어졌고, Calendar클래스는 JDK1.1에 만들어짐
  • Date는 지역화에 대한 부분이 고려되지 않음 > 이 문제점을 극복하기 위해 Calender 클래스 탄생
    • 지역화(Localization): 지역에 따라서 다른 시간, 통화(원, 달러, 엔 등), 언어 등에 대하여 고려하는 프로그래밍
  • Date클래스를 보면 대부분의 생성자와 메소드가 Deprecated되어 있음
    • Deprecated: 앞으로 지원을 하지 않거나 문제가 있을 수 있으니 사용하지 말라는 뜻

 

Date클래스의 생성과 사용

  • 기본 생성자를 이용한 Date클래스 생성
    • 기본 생성자로 Date인스턴스를 만들면 현재 시간과 날짜 정보를 Date인스턴스가 가짐
Date date = new Date();
  • toString( )메소드를 이용하여 현재 시간을 문자열로 구함
    • Date클래스엔 toString( )메소드가 내장되어 있어서, date.toString( )이나 date나 같은 값을 가짐
    • 출력 결과: Sat May 13 17:53:14 KST 2023
System.out.println(date.toString());

 

java.util.SimpleDateFormat 클래스로 날짜와 시간을 원하는 형태로 출력하는 방법

기호
yyyy
MM
dd
hh 시간
mm
ss
a 오전/오후
zzz TimeZone
(예: 한국 - 한국표준시 KST)
  • 예: "yyyy.MM.dd 'at' hh:mm:ss a zzz"
    • 날짜와 시간을 구분하기 위해 중간에 ‘at’을 넣어줌
    • 작은따옴표( ‘ )로 감싸면 문자 그대로 출력해줌
  • SimpleDateFormat 클래스가 갖고 있는 format( )메소드에 아까 만든 Date 객체를 넣어서 출력
SimpleDateFormat ft =  new SimpleDateFormat ("yyyy.MM.dd 'at' hh:mm:ss a zzz");     
System.out.println(ft.format(date));

 

현재 시간을 Long값으로 구하는 방법

  • 1.  getTime( )메소드
    • Date를 밀리세컨드로 환산한 값을 숫자(Long값)로 리턴 (1970년 1월 1일 0시 0분 0초부터 현재까지의 시간)
    • 하루는 86,400,000 밀리초로 계산됨
  • 2.  System 클래스의 currentTimeMillis( )메소드
    • System의 현재 시각을 밀리세컨드(Long값)로 리턴해줌
System.out.println(date.getTime());
*// System이 가지고 있는 currentTimeMillis()메소드를 이용해도 됨*
long today = System.currentTimeMillis();
System.out.println(today);
  • 현재 시각을 반영했기 때문에 결과는 계속 바뀜

 

시간들 사이의 연산

  • System 클래스의 currentTimeMillis( ) 메소드로 구한 시간 today에서 Date인스턴스를 만들었을 때의 시간를 빼면, today와 date 사이의 시간을 구할 수 있음
System.out.println(today - date.getTime());

 

 Calendar

Date의 단점(지역화 고려 X)을 해결하고 등장한 것이 Calendar클래스

  • Calender클래스는 많은 상수 필드를 가지고 있음
    • 조금 더 의미가 명확하게 값을 받아오기 위해 사용

 

Calendar 클래스 생성 방법

  • Calendar클래스는 추상클래스
  • Calendar클래스에 대한 인스턴스를 생성하려면 Calendar가 가지고 있는 클래스 메소드 getInstnace( )를 사용해야 함
    • Calendar클래스가 리턴되면 Calendar의 자식 클래스들도 리턴될 수 있음 (추상 클래스니까)
Calendar cal = Calendar.getInstance();

  • getInstance( )메소드를 호출하면 내부적으로 java.util.GregorianCalendar 인스턴스를 만들어서 리턴함
    • GregorianCalendar는 Calendar의 자식 클래스
    • GregorianCalendar로 인스턴스를 명시적으로 생성하지 않는 이유
      • Calendar cal = new GregorianCalendar 라고 하지 않음
      • GregorianCalendar이 아닌, 새로운 형식의 달력이 표준이 될 수도 있기 때문에 getInstance( )메소드를 사용
      • 새로운 형식의 달력이 표준이 됐을 경우, Java 버전이 올라갔을 때 자동으로 달력 버전도 업그레이드될 것

 

Calendar 클래스로 현재 날짜와 시간 정보를 알아내는 방법

  • Calendar는 현재 날짜와 시간에 대한 정보를 가짐
  • Calenda의 get( ) 메소드에 어떤 Calendar의 상수를 넣느냐에 따라 다른 값이 나옴
    • 상수를 사용할 땐 클래스명.상수 로 적어줘야 함
Calendar 상수
YEAR
MONTH
(Java에서 월은 0부터 시작)
DATE 날짜
HOUR_OF_DAY 시간 (24시간제)
HOUR 시간 (12시간제)
MINUTE
SECOND
int yyyy = cal.get(Calendar.YEAR);
int month = cal.get(Calendar.MONTH) + 1; *// 월은 0부터 시작*
int date = cal.get(Calendar.DATE);
int hour = cal.get(Calendar.HOUR_OF_DAY);
int minute = cal.get(Calendar.MINUTE);

 

Calendar 클래스로 원하는 날짜나 시간 정보 얻어오는 방법

  • Calendar클래스의 add( )메소드
    • 쉽게 다음 시간이나 이전 시간을 구할 수 있음
    • 인스턴스명.add(Calender.Calendar상수, 원하는 숫자);
  • 예: 현재보다 5시간 후 구하기
cal.add(Calendar.HOUR, 5);

System.out.println(cal.get(Calendar.YEAR));
System.out.println(cal.get(Calendar.MONTH)+1);
System.out.println(cal.get(Calendar.DATE));
System.out.println(cal.get(Calendar.HOUR_OF_DAY));
System.out.println(cal.get(Calendar.HOUR));
System.out.println(cal.get(Calendar.MINUTE));
System.out.println(cal.get(Calendar.SECOND));
  • 예: 현재보다 10일 전 구하기
cal.add(Calendar.HOUR, 5);

System.out.println(cal.get(Calendar.YEAR));
System.out.println(cal.get(Calendar.MONTH)+1);
System.out.println(cal.get(Calendar.DATE));
System.out.println(cal.get(Calendar.HOUR_OF_DAY));
System.out.println(cal.get(Calendar.HOUR));
System.out.println(cal.get(Calendar.MINUTE));
System.out.println(cal.get(Calendar.SECOND));

 

실습

  • 문제 설명
    • hundredDaysAfter메소드에서 지금부터 100일 이후가 몇 월 며칠인지를 문자열로 만들어서 return하세요. 예를 들어 100일 이후가 2016년 1월 1일 19시라면 "2016년1월1일"라는 문자열을 return하면 됩니다.
  • 해설
    • 우선 add( ) 메소드로 이용해 100일 후로 만들어줌
    • 년, 월, 일을 get( ) 메소드와 Calendar 상수를 이용해 변수로 생성
    • today라는 변수에, 위에서 선언한 상수와 “년”, “월”, “일”을 더하고 리턴
  • 주의할 점
    • 월은 0부터 시작하니까 1을 더해줘야 함 (cal.get(Calendar.MONTH) + 1)
    • 정수를 문자열로 만드는 방법: String.valueOf( )
  • CalendarExam 클래스
import java.util.*;

public class CalendarExam{
  public String hundredDaysAfter(){
  //오늘부터 100일 뒤의 날짜를 "2016년1월1일"의 형식으로 return하세요.
  Calendar cal = Calendar.getInstance();
        
  cal.add(Calendar.DATE, 100);
  int yyyy = cal.get(Calendar.YEAR);
  int month = cal.get(Calendar.MONTH) + 1;
  int date = cal.get(Calendar.DATE);
        
  String today = String.valueOf(yyyy)+"년"+String.valueOf(month)
                 +"월"+String.valueOf(date)+"일";
        
  return today;
  }

    public static void main(String[] args){}
}


 

 java.time 패키지 

Java에서 제공하는 Date, Time API에 문제점이 많았음 (디자인 기능 등)

  • java.util.Date의 문제점
    • 1900년도부터만 사용 가능
    • 월이 0부터 시작
  • java.util.Calendar의 문제점
    • Calendar 인스턴스는 불변 객체(immutable object)가 아니라서 값이 수정될 수 있음
    • 윤초(leap second)와 같은 특별한 상황을 고려하지 않음
    • Calendar 클래스에서는 월(month)을 나타낼 때 1월부터 12월을 0부터 11까지로 표현해야 하는 불편함이 있음
  • 많은 자바 개발자들은 Calendar 클래스뿐만 아니라 더 나은 성능의 Joda-Time이라는 라이브러리를 함께 사용해옴
  • Joda-Time 라이브러리를 발전시킨 새로운 날짜와 시간 API인 java.time 패키지를 제공

 

Java SE 8부터 문제점을 해결하고 더 좋고 직관적인 API들을 제공하기 위해 새롭게 디자인한 Date, Time API 제공

 

java.time 패키지의 특성

  • 해당 패키지에 속하는 모든 클래스의 인스턴스는 불변 객체(immutable object)로 생성됨
    = java.time 패키지에 포함되는 클래스의 메소드들은 모두 새로운 객체를 생성하여 반환하고 있음
  • 새로운 API의 핵심 클래스는 객체를 생성하기 위해 다양한 factory 메소드를 사용함
    • 객체 자기 자신의 특정 요소로 객체를 생성할 경우: of( ) 메소드 호출
    • 다른 타입으로 변경할 경우: from( ) 메소드 호출
  • parse( ) 메소드: String으로 표현된 날짜 형식을 LocalDate, LocalTime, LocalDateTime으로 변환시켜줌
  • String 값을 매개변수로 받아서 사용함

 

java.time 패키지의 하위 패키지

  • java.time.chrono: ISO-8601에 정의된 표준 달력 이외의 달력 시스템을 사용할 때 필요한 클래스들
  • java.time.format: 날짜와 시간에 대한 데이터를 구문분석하고 형식화하는 데 사용되는 클래스들
  • java.time.temporal: 날짜와 시간에 대한 데이터를 연산하는 데 사용되는 보조 클래스들
  • java.time.zone: 타임 존(time-zone)과 관련된 클래스들

 

java.time 패키지의 구성 클래스

  • 기존 Calendar 클래스는 날짜와 시간을 한 번에 표현했지만, java.time 패키지에서는 별도로 구분해 처리
클래스명 기능
LocalDate 날짜를 표현
LocalTime 시간을 표현
LocalDateTime 날짜와 시간을 한 번에 표현
ZonedDateTime 특정 타임 존(time-zone)에 해당하는 날짜와 시간을 다룸
Instant 기존의 Date 클래스와 비슷한 용도
특정 시점의 날짜와 시간을 나노초(nanosecond) 단위로 표현하는 타임스탬프(time-stamp)를 다룸
Period 두 날짜 사이의 차이를 표현
Duration 두 시각 사이의 차이를 표현

 

LocalDateTime 클래스로 현재의 날짜와 시간을 가진 time객체 만드는 방법

  • now( ) 메소드: 현재의 날짜와 시간을 이용하여 새로운 객체를 생성하여 반환
LocalDateTime timePoint = LocalDateTime.now(); *// 현재의 날짜와 시간
System.out.println(timePoint);*
  • 결과
    • 2023-05-13T20:01:51.769

 

LocalDate 클래스와 LocalTime 클래스로 원하는 날짜, 시간을 갖고 있는 time객체 생성하는 방법

  • LocalDate 클래스: 원하는 날짜를 구할 수 있음
  • LocalTime 클래스: 원하는 시간을 구할 수 있음
  • 객체 자기 자신의 특정 요소로 객체를 생성할 거니까 of( ) 메소드 사용
  • 상수도 제공함
    • Month가 가지고 있는 Enum 타입의 데이터 (예: Month.DECEMBER > 12월을 뜻함)
  • parse( ) 메소드: String으로 표현된 날짜 형식을 LocalDate, LocalTime, LocalDateTime으로 변환시켜줌
// 2012년 12월 12일의 시간에 대한 정보를 가지는 LocalDate객체를 만드는 방법
LocalDate ld1 = LocalDate.of(2012, Month.DECEMBER, 12);
System.out.println(ld1); *//2012-12-12

// 17시 18분에 대한 LocalTime객체를 구함
LocalTime lt1 = LocalTime.of(17, 18);
System.out.println(ld2); *//17:18

// 10시 15분 30초라는 문자열에 대한 LocalTime객체를 구함
LocalTime lt2 = LocalTime.parse("10:15:30"); *// From a String*

 

현재의 날짜와 시간 정보를 getter메소드를 이용하여 구하는 방법

  • Month 정보를 출력할 때 +1 을 하지 않아도 정상적으로 출력됨
  • getMonth( ) 메소드: 월(MONTH_OF_YEAR) 필드의 값을 Month 타입으로 반환 (예: NOVEMBER, DECEMBER…)
  • getMonthValue( )메소드: 월(MONTH_OF_YEAR) 필드의 값을 반환 (예: 1, 2, 3…)
LocalDate theDate = timePoint.toLocalDate(); //년-월-일만 출력

// 달을 숫자로 출력. 1월도 1부터 시작하는 것을 알 수 있음
Month month = timePoint.getMonth();
System.out.println(month.getValue());
//위의 값과 아래의 값이 같음
System.out.println(timePoint.getMonthValue()); //달을 숫자로 출력

System.out.println(timePoint.getMonth()); //Month 타입의 값을 출력

int day = timePoint.getDayOfMonth();
int hour = timePoint.getHour();
int minute = timePoint.getMinute();
int second = timePoint.getSecond();

System.out.println(month.getValue() + "/" + day + "  " + hour + ":" + minute + ":" + second);
//결과: 5/13 21:22:4

 

LocalDate 클래스의 getter 메소드

메소드 설명
int get(TemporalField field)
long getLong(TemporalField field)
해당 날짜 객체의 명시된 필드의 값을 int형이나 long형으로 반환
int getYear( ) 해당 날짜 객체의 연도(YEAR) 필드의 값을 반환
Month getMonth( ) 해당 날짜 객체의 월(MONTH_OF_YEAR) 필드의 값을 Month 열거체를 이용하여 반환
int getMonthValue( ) 해당 날짜 객체의 월(MONTH_OF_YEAR) 필드의 값을 반환 (1~12)
int getDayOfMonth( ) 해당 날짜 객체의 일(DAY_OF_MONTH) 필드의 값을 반환 (1~31)
int getDayOfYear( ) 해당 날짜 객체의 일(DAY_OF_YEAR) 필드의 값을 반환 (1~365, 윤년이면 366)
DayOfWeek getDayOfWeek( ) 해당 날짜 객체의 요일(DAY_OF_WEEK) 필드의 값을 DayOfWeek 열거체를 이용하여 반환

 

LocalTime 클래스의 getter 메소드

메소드 설명
int get(TemporalField field)
long getLong(TemporalField field)
해당 시간 객체의 명시된 필드의 값을 int형이나 long형으로 반환
int getHour( ) 해당 시간 객체의 시(HOUR_OF_DAY) 필드의 값을 반환
int getMinute( ) 해당 시간 객체의 분(MINUTE_OF_HOUR) 필드의 값을 반환
int getSecond( ) 해당 시간 객체의 초(SECOND_OF_MINUTE) 필드의 값을 반환
int getNano( ) 해당 시간 객체의 나노초(NANO_OF_SECOND) 필드의 값을 반환

 

실습

  • 문제 설명
    • LocalDateTime을 이용해서 지금이 몇 월인지를 영어로 출력해 보세요. 예를들어 지금이 1월이면 "JANUARY", 2월이면 "FEBRUARY"라고 출력되어야 합니다.
  • 해설
    • LocalDateTime 클래스로 현재의 날짜와 시간을 가진 time객체를 생성
    • LocalDateTime 클래스로 현재의 날짜와 시간 정보에서 년-월-일만 출력하도록 객체 생성
    • getMonth( ) 메소드로 Month 타입의 값 출력
  • TimeExam 클래스
import java.time.LocalDateTime;
import java.time.LocalDate;

public class TimeExam{
  public static void main(String[] args){
    //지금이 몇 월인지를 영어로(예. 1월이면 JANUARY, 2월이면 FEBRUARY) 출력하세요
    LocalDateTime timePoint = LocalDateTime.now();
        
    LocalDate theDate = timePoint.toLocalDate();
        
    System.out.println(timePoint.getMonth());
    }
}