Continuous Challenge

[Java의 정석_연습문제 풀이] Chapter10 날짜와 시간 & 형식화 본문

Study/Java의 정석

[Java의 정석_연습문제 풀이] Chapter10 날짜와 시간 & 형식화

응굥 2019. 10. 30. 10:44
728x90
728x90

[10-1] Calendar 클래스와 SimpleDateFormat클래스를 이용해서 2010년의 매월 두 번째 일요일의 날짜를 출력하시오.

[실행결과]

2010-01-10은 2번째 일요일입니다.

2010-02-14은 2번째 일요일입니다.

2010-03-14은 2번째 일요일입니다.

2010-04-11은 2번째 일요일입니다.

2010-05-09은 2번째 일요일입니다.

2010-06-13은 2번째 일요일입니다.

2010-07-11은 2번째 일요일입니다. 

2010-08-08은 2번째 일요일입니다.

2010-09-12은 2번째 일요일입니다. 

2010-10-10은 2번째 일요일입니다.

2010-11-14은 2번째 일요일입니다.

2010-12-12은 2번째 일요일입니다.

답:

import java.text.SimpleDateFormat;

import java.util.Calendar;


public class Exercise10_1 {

public static void main(String[] args){

Calendar cal = Calendar.getInstance();

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

cal.set(Calendar.YEAR, 2010);

for(int i = Calendar.JANUARY; i <= Calendar.DECEMBER; i++){

cal.set(Calendar.MONTH, i);

cal.set(Calendar.WEEK_OF_MONTH, 3);

cal.set(Calendar.DAY_OF_WEEK, Calendar.SUNDAY);

System.out.println(sdf.format(cal.getTime())+"은 2번째 일요일입니다.");

}

}

}


답:

import java.text.SimpleDateFormat;

import java.util.Calendar;

import java.util.Date;


public class Exercise10_1 {

public static void main(String[] args){

Calendar cal = Calendar.getInstance();

cal.set(2010,0,1); //cal의 날짜를 2010년 1월 1일로 설정한다.

for(int i =0;i<12;i++){

int weekday = cal.get(Calendar.DAY_OF_WEEK); //1일의 요일을 구한다.

//두 번째 일요일은 1일의 요일에 따라 달라진다.

//1일이 일요일인 경우에는 두번째 일요일은 8일이고,

//1일이 다른 요일일 때는 16에서 1일의 요일을 빼면 알 수 있다.

int secondSunday = (weekday == 1)?8:16-weekday;

//두 번째 일요일로 cal의 날짜(DAY_OF_MONTH)를 바꾼다.

cal.set(Calendar.DAY_OF_MONTH, secondSunday);

Date d = cal.getTime(); //Calendar를 Date로 변환한다.

System.out.println(new SimpleDateFormat("yyyy-MM-dd은 F번째 E요일입니다.").format(d));

//날짜를 다음달 1일로 변경한다.

cal.add(Calendar.MONTH, 1);

cal.set(Calendar.DAY_OF_MONTH,1);

}

}

}


[10-2] 어떤 회사의 월급날이 매월 21일이다. 두 날짜 사이에 월급날이 몇 번있는지 계산해서 반환하는 메서드를 작성하고 테스트하시오.

import java.util.*;

import java.text.*;


