[Java] 기본 API 클래스 ⑦

kiteB·2022년 2월 8일
0

Java

목록 보기
35/35
post-thumbnail

[ Format 클래스 ]

자바에서는 숫자와 날짜를 원하는 형식의 문자열로 쉽게 변환하기 위해 형식 클래스를 제공한다.

형식 클래스는 java.text 패키지에 포함되어 있는데

  • 숫자 형식을 위해 DecimalFormat,
  • 날짜 형식을 위해 SimpleDateFormat,
  • 매개 변수화된 문자열 형식을 위해 MessageFormat 등을 제공한다.

1. 숫자 형식 클래스 ( DecimalFormat )

DecimalFormat숫자 데이터를 원하는 형식을 표현하기 위해서 패턴을 사용한다.

📌 DecimalFormat 패턴

패턴 사용 방법은 다음과 같다.

  • 적용할 패턴을 DecimalFormat 생성자 매개값으로 지정해서 객체를 생성한다.
  • format() 메소드를 호출해서 패턴이 적용된 문자열을 얻는다.
DecimalFormat df = new DecimalFormat("#,###.0");
String result = df.format(1234567.89);

2. 날짜 형식 클래스 ( SimpleDateFormat )

Date 클래스의 toString() 메소드는 영문으로 된 날짜를 리턴하는데 만약 특정 문자열 포맷으로 얻고 싶다면 java.text.SimpleDateFormat 클래스를 이용하면 된다. SimpleDateFormat 클래스도 날짜를 원하는 형식으로 표현하기 위해서 패턴을 사용한다.

📌 SimpleDateFormat 패턴

패턴에는 자릿수에 맞게 기호를 반복하여 작성할 수 있다.

  • yyyy는 년도를 4자리로 표현하라는 의미이다.
  • MMdd는 각각 달과 일을 2자리로 표시하라는 의미이다.
SimpleDateFormat df = new SimpleDateFormat("yyyy년 MM월 dd일");
String strDate = sdf.format(new Date());

3. 문자열 형식 클래스 ( MessageFormat )

데이터를 파일에 저장하거나, 네트워크로 전송할 때, 그리고 데이터베이스 SQL문을 작성할 때 등 많은 부분에서 일정한 형식의 문자열을 사용한다.

MessageFormat 클래스를 사용하면 문자열에 데이터가 들어갈 자리를 표시해 두고,
프로그램이 실행하면서 동적으로 데이터를 삽입해 문자열을 완성시킬 수 있다.

예를 들어 다음과 같이 회원 정보를 출력한다고 가정해보자.

회원 ID: blue
회원 이름: Java
회원 전화번호: 010-1234-5678

만약 id, name, tel이라는 변수에 회원 정보가 저장되어 있을 경우,
연결 연산자 +를 사용하거나, MessageForma를 사용할 수 있다.

✅ 연결 연산자 + 사용

다음과 같이 문자열 연결 연산자+로 출력할 문자열을 생성할 수 있다.

String resut = "회원 ID: " + id + "\n회원 이름: " + name + "\n회원 전화번호: " + tel;

위의 방법은 + 연산자로 인해 복잡해 보이고, 전체 문자열을 파악하기 힘들다.


MessageFormat 사용

MessageFormat 클래스를 사용하면 조금 더 깔끔하게 데이터를 삽입하고 전체 문자열을 쉽게 예측할 수 있다.

String message = "회원 ID: {0} \n회원 이름: {1} \n회원 전화번호: {2}";
String result = MessageFormat.format(message, id, name, tel):

MessageFormat은 정적 format() 메소드를 호출해서 완성된 문자열을 리턴시킨다.

format()

  • 첫 번째 매개값은 매개 변수화된 문자열을 지정하고
  • 두 번째 이후의 매개값은 인덱스 순서에 맞게 값을 나열하면 된다.

값을 나열하는 대신, 다음과 같이 배열을 대입해도 된다.

String text = "회원 ID: {0} \n회원 이름: {1}\n 회원 전화번호: {2}";
Ojbect[] arguments = {id, name, tel};
String result = MessageFormat.format(text, arguments);

[ java.time 패키지 ]

자바 7 이전까지는 DateCalendar 클래스를 이용해서 날짜와 시간 정보를 얻을 수 있었다. 하지만 여러 요인들로 인해 자바 8부터는 java.time 패키지와 하위 패키지를 사용한다.

💡 참고 | DateCalendar 클래스의 문제점

  • Date 클래스의 대부분의 메소드는 Deprecated 되었고, Date 용도는 단순히 특정 시점의 날짜 정보를 저장하는 역할만 한다.
  • Calendar 클래스는 날짜와 시간 정보를 얻기에는 충분하지만, 날짜와 시간을 조작하거나 비교하는 기능이 불충분하다.

