본문 바로가기

안드로이드 Android

안드로이드 개발(1) - Java 시간 표시 처리 대비

오늘 작은 사이드 협업의 모든 기능을 다 끝냈습니다.

사이드 협업중 하나는 올드한 느낌을 한번 맛보고 싶어서

ViewBinding 혹은 DataBinding 쓰지 않고

findViewById를 사용하면서 언어는 Java 로 진행중이었습니다.

 

(주요 프로젝트에서 Kotlin과 DataBinding을 주로 쓰는데 오랜만에 옛 감성이 땡겼네요(?)

이래서 고전게임을 좋아하시는 분이 많은가보다.)

 

 Kotlin으로 작업할땐 코드가 반복되거나 장황해지는게 싫어서

File 하나 만들어서 확장 함수를 많이 사용하거나 

Binding Adapter로 효과를 톡톡히 보는걸 좋아합니다. 

 

그런데 Java에 확장 함수는 존재하지 않아서 별도의 클래스를 직접 만들어야 합니다.

(Kotlin에서는 File만들어서 안에 함수를 만들어 사용할시 클래스 생략 가능..

자동으로 클래스를 생성해준다고한다.)

 

앱 프로젝트를 하다보면 시간 표시를 해야하는 경우가 많은데

SimpleDateFormat() 으로 열심히 일일히 쓰다보면 너무 손가락이 아픕니다..

딱히 중요한 일이 아닌것들은

Util로 만들어 처리하는것이 편합니다.

 

반복되는 코드는 함축을 시켜 일처리를 우선할 부분에 

집중하는 환경을 만드는것이 가장 베스트라고 생각합니다.

 

-시간 표시를 클래스 하나로 끝내 버리는법 

내가 사용한 서버에서 yyyy-MM-dd HH:mm:ss (한국 시간 기준)

형식으로 String으로 해당 db가 만들어진 시간이나

업데이트 된 시간들을 db에 저장하고 있는 상황에서 사용한 것 입니다. 

 

서버에서 시간을 받으면 yyyy-MM-dd HH:mm:ss 형식으로 String으로 받아 여러가지를 사용해야하니,

미리 준비를 안해놓으면 여간 불편한 일이 아닐 수 없었습니다.

 

예를들어 yyyy-MM-dd HH:mm:ss 이 패턴에서 "yyyy년 MM월 dd일 HH시 mm분 ss초" 혹은

"MM/dd HH시 mm분" 등등 다양하게 변화를 시켜줘야했습니다.

그리고 유저가 사용하는 현재시간과 비교해서 

몇분전, 몇시간 전 등등에 맞춰서 표시를 해줘야하기도 합니다.

 

그러기 위해서는 우선 Date 형식으로 변환 시킬 필요가 있었습니다. 

 

public static Date getDate(String from) throws ParseException {
// "yyyy-MM-dd HH:mm:ss"
SimpleDateFormat transFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.KOREAN);
return transFormat.parse(from);
}

 

- 서버에서 받는 yyyy-MM-dd HH:mm:ss 문자열을 받는 순간 바로 Date 클래스로 변환을 시킴.

- Date 클래스과 SimpleDateFormat 다양한 형태로 String형변화 시킬수 있다.

 

public static String getString(Date date, String pattern) {
SimpleDateFormat transFormat = new SimpleDateFormat(pattern, Locale.KOREA);
return transFormat.format(date);
}

getString 이라는 함수를 하나 더 만들었다. (변수명 최악이네..)

이 함수의 특징으로 인자로 Date 와 String을 받는다.

pattern이라고 변수명을 지었다시피, 내가 원하는 패턴만 넣는다면..

 

getString(date,"yyyy년 MM월 dd일") -> output "2021년 05월 19일"

이런식으로 내가 원하는 패턴에 따라 빠르게 스트링 값으로 리턴 받을 수 있습니다.

 

그리고... 위의 두개의 함수로 나뉘어 사용 했는데 두개의 함수를 나눠 쓰기도 귀찮습니다. 아예 통합해버렸습니다.

 

public static String resultDateToString(String date, String pattern) throws ParseException {
Date tempDate = getDate(date);
return getString(tempDate, pattern);
}

 

이 함수를 사용해서 바로 서버에서 받는 String 문자열과

최종적으로 사용할 패턴을 패러미터로 적는다면,

두개의 함수를 나눌필요없이  하나의 함수로 바로 pattern에 맞는 값을 추출해낼 수 있었습니다.

 

개인적으로 바로 input 후 output 이 나오는걸 상당히 좋아하는데,

위 함수를 만들고 나니 서버의 시간 값은 금방 변환하여 사용할 수 있음으로

작업속도가 조금은 향상된걸 작업하면서 느꼇습니다.

 