class Exercise10_2 {

static int paycheckCount(Calendar from, Calendar to) {


/*

* (1) 아래의 로직에 맞게 코드를 작성하시오. 

* 1.from 또는 to가 null이면 0을 반환한다. 

* 2.from와 to가 같고 날짜가 21일이면 1을 반환한다.  

* 3.to와 from이 몇 개월 차이인지 계산해서 변수 monDiff에 담는다.

* 4.monDiff가 음수이면 0을 반환한다.

* 5.만일 from의 일(DAY_OF_MONTH)이 21일이거나 이전이고 

*   to의 일(DAY_OF_MONTH)이 21일이거나 이후이면 monDiff의 값을 1 증가시킨다.

* 6.만일 from의 일(DAY_OF_MONTH)이 21일 이후고

*   to의  일(DAY_OF_MONTH)이 21일 이전이면 monDiff의 값을 1 감소시킨다.

*/

return monDiff;

}


static void printResult(Calendar from, Calendar to) {

Date fromDate = from.getTime();

Date toDate = to.getTime();


SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

System.out.print(sdf.format(fromDate) + "~" + sdf.format(toDate) + ":");

System.out.println(paycheckCount(from, to));

}


public static void main(String[] args) {

Calendar fromCal = Calendar.getInstance();

Calendar toCal = Calendar.getInstance();

fromCal.set(2010, 0, 1);

toCal.set(2010, 0, 1);

printResult(fromCal, toCal);

fromCal.set(2010, 0, 21);

toCal.set(2010, 0, 21);

printResult(fromCal, toCal);

fromCal.set(2010, 0, 1);

toCal.set(2010, 2, 1);

printResult(fromCal, toCal);

fromCal.set(2010, 0, 1);

toCal.set(2010, 2, 23);

printResult(fromCal, toCal);

fromCal.set(2010, 0, 23);

toCal.set(2010, 2, 21);

printResult(fromCal, toCal);

fromCal.set(2011, 0, 22);

toCal.set(2010, 2, 21);

printResult(fromCal, toCal);

}

}


[실행결과]

2010-01-01~2010-01-01:0 

2010-01-21~2010-01-21:1 

2010-01-01~2010-03-01:2 

2010-01-01~2010-03-23:3 

2010-01-23~2010-03-21:2

2011-01-22~2010-03-21:0

답:

int monDiff;


int fMonth = from.get(Calendar.MONTH);

int tMonth = to.get(Calendar.MONTH);

int fDay = from.get(Calendar.DAY_OF_MONTH);

int tDay = to.get(Calendar.DAY_OF_MONTH);


if(from == null || to == null) return 0;

if(from.compareTo(to)==0  && fDay == 21) return 1;


monDiff = tMonth - fMonth;

if(monDiff < 0) return 0;

if(fDay <= 21 || tDay >= 21) monDiff++;

if(fDay >= 21 || tDay <= 21) monDiff--;


[10-3] 문자열 "123,456,789.5"를 소수점 첫 번째 자리에서 반올림하고, 그 값을 만 단위마다 콤마( , )로 구분해서 출력하시오.

[실행결과]

data:123,456,789.5 

반올림:123456790 

만단위:1,2345,6790

답:

import java.text.DecimalFormat;


public class Exercise10_3 {

public static void main(String[] args) {

String data = "123,456,789.5";


DecimalFormat formatter = new DecimalFormat("####,####");

Long roundData = Math.round(Double.parseDouble(data.replace(",", "")));

System.out.println("data: " + data);

System.out.println("반올림: " + roundData.toString());

System.out.println("만단위: " + formatter.format(roundData));

}

}


답:

public class Exercise10_3 {

public static void main(String[] args){

String data = "123,456,789.5";

DecimalFormat df = new DecimalFormat("#,###.##"); //변환할 문자열의 형식을 지정

DecimalFormat df2 = new DecimalFormat("#,####");

try{

Number num = df.parse(data);

double d = num.doubleValue();

System.out.println("data:"+data);

System.out.println("반올림:"+Math.round(d));

System.out.println("만단위:"+df2.format(d));

}catch(Exception e){}

}

}

해설 : 

특정 형식의 문자열을 숫자로 변환하려면 DecimalFormat클래스에 형식을 정의해준 다음에 parse()를 이용하면 된다. parse()의 반환타입이 Number이기 때문에, Number에서 다시 doubleValue()를 호출해서 double의 값을 얻어야 한다.

format()은 주어진 값을 정해진 형식에 맞게 변환한 다음에 문자열(String)로 반환한다.


[10-4] 화면으로부터 날짜를 "2007/05/11"의 형태로 입력받아서 무슨 요일인지 출력하는 프로그램을 작성하시오.

단, 입력된 날짜의 형식이 잘못된 경우 메세지를 보여주고 다시 입력받아야 한다.

[실행결과]

날짜를 yyyy/MM/dd의 형태로 입력해주세요. (입력예:2007/05/11)

>>2009-12-12

날짜를 yyyy/MM/dd의 형태로 입력해주세요. (입력예:2007/05/11)

>>2009/12/12

입력하신 날짜는 토요일입니다.

답:

import java.text.ParseException;

import java.text.SimpleDateFormat;

import java.util.Calendar;

import java.util.Date;

import java.util.Scanner;


public class Exercise10_4 {

public static void main(String[] args) throws ParseException {


while (true) {

System.out.println("날짜를 yyyy/MM/dd의 형태로 입력해주세요. (입력예:2007/05/11)");

Scanner s = new Scanner(System.in);

String date = s.nextLine();

if (date.matches("\\d{4}/\\d{2}/\\d{2}")) {

SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");

Date d = sdf.parse(date);

Calendar c = Calendar.getInstance();

c.setTime(d);


int day = c.get(Calendar.DAY_OF_WEEK);

String sDay = "";

switch (day) {

case 1:

sDay = "일";

break;

case 2:

sDay = "월";

break;

case 3:

sDay = "화";

break;

case 4:

sDay = "수";

break;

case 5:

sDay = "목";

break;

case 6:

sDay = "금";

break;

case 7:

sDay = "토";

}

System.out.println("입력하신 날짜는 " + sDay + "요일입니다.");

} else {

continue;

}

}

}

}


답:

import java.text.DateFormat;

import java.text.SimpleDateFormat;

import java.util.Date;

import java.util.Scanner;


public class Answer10_4 {

public static void main(String[] args){

String pattern = "yyyy/MM/dd";

String pattern2 = "입력하신 날짜는 E요일입니다."; //'E'는 일~토 중의 하나가 된다.

DateFormat df = new SimpleDateFormat(pattern);

DateFormat df2 = new SimpleDateFormat(pattern2);

Scanner s = new Scanner(System.in);

Date inDate = null;

do{

System.out.println("날짜를 " + pattern + "의 형태로 입력해주세요. (입력예:2007/05/11)");

try{

System.out.print(">>");

inDate = df.parse(s.nextLine()); //입력받은 날짜를 Date로 변환한다.

break; //parse()에서 예외가 발생하면 이 문장은 수행되지 않는다.

}catch(Exception e){}

}while(true);

System.out.println(df2.format(inDate));

}

}


[10-5] 다음과 같이 정의된 메서드를 작성하고 테스트하시오.     

메서드명: getDayDiff

기능: yyyymmdd형식의 두 문자열을 넘겨받으면 두 날짜의 차이를 일(day)단위로 반환한다.

  단, 첫 번째 날짜 빼기 두 번째 날짜의 결과를 반환한다.

  만일 주어진 문자열이 유효하지 않으면 0을 반환한다.

반환타입: int

매개변수: String yyyymmdd1 - 시작 날짜                                                                                                                         String yyyymmdd2 - 끝 날짜

import java.util.*; 


class Exercise10_5 { 

/* 

* (1)getDayDiff 메서드를 작성하시오.

*/ 

public static void main(String[]args){ 

System.out.println(getDayDiff("20010103","20010101")); 

System.out.println(getDayDiff("20010103","20010103")); 

System.out.println(getDayDiff("20010103","200103")); 

}

}


[실행결과]

2

0

0

답:

public static int getDayDiff(String yyyymmdd1, String yyyymmdd2){

SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd");

int ret = 0;

try {

Date date1 = format.parse(yyyymmdd1);

Date date2 = format.parse(yyyymmdd2);

long diff = (date1.getTime() - date2.getTime()) / (24*60*60*1000);

ret = (int)Math.abs(diff);

} catch (ParseException e) {

//e.printStackTrace();

}

return ret;

}


[10-6] 자신이 태어난 날부터 지금까지 며칠이 지났는지 계산해서 출력하시오.

[실행결과]

birth day =2000-01-01

today = 2016-01-29

5872 days

답:

import java.text.ParseException;

import java.text.SimpleDateFormat;

import java.util.Calendar;

import java.util.Date;


public class Exercise10_6 {

public static void main(String[] args) {

String sBDay = "19941112";

Calendar cal = Calendar.getInstance();

SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd");


try {

Date bDay = format.parse(sBDay);

Date today = new Date();

long days = (today.getTime() - bDay.getTime())/ (24 * 60 * 60 * 1000);

System.out.println(days + " days");

} catch (ParseException e) {

// e.printStackTrace();

}

}

}


답: LocalDate의 until()을 이용하면 쉽게 해결된다.

import java.time.*;

import java.time.temporal.*;


public class Exercise10_6 {

public static void main(String[] args){

LocalDate birthDay = LocalDate.of(1994,11,12);

LocalDate now = LocalDate.now();

long days = birthDay.until(now, ChronoUnit.DAYS);

System.out.println("birth day="+birthDay);

System.out.println("today    ="+now);

System.out.println(days+" days");

}

}


[10-7] 2016년 12월 넷째주 화요일의 날짜를 아래의 실행결과와 같은 형식으로 출력하시오.

[실행결과]

2016-12-27

답:

import java.text.SimpleDateFormat;

import java.util.Calendar;


public class Exercise10_7 {

public static void main(String[] args){

Calendar cal = Calendar.getInstance();

cal.set(Calendar.YEAR, 2016);

cal.set(Calendar.MONTH, Calendar.DECEMBER);

cal.set(Calendar.WEEK_OF_MONTH, 5);

cal.set(Calendar.DAY_OF_WEEK, Calendar.TUESDAY);

SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");

System.out.println(format.format(cal.getTime()));

}

}


답: ?째주 ?요일은 TemporalAdjusters 클래스의 dayOfWeekInMonth()를 이용하면 된다.

import java.time.*;

import static java.time.DayOfWeek.*;

import static java.time.temporal.TemporalAdjusters.*;


public class Answer10_7 {

public static void main(String[] args) {

LocalDate date = LocalDate.of(2016, 12, 1);

System.out.println(date.with(dayOfWeekInMonth(4, TUESDAY)));

}

}


[10-8] 서울과 뉴욕간의 시차가 얼마인지 계산하여 출력하시오.

[실행결과]

2016-01-28T23:01:00.136+09:00[Asia/Seoul] 

2016-01-28T09:01:00.138-05:00[America/New_York] 

sec1=32400 

sec2=-18000 

diff=14 hrs

답:

import java.time.ZoneId;

import java.time.ZonedDateTime;


public class Exercise10_8 {

public static void main(String[] args) {

ZonedDateTime zdt = ZonedDateTime.now();

ZoneId nyId = ZoneId.of("America/New_York");

ZonedDateTime zdtNY = ZonedDateTime.now().withZoneSameInstant(nyId);


System.out.println(zdt);

System.out.println(zdtNY);


long sec1 = zdt.getOffset().getTotalSeconds();

long sec2 = zdtNY.getOffset().getTotalSeconds();

long diff = (sec1 - sec2) / 3600;


System.out.println("sec1=" + sec1);

System.out.println("sec2=" + sec2);

System.out.printf("diff=%d hrs%n", diff);

}

}

해설: ZonedDateTime의 getOffset()은 ZoneOffset을 반환한다. ZoneOffset의 getTotalSeconds()를 호출하면, 날짜와 시간을 초단위로 변환한 결과를 얻을 수 있다.


728x90
728x90
Comments