1. 날짜와 시간 객체 생성

java.time 패키지에는 다음과 같이 날짜와 시간을 표현하는 5개의 클래스가 있다.


LocalDate

LocalDate로컬 날짜 클래스로, 날짜 정보만을 저장할 수 있다.

LocalDate 객체는 두 가지 정적 메소드로 얻을 수 있다.

  • now(): 컴퓨터의 현재 날짜 정보를 저장한 LocalDate 객체를 리턴한다.
  • of(): 매개값으로 주어진 날짜 정보를 저장한 LocalDate 객체를 리턴한다.
LocalDate currDate = LocalDate.now();
LocalDate targetDate = LocalDate.of(int year, int month, int dayOfMonth);

LocalTime

LocalTime로컬 시간 클래스로, 시간 정보만을 저장할 수 있다.

LocalTime 객체도 마찬가지로 두 가지 정적 메소드로 얻을 수 있다.

  • now(): 컴퓨터의 현재 시간 정보를 저장한 LocalTime 객체를 리턴한다.
  • of(): 매개값으로 주어진 시간 정보를 저장한 LocalTime 객체를 리턴한다.
LocalTime currTime = LocalTime.now();
LocalTime targetTime = LocalTime.of(int hour, int minute, int second, int nanoOfSecond);

LocalDateTime

LocalDateTimeLocalDateLocalTime을 결합한클래스라고 보면 된다.
날짜와 시간 정보를 모두 저장할 수 있다.

LocalDateTime 객체도 마찬가지로 두 가지 정적 메소드로 얻을 수 있다.

  • now(): 컴퓨터의 현재 날짜와 시간 정보를 저장한 LocalDateTime 객체를 리턴한다.
  • of(): 매개값으로 주어진 날짜와 시간 정보를 저장한 LocalDateTime 객체를 리턴한다.
LocalDateTime currDateTime = LocalDateTime.now();
LocalDateTime targetTime = LocalDateTime.of(int year, int month, int dayOfMonth, int hour, int minute, int second, int nanoOfSecond);

ZonedDateTime

ZonedDateTimeISO-8601 달력 시스템에서 정의하고 있는 타임존의 날짜와 시간을 저장하는 클래스이다.

  • 저장 형태는 2014-04-21T07:50:24.017+09:00[Asia/Seoul]와 같이 맨 뒤에 타임존에 대한 정보(±존오프셋[존아이디])가 추가적으로 붙는다.
    • 존오프셋(ZoneOffset): 협정세계시 (UTC: Universal Time Coordinated)와 차이 나는 시간(시차)을 말한다.
  • ZonedDateTimenow() 정적 메소드에 ZoneId를 매개값으로 주고 얻을 수 있다.
    • ZoneIdof() 메소드로 얻을 수 있다.
      • of()의 매개값은 java.util.TimeZonegetAvailableIDs() 메소드가 리턴하는 유효한 값 중 하나이다.
ZonedDateTime utcDateTime = ZonedDateTime.now(ZoneId.of("UTC"));
ZonedDateTime londonDateTime = ZonedDateTime.now(ZoneId.of("Europe/London"));
ZonedDateTime seoulDateTime = ZonedDateTime.now(ZoneId.of("Asia/Seoul"));

Instant

Instant 클래스는 날짜와 시간의 정보를 얻거나 조작하는데 사용되지 않고, 특정 시점의 타임스탬프(Time-Stamp)로 사용된다. 주로 특정한 두 시점 간의 시간적 우선순위를 따질 때 사용한다.

java.util.Date와 가장 유사한 클래스이지만

  • Date로컬 컴퓨터의 현재 날짜와 시간 정보를,
  • Instant협정세계시(UTC)를 기준으로 한다는 차이점이 있다.
Instant instant1 = Instant.now();
Instant instant2 = Instant.now();

if(instant1.isBefore(instant2)) {
    System.out.println("instant1이 빠릅니다.");
} else if (instant1.isAfter(instant2)) {
    System.out.println("instant1이 늦습니다.");
} else {
    System.out.println("동일한 시간입니다.");
}

System.out.println("차이(nanos): " + instant1.until(instant2,ChronoUnit.NANOS));

위 코드에서 isBefore()isAfter()시간의 앞뒤 여부를 확인하는 메소드이고,
until() 메소드는 두 시점 간의 차이를 리턴한다.


2. 날짜와 시간에 대한 정보 얻기

LocalDateLocalTime은 프로그램에서 날짜와 시간 정보를 이용할 수 있도록 다음과 같은 메소드를 제공하고 있다.

LocalDateTimeZonedDateTime은 날짜와 시간 정보를 모두 갖고 있기 때문에 위 표에 나와 있는 대부분의 메소드를 가지고 있다. 단, isLeapYear()LocalDate에만 있기 때문에 toLocalDate() 메소드로 LocalDate로 변환한 후에 사용할 수 있다.

ZonedDateTime시간존에 대한 정보를 제공하는 다음 메소드들을 추가적으로 가지고 있다.


3. 날짜와 시간 조작하기

날짜와 시간 클래스들은 날짜와 시간을 조작하는 메소드와 상대 날짜를 리턴하는 메소드들을 가지고 있다.

✅ 빼기와 더하기

다음은 날짜와 시간을 빼거나 더하는 메소드들이다.

각 메소드들은 수정된 LocalDate, LocalTime, LocalDateTime, ZonedDateTime을 리턴하기 때문에 도트 . 연산자로 연결해서 순차적으로 호출할 수 있다.


✅ 변경하기

다음은 날짜와 시간을 변경하는 메소드들이다.

with() 메소드는 현재 날짜를 기준으로 해의 첫 번째 일 또는 마지막 일, 달의 첫 번재 일 또는 마지막 일, 달의 첫 번째 요일, 지난 요일 및 돌아오는 요일 등 상대적인 날짜를 리턴한다. 매개값은 TemporalAdjuster 타입으로 다음 표에 있는 TemporalAdjusters의 정적 메소드를 호출하면 얻을 수 있다.


4. 날짜와 시간을 비교하기

날짜와 시간 클래스들은 다음과 같이 비교하거나 차이를 구하는 메소드들을 가지고 있다.

PeriodDuration은 날짜와 시간의 양을 나타내는 클래스들이다.

  • Period는 년, 달, 일의 양을 나타내는 클래스이고,
  • Duration은 시, 분, 초, 나노초의 양을 나타내는 클래스이다.

이 클래스는 D-dayD-time을 구할 때 사용될 수 있다.


다음은 PeriodDurataion에서 제공하는 메소드들이다.

between() 메소드는 PeriodDuration 클래스, 그리고 ChronoUnit 열거 타입에도 있다.

  • PeriodDurationbetween()은 년, 달, 일의 단순 차이를 리턴하고,
  • ChronoUnit 열거 타입의 between()은 전체 시간을 기준으로 차이를 리턴한다.

예를 들어 2023년 1월과 2024년 3월의 달의 차이를 구할 때

  • Periodbetween()은 2가 되고,
  • ChronoUnit.MONTHS.between()은 14가 된다.

5. 파싱과 포맷팅

날짜와 시간 클래스는 문자열을 파싱(parsing)해서 날짜와 시간을 생성하는 메소드와 이와 반대로 날짜와 시간을 포맷팅(Formatting)된 문자열로 변환하는 메소드를 제공하고 있다.

✅ 파싱 (Parsing) 포맷팅

다음은 날짜와 시간 정보가 포함된 문자열을 파싱해서 날짜와 시간을 생성하는 두 개의 parse() 정적 메소드이다.

LocalDateparse(CharSequence) 메소드는 기본적으로 ISO_LOCAL_DATE 포맷터를 사용해서 문자열을 파싱한다. ISO_LOCAL_DATEDateTimeFormatter의 상수로 정의되어 있는데, "2022-02-08" 형식의 포맷터이다.

LocalDate localDate = LocalDate.parse("2022-02-08");

만약 다른 포맷터를 이용해서 문자열을 파싱하고 싶다면 parse(CharSequence, DateTime Formatter) 메소드를 사용할 수 있다. DateTimeFormatterofPattern() 메소드로 정의할 수도 있는데, 다음 코드는 "2022.02.08" 형식의 DateTimeFormatter를 정의하고 문자열을 파싱했다.

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy.MM.dd");
LocalDate localDate = LocalDate.parse("2022.02.08", formatter);

DateTimeFormatter에는 표준화된 포맷터들이 다음과 같이 상수로 미리 정의되어 있기 때문에 ofPattern() 메소드를 사용하지 않고 바로 이용할 수 있다.

만약 포맷터의 형식과 다른 문자열을 파싱하게 되면 DateTimeParseException이 발생하게 된다.


✅ 포맷팅 ( Formatting ) 메소드

format()의 매개값은 DateTimeFormatter로, 해당 형식대로 문자열을 리턴한다.

다음은 LocalDateTime으로부터 "2022년 2월 8일 오후 5시 30분"과 같은 문자열을 얻는 코드이다.

LocalDateTime now = LocalDateTime.now();
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy년 M월 d일 a h시 m분");
String nowString = now.format(dateTimeFormatter);
profile
🚧 https://coji.tistory.com/ 🏠

0개의 댓글