JAVA

[자바의 정석 기초편 chapter 10] DateFormat(DecimalFormat/SimpleDateFormat)

zoozoo2 2022. 12. 16. 01:36

DecimalFormat이란?

숫자를 형식화하는데 사용하는 Format이다.

 

 

DecimalFormat 사용방법

1. 원하는 출력형식 패턴 작성하고

2. DecimalFormat인스턴스 생성하고

3. 출력하고자 하는 문자열로 format 메서드를 호출하기

double number = 1234567.89;
DecimalFormat df =  new DecimalFormat("#.#E0");
String result = df.format(number); // result = "1.2E6"

 입력값: 1234567.89 

기호 의미 패턴 결과
0 10진수(값이 없을때는 0) 0 12345678
0.0 12345678.9
0000000000.0000 0001234567.8900
# 10진수 # 12345678
#.# 12345678.9
##########.#### 0001234567.8900
. 소수점 #.# 1234567.9
- 음수부호 #.# - 1234567.9-
- #.# -1234567.9
, 단위 구분자 #,###.## 1,234,567.89
#.####.## 123,4567.89
E 지수기호 #E0 .1E7
0E0 1E6
##E0 1.2E6
00E0 12E5
####E0 123.5E4
0000E0 1235E3
#.#E0 1.2E6
0.0E0 1.2E6
0.000000000E0 1.234567890E6
00.00000000E0 12.34567890E5
000.0000000E0 123.4567890E4
#.#########E0 1.23456789E6
##.########E0 1.23456789E6
###.#######E0 1.23456789E6
; 패턴 구분자 #,###.##+;#,###.##- 1,234.567.89+(양수일때)
1,234.567.89-(음수일때)
% 퍼센트 #.#% 123456789%
\u2030 퍼밀(퍼센트 ⨉ 10) #.#\u2030 1234567890‰
\u00A4 통화 \u00A4#.### ₩ 1,234,568
' escape문자 '#'#,### #1,234,568
"#,### '1,234,568

예제1

import java.text.*;

class Ex10_6 {
	public static void main(String[] args) throws Exception {
		double number  = 1234567.89;
		String[] pattern = {
			"0",
			"#",
			"0.0",
			"#.#",
			"0000000000.0000",
			"##########.####",
			"#.#-",
			"-#.#",
			"#,###.##",
			"#,####.##",
			"#E0",
			"0E0",
			"##E0",
			"00E0",
			"####E0",
			"0000E0",
			"#.#E0",
			"0.0E0",
			"0.000000000E0",
			"00.00000000E0",
			"000.0000000E0",
			"#.#########E0",
			"##.########E0",
			"###.#######E0",
			"#,###.##+;#,###.##-",
			"#.#%",
			"#.#\u2030",
			"\u00A4 #,###",
			"'#'#,###",
			"''#,###",
		};
		
		for(int i=0; i < pattern.length; i++) {
		    DecimalFormat df = new DecimalFormat(pattern[i]);
		    System.out.printf("%19s : %s\n",pattern[i], df.format(number));
		}
	} // main
}

결과


예제2

import java.text.*;

class Ex10_7 {
	public static void main(String[] args) {
		DecimalFormat df  = new DecimalFormat("#,###.##");
		DecimalFormat df2 = new DecimalFormat("#.###E0");

		try {
			Number num = df.parse("1,234,567.89");
			System.out.print("1,234,567.89" + " -> ");

			double d = num.doubleValue(); 
			System.out.print(d + " -> ");

			System.out.println(df2.format(num));
		} catch(Exception e) {
			//예외처리
			e.printStackTrace();
		}
	} // main
}

결과

코드 1줄을 추가했다.

import java.text.*;

class Ex10_7 {
	public static void main(String[] args) {
		DecimalFormat df  = new DecimalFormat("#,###.##");
		DecimalFormat df2 = new DecimalFormat("#.###E0");

		try {
       		 //추가한 코드
			System.out.println(Double.parseDouble("1,234,567.89"));
			Number num = df.parse("1,234,567.89");
			System.out.print("1,234,567.89" + " -> ");

			double d = num.doubleValue(); 
			System.out.print(d + " -> ");

			System.out.println(df2.format(num));
		} catch(Exception e) {
			//예외처리
			e.printStackTrace();
		}
	} // main
}

System.out.println(Double.parseDouble("1,234,567.89")); 를 추가했는데

결과는 에러가 나왔다.

java.lang.NumberFormatException: For input string: "1,234,567.89"
	at java.base/jdk.internal.math.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:2054)
	at java.base/jdk.internal.math.FloatingDecimal.parseDouble(FloatingDecimal.java:110)
	at java.base/java.lang.Double.parseDouble(Double.java:651)
	at Ex10_7.main(Ex10_7.java:9)

에러가 뜬 이유는 타입이 맞지 않아서!

Double.parseDouble()메소드는 ,를 받아들이지 못한다.

에러 해결 방법

1. , (콤마)빼주기

,(콤마)를 쓰고 싶다면 Double이 아닌

2.  DecimalFormat 형식 써주기 

 

i) 1번 방법을 적용하여 에러 해결하기

import java.text.*;

class Ex10_7 {
	public static void main(String[] args) {
		DecimalFormat df  = new DecimalFormat("#,###.##");
		DecimalFormat df2 = new DecimalFormat("#.###E0");

		try {
       		 //추가한 코드
			System.out.println(Double.parseDouble("1234567.89"));
			Number num = df.parse("1,234,567.89");
			System.out.print("1,234,567.89" + " -> ");

			double d = num.doubleValue(); 
			System.out.print(d + " -> ");

			System.out.println(df2.format(num));
		} catch(Exception e) {
			//예외처리
			e.printStackTrace();
		}
	} // main
}

추가한 코드 System.out.println(Double.parseDouble("1,234,567.89")); 에서 ,(콤마)를 빼주었다.

 

=======결과=======

에러가 해결됐다! ㅎ

 


ii) 2번 방법으로 에러를 해결해보자!

import java.text.*;

class Ex10_7 {
	public static void main(String[] args) {
		DecimalFormat df  = new DecimalFormat("#,###.##");
		DecimalFormat df2 = new DecimalFormat("#.###E0");

		try {
        		//추가한코드
			System.out.println(df.parse("1,234,567.8888"));
			Number num = df.parse("1,234,567.89");
			System.out.print("1,234,567.89" + " -> ");

			double d = num.doubleValue(); 
			System.out.print(d + " -> ");

			System.out.println(df2.format(num));
		} catch(Exception e) {
			//예외처리
			e.printStackTrace();
		}
	} // main
}

DecimalFormat 형식을 써주기 위해서 System.out.println(df.parse("1,234,567.8888")); 코드를 추가했다.

 

DecimalFormat df  = new DecimalFormat("#,###.##"); 형식으로 출력이 될 것이다.

 

=======결과=======

에러 해결 ^^^


SimpleDateFormat 이란?

날짜를 형식화한 Format 이다.

DateFormat은 추상클래스로  SimpleDateFormat의 조상이다.

DateFormat은 추상클래스이므로 인스턴스 생성을 위해서는  getDateInstance()와 같은 static 메서드를 사용해야한다.

 

 

기호 의미 보기
G 연대(BC,AD) AD
y 년도 2022
M 월(1-12 또는 1월-12월) 10 또는 10월, OCT
w 년의 몇 번째 주(1-53) 50
W 월의 몇 번째 주(1-5) 4
D 년의 몇 번째 일(1~366) 100
d 월의 몇 번째 일(1-31) 15
F 월의 몇 번째 요일(1-5) 4
E 요일
a 오전/오후(AM,PM) PM
H 시간(0-23) 20
k 시간(1-24) 13
K 시간(0-11) 10
h 시간(1-12) 11
m 분(0-59) 58
s 초(0-59)  
S 천분의 일초(0-999)  
z Time zone(General time zone) GMT+9:00
Z Time zone(RFC 822 time zone) +0900
' escape문자
(특수문자를 표현하는데 사용)
없음

 

 


 

예제 3

import java.util.*;
import java.text.*;

class Ex10_8 {
	public static void main(String[] args) {
		Date today = new Date();//현재의 날짜와 시간을 저장

		SimpleDateFormat sdf1, sdf2, sdf3, sdf4;
		SimpleDateFormat sdf5, sdf6, sdf7, sdf8, sdf9;

		sdf1 = new SimpleDateFormat("yyyy-MM-dd");
		sdf2 = new SimpleDateFormat("''yy년 MMM dd일 E요일");
		//HH: 24시간 포맷
		sdf3 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
		//hh: 12시간 포맷
		sdf4 = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss a");

		sdf5 = new SimpleDateFormat("오늘은 올 해의 D번째 날입니다.");
		sdf6 = new SimpleDateFormat("오늘은 이 달의 d번째 날입니다.");
		sdf7 = new SimpleDateFormat("오늘은 올 해의 w번째 주입니다.");
		sdf8 = new SimpleDateFormat("오늘은 이 달의 W번째 주입니다.");
		sdf9 = new SimpleDateFormat("오늘은 이 달의 F번째 E요일입니다.");

		System.out.println(sdf1.format(today));	// format(Date d)
		System.out.println(sdf2.format(today));
		System.out.println(sdf3.format(today));
		System.out.println(sdf4.format(today));
		System.out.println();
		System.out.println(sdf5.format(today));
		System.out.println(sdf6.format(today));
		System.out.println(sdf7.format(today));
		System.out.println(sdf8.format(today));
		System.out.println(sdf9.format(today));
	}
}

 

===결과===

 

홑따옴표( ' ) 는 escape기호이기 때문에 패턴 내에서 표시하려면 홑따옴표를 연속 두 번 사용해야 한다.


예제 4

import java.util.*;
import java.text.*;

class Ex10_9 {
	public static void main(String[] args) {
		DateFormat df  = new SimpleDateFormat("yyyy년 MM월 dd일");
		DateFormat df2 = new SimpleDateFormat("yyyy/MM/dd");

		try {
			Date d = df.parse("2019년 11월 23일");
			System.out.println(df2.format(d));
		} catch(Exception e) {}
	} // main
}

===결과===

(지정된 형식과 입력된 형식이 일치하지 않는 경우에는 예외가 발생하므로 적절한 예외처리가 필요하다.)

 

Integer의 parseInt()는 문자열을 정수로 변환하는 것처럼

parse(String source)문자열 source 날짜 Date 인스턴스로 변환해주기 때문에 매우 유용하다.

 

 

 

예외 발생 시켜보기

import java.util.*;
import java.text.*;

class Ex10_9 {
	public static void main(String[] args) {
		DateFormat df  = new SimpleDateFormat("yyyy년 MM월 dd일");
		DateFormat df2 = new SimpleDateFormat("yyyy/MM/dd");

		try {
			Date d = df.parse(" 11월 23일");
			System.out.println(df2.format(d));
		} catch(Exception e) {
			System.out.println("예외발생욥");
		}
	} // main
}

결과

 


 

예제 5

import java.util.*;
import java.text.*;

class Ex10_10 {
	public static void main(String[] args) {
		String pattern = "yyyy/MM/dd"; 
		DateFormat df = new SimpleDateFormat(pattern);
		Scanner s = new Scanner(System.in);

		Date inDate = null;

		System.out.println("날짜를 " + pattern 
		+ "의 형태로 입력해주세요.(입력예:2019/12/31)");
		while(s.hasNextLine()) {
			try {
				inDate = df.parse(s.nextLine());
				break;
			} catch(Exception e) {
				System.out.println("날짜를 " + pattern 
				+ "의 형태로 다시 입력해주세요.(입력예:2019/12/31)");
			}
		} // while

		Calendar cal = Calendar.getInstance();
		cal.setTime(inDate);
		Calendar today = Calendar.getInstance();
		long day = (cal.getTimeInMillis()
		- today.getTimeInMillis())/(60*60*1000);
		System.out.println("입력하신 날짜는 현재와 "+ day +"시간 차이가 있습니다.");
	} // main
}

hasNextLine()은 다음에 읽을 값이 있는지 확인하는 boolean타입의 메소드로 값이 있으면 true를 반환한다.

다음줄에 입력이 있는지 여부를 판단해 입력이 있으면 True를, 없다면 False를 반환한다

(입력이 있을때까지 기다렸다가 True를 반환하기 때문에  close()로 닫아주지 않으면 무한루프에 빠질 수 있다.)

 

NextLine()은 줄 단위로 값을 읽어온다.

여기서 줄 단위가 아닌 단어를 단위로 하고 싶으면 둘 다 Line을 빼고 사용하면 된다.

 

===결과===