위에 만든  3개의 함수를 통해 많은 부분에서 활용할 수 있었습니다. 예를들어, 

 

아래와 같은 경우를 봐보면 현재 시간 기준으로 시간차이가 얼마나 나는지 UI를 표시한다 했을 때,

60분이 지나면 1시간이 되서 시 분 단위로 표시하고 24시간이 지나면 날짜가 표시가 되어야합니다. 

 

이러한 변환 과정에 있어서 위에 미리 만들어둔 함수들이 큰 역활을 해줍니다

현재 시간과 db 시간 차이 구하기 

 

public static Long getCurrentTime() {
return System.currentTimeMillis();
}
public static Long getStringToTime(String date) throws ParseException {
return getDate(date).getTime();
}

long 타입으로 밀리세컨드를 구할 두개의 함수를 만듭니다.

 

1. getCurrentTime() 함수는 현재 시간의 밀리세컨드를 구해줄 것이고,

2. getStringToTime은 서버에서 받는 String형식을 위에 만들어둔

getDate() 함수로 Date로 변환 한뒤  밀리세컨드를 구해서 롱타입으로 리턴해줍니다.

public static String getUploadMinuteTime(Long curTime,

String dateTime,String pattern) throws ParseException {

long boardTime = getStringToTime(dateTime);
long result = (curTime - boardTime) / 60000;
//분으로 표현,//시 + 분으로 표현
if (result < 60) {
  return result + "분전";
} else if (result > 1440) {
    return resultDateToString(dateTime, pattern);
} else {

     int num = String.valueOf(result / 60.0).indexOf(".");
     String minute = String.valueOf(result / 60.0).substring(num);
     int newMinute = (int) (Double.parseDouble("0" + minute) * 60);
    return result / 60 + "시간" + newMinute + "분전";
}
}

그 후 시간 차이를 구할 함수를 만들었습니다.

(curTime - boardTime) 60000; 

위처럼 현재시간과 db에 기록된 비교한 후 60000을 나누면 밀리세컨드가 "분"으로 표시가 됩니다.

분으로 나눈 후에 만든 변수로 분기처리를 해서  return을 다르게 하면 됩니다.

 

3가지 분기로 나뉘는데 

1) 현재시간과 db의 시간이 60분 미만으로 차이가 날 경우  xx분전 으로 String을 return

2) 현재시간과 db의 시간이 60분 이상 하루 미만으로 치아기 날 경우  xx시간 + xx분전 으로 return

3) 현재시간과 db의 시간이 하루 이상 차이가 날 경우 내가 원하는 패턴으로 String을 return 

 

이렇게 설정해놓으니 시간 표시하는것에 있어서 힘든점이 전혀 없었습니다.

간단히 함수로 만들어 처리해버리는 프로그래밍의 아름다움이란 위대하구나..

 

결과적으로 전체 코드를 보자면 아래와 같습니다. 

 

public class DateConverter {

public static Date getDate(String from) throws ParseException {
// "yyyy-MM-dd HH:mm:ss"
SimpleDateFormat transFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.KOREAN);
return transFormat.parse(from);
}

public static String getString(Date date, String pattern) {
SimpleDateFormat transFormat = new SimpleDateFormat(pattern, Locale.KOREA);
return transFormat.format(date);
}

public static String resultDateToString(String date, String pattern) throws ParseException {
Date tempDate = getDate(date);
return getString(tempDate, pattern);
}

public static Long getCurrentTime() {
return System.currentTimeMillis();
}

public static Long getStringToTime(String date) throws ParseException {
return getDate(date).getTime();
}

public static String getUploadMinuteTime(Long curTime, String dateTime,String pattern) throws ParseException {

long boardTime = getStringToTime(dateTime);
long result = (curTime - boardTime) / 60000;
//분으로 표현,//시 + 분으로 표현
if (result < 60) {
return result + "분전";
} else if (result > 1440) {
return resultDateToString(dateTime, pattern);
} else {
int num = String.valueOf(result / 60.0).indexOf(".");
String minute = String.valueOf(result / 60.0).substring(num);
int newMinute = (int) (Double.parseDouble("0" + minute) * 60);
return result / 60 + "시간" + newMinute + "분전";
}
}
}

 

 

클래스파일 하나 만들어 사용하면 됩니다. 실사용은 편하게 아래와 같은식으로 사용합니다.

 

개인적으로 oop만의 정보은닉 특성을 좋아하면서 동시에

input후 바로 output 이 나오는것도 무척 좋아하다보니 많은 괴랄한 작품(?)들을 만들어 내는거 같네요..

 

정말 코딩은 다양한 방법으로 즐길 수 있어서 그 매력은 끝을 알 수가 없습니다.