관리 메뉴

나만을 위한 블로그

[Android] 날짜 변환 시 사용하는 enum과 확장 함수 모음 본문

Android

[Android] 날짜 변환 시 사용하는 enum과 확장 함수 모음

참깨빵위에참깨빵 2022. 11. 10. 01:35
728x90
반응형

이 포스팅은 아래의 미디엄 링크를 보고 작성했다.

 

https://medium.com/@abdulqadirtr/android-how-to-convert-your-datetime-to-different-formats-using-extension-function-7ade5de76522

 

Android How to Convert your dateTime to different formats using extension function

A very useful extension function for converting your date to different formats by using extension function.

medium.com

 

날짜를 1분 전, 4시간 전 등으로 바꿔야 하는 경우도 있지만 가끔은 yyyy-MM-dd 형태로 바꿔야 하는 경우도 있기 마련이다.

위 포스팅이 이것에 대해 다루는데, 앞으로 유용하게 쓸 수 있을 것 같아 포스팅으로 남겨둔다. 그 전에 밑준비부터 한다.

먼저 values 폴더에 format_date.xml 파일을 만들고 아래 내용을 복붙한다.

 

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string-array name="format_date">
        <item>Default format</item>
        <item>Date time  YYYY MM DD Format</item>
        <item>Date time  YYYY MM DD HH:mm Format</item>
        <item>Date time  YYYY MM DD HH:mm:ss Format</item>
        <item>MONTH AND YEAR MM DD YYYY Format</item>

        <item>Date time  DD MM YYYY HH:mm:ss Format</item>
        <item>Date YYYY MM DD Format</item>
        <item>Date / Name of Week/ year Format</item>
        <item>Week name / Date Month Format</item>
        <item>Date / Name of Month</item>
        <item>Date time  DD MM YYYY - HH:mm:ss Format</item>
        <item>AM / PM Format</item>
    </string-array>
</resources>

 

스피너 클릭 시 보여줄 리스트에 들어갈 문장들이다. 저 형식대로 바뀐 날짜를 보여줄 것이다.

XML은 아래와 같이 작성한다.

 

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".other.DateTimeActivity">

        <TextView
            android:id="@+id/text1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="20dp"
            android:textColor="@color/cardview_dark_background"
            android:textSize="28sp"
            android:textStyle="bold"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

        <Spinner
            android:id="@+id/spinner"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginHorizontal="12dp"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/text1"
            android:layout_marginTop="30dp"
            android:background="@android:color/transparent"
            android:gravity="center"
            android:spinnerMode="dropdown" />

        <TextView
            android:id="@+id/welcomeFormatText"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/spinner" />

    </androidx.constraintlayout.widget.ConstraintLayout>

</layout>

 

그리고 미디엄 포스팅에선 enum class를 활용하기 때문에 포스팅과 똑같이 enum class를 만든다.

 

enum class DateFormats(
    val format: String
) {
    DEFAULT_FORMAT("yyyy-MM-dd'T'HH:mm:ss"),                        // 2021-05-20T11:28:24Z
    DEFAULT_FORMAT_WITHOUT_TIME("yyyy-MM-dd"),                      // 2021-05-20
    DATE_TIME_YY_MM_FORMAT("yyyy-MM-dd'T'HH:mm"),                   // 2021-05-20T11:28
    DATE_TIME_YY_MM_FULL_TIME_FORMAT("yyyy-MM-dd'T'HH:mm:ss"),      // 2021-05-20T11:28
    DATE_MM_DD_YY_FORMAT("MM-dd-yyyy"),                             // 05-20-2021
    DATE_MM_DD_FORMAT("MMM dd, yyyy"),                              // May 20,2021
    FULL_DATE_TIME_DD_MM_FORMAT("dd-MM-yyyy'T'HH:mm:ss"),           // 2021-05-20T11:28:24
    DATE_YY_MM_FORMAT("yyyy-MM-dd"),                                // 2021-05-20
    DATE_MONTH_OF_YEAR_FORMAT("d MMMM, yyyy"),                      // 20 May, 2021
    DAY_OF_WEEK_MONTH_FORMAT("EEE, d MMM"),                         // Thu, 20 May
    DATE_MONTH_FORMAT("d MMM"),                                     // 20 MAY
    DATE_TIME_FORMAT_CUSTOM_FORMAT("dd.MM.yyyy' - ' HH:mm:ss"),     // 21.06.2021 - 10:10:18
}

 

그리고 확장 함수를 만들 파일을 만든다. 파일의 이름은 StringDateUtil이다.

 

import java.text.SimpleDateFormat
import java.util.*

fun String.convertDefaultWithoutTime(format: String): String? {
    val dateFormat = SimpleDateFormat(format, Locale.getDefault())
    val parsedDate = dateFormat.parse(this)
    val dayMonthFormat =
        SimpleDateFormat(DateFormats.DEFAULT_FORMAT_WITHOUT_TIME.format, Locale.getDefault())

    return parsedDate?.let { dayMonthFormat.format(parsedDate) }
}

fun String.convertDateToYMDTime(format: String): String? {
    val dateFormat = SimpleDateFormat(format, Locale.getDefault())
    val parsedDate = dateFormat.parse(this)
    val dayMonthFormat =
        SimpleDateFormat(DateFormats.DATE_TIME_YY_MM_FULL_TIME_FORMAT.format, Locale.getDefault())

    return parsedDate?.let { dayMonthFormat.format(parsedDate) }
}

fun String?.formatStringDate(inputFormat: String, outputFormat: String): String {
    return if (this.isNullOrEmpty()) {
        ""
    } else {
        val dateFormatter = SimpleDateFormat(inputFormat, Locale.getDefault())
        val date = dateFormatter.parse(this)
        date?.let { SimpleDateFormat(outputFormat, Locale.getDefault()).format(it) }.orEmpty()
    }
}

fun String.convertDateToYMDFullTimeDate(format: String): String? {
    val dateFormat = SimpleDateFormat(format, Locale.getDefault())
    val parsedDate = dateFormat.parse(this)
    val dayMonthFormat =
        SimpleDateFormat(DateFormats.DATE_TIME_YY_MM_FORMAT.format, Locale.getDefault())

    return parsedDate?.let { dayMonthFormat.format(parsedDate) }
}


fun String.trimTimeFromDateMDY(format: String): String? {
    val dateFormat = SimpleDateFormat(format, Locale.getDefault())
    val parsedDate = dateFormat.parse(this)
    val trimmed = SimpleDateFormat(DateFormats.DATE_MM_DD_YY_FORMAT.format, Locale.getDefault())

    return parsedDate?.let { trimmed.format(parsedDate) }
}

fun String.convertDateToDMYFullTimeDate(format: String): String? {
    val dateFormat = SimpleDateFormat(format, Locale.getDefault())
    val parsedDate = dateFormat.parse(this)
    val dayMonthFormat =
        SimpleDateFormat(DateFormats.FULL_DATE_TIME_DD_MM_FORMAT.format, Locale.getDefault())

    return parsedDate?.let { dayMonthFormat.format(parsedDate) }
}

fun String.convertDateToYMD(format: String): String? {
    val dateFormat = SimpleDateFormat(format, Locale.getDefault())
    val parsedDate = dateFormat.parse(this)
    val dayMonthFormat = SimpleDateFormat(DateFormats.DATE_YY_MM_FORMAT.format, Locale.getDefault())

    return parsedDate?.let { dayMonthFormat.format(parsedDate) }
}

fun String.convertDateToMonthNameYear(format: String): String? {
    val dateFormat = SimpleDateFormat(format, Locale.getDefault())
    val parsedDate = dateFormat.parse(this)
    val dayMonthFormat =
        SimpleDateFormat(DateFormats.DATE_MONTH_OF_YEAR_FORMAT.format, Locale.getDefault())

    return parsedDate?.let { dayMonthFormat.format(parsedDate) }
}

fun String.convertDateToWeekNameYear(format: String): String? {
    val dateFormat = SimpleDateFormat(format, Locale.getDefault())
    val parsedDate = dateFormat.parse(this)
    val dayMonthFormat =
        SimpleDateFormat(DateFormats.DAY_OF_WEEK_MONTH_FORMAT.format, Locale.getDefault())

    return parsedDate?.let { dayMonthFormat.format(parsedDate) }
}

fun String.convertDateMonthName(format: String): String? {
    val dateFormat = SimpleDateFormat(format, Locale.getDefault())
    val parsedDate = dateFormat.parse(this)
    val dayMonthFormat = SimpleDateFormat(DateFormats.DATE_MONTH_FORMAT.format, Locale.getDefault())

    return parsedDate?.let { dayMonthFormat.format(parsedDate) }
}

fun String.convertDateCustom(format: String): String? {
    val dateFormat = SimpleDateFormat(format, Locale.getDefault())
    val parsedDate = dateFormat.parse(this)
    val dayMonthFormat =
        SimpleDateFormat(DateFormats.DATE_TIME_FORMAT_CUSTOM_FORMAT.format, Locale.getDefault())

    return parsedDate?.let { dayMonthFormat.format(parsedDate) }
}

fun String.convertDateToAmPm(format: String): String? {
    val dateFormat = SimpleDateFormat(format, Locale.getDefault())
    val parsedDate = dateFormat.parse(this)
    val dayMonthFormat = SimpleDateFormat("hh:mm a", Locale.getDefault())

    return parsedDate?.let { dayMonthFormat.format(parsedDate) }
}

 

이제 액티비티 코틀린 파일을 아래처럼 바꿔준다.

 

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.View
import android.widget.AdapterView
import android.widget.ArrayAdapter
import android.widget.Toast
import com.example.kotlinprac.R
import com.example.kotlinprac.databinding.ActivityDateTimeBinding
import kotlinx.android.synthetic.main.activity_date_time.*

class DateTimeActivity : AppCompatActivity() {

    private val TAG = this.javaClass.simpleName
    var date1 = "2022-11-10T10:10:00"
    var result: String = ""

    private val binding by lazy {
        ActivityDateTimeBinding.inflate(layoutInflater)
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(binding.root)

        ArrayAdapter.createFromResource(this, R.array.format_date, android.R.layout.simple_spinner_item).also { adapter ->
            adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
            this.spinner.adapter = adapter

            this.spinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
                override fun onItemSelected(
                    parentView: AdapterView<*>?,
                    selectedItemView: View,
                    position: Int,
                    id: Long
                ) {
                    when (position) {
                        1 -> {
                            var dayMonth = date1
                            dayMonth = dayMonth.convertDefaultWithoutTime(DateFormats.DEFAULT_FORMAT.format).toString()
                            result = dayMonth
                        }
                        2 -> {
                            var trimHour = date1
                            trimHour = trimHour.convertDateToYMDFullTimeDate(DateFormats.DEFAULT_FORMAT.format).toString()
                            result = trimHour
                        }
                        3 -> {
                            var timeAMPM = date1
                            timeAMPM = timeAMPM.convertDateToYMDFullTimeDate(DateFormats.DEFAULT_FORMAT.format)
                                .toString()
                            result = timeAMPM
                        }
                        4 -> {
                            var timeAMPM = date1
                            timeAMPM = timeAMPM.trimTimeFromDateMDY(
                                DateFormats.DEFAULT_FORMAT.format,
                            ).toString()
                            result = timeAMPM
                        }

                        5 -> {
                            var timeAMPM = date1
                            timeAMPM = timeAMPM.convertDateToDMYFullTimeDate(
                                DateFormats.DEFAULT_FORMAT.format
                            ).toString()
                            result = timeAMPM
                        }
                        6 -> {
                            var timeAMPM = date1
                            timeAMPM = timeAMPM.convertDateToYMD(
                                DateFormats.DEFAULT_FORMAT.format
                            ).toString()
                            result = timeAMPM
                        }
                        7 -> {
                            var timeAMPM = date1
                            timeAMPM = timeAMPM.convertDateToMonthNameYear(
                                DateFormats.DEFAULT_FORMAT.format
                            ).toString()
                            result = timeAMPM
                        }
                        8 -> {
                            var timeAMPM = date1
                            timeAMPM = timeAMPM.convertDateToWeekNameYear(
                                DateFormats.DEFAULT_FORMAT.format
                            ).toString()
                            result = timeAMPM
                        }
                        9 -> {
                            var timeAMPM = date1
                            timeAMPM = timeAMPM.convertDateMonthName(
                                DateFormats.DEFAULT_FORMAT.format
                            ).toString()
                            result = timeAMPM
                        }
                        10 -> {
                            var timeAMPM = date1
                            timeAMPM = timeAMPM.convertDateCustom(
                                DateFormats.DEFAULT_FORMAT.format
                            ).toString()
                            result = timeAMPM
                        }
                        11 -> {
                            var timeAMPM = date1
                            timeAMPM = timeAMPM.convertDateToAmPm(
                                DateFormats.DEFAULT_FORMAT.format
                            ).toString()
                            result = timeAMPM
                        }
                    }
                    text1.text = result
                    Toast.makeText(this@DateTimeActivity, "변환 결과 : $result", Toast.LENGTH_SHORT).show()
                }

                override fun onNothingSelected(parentView: AdapterView<*>?) {}

            }
        }
    }
}

 

대충 스피너에서 뭐 선택했냐에 따라서 date1 프로퍼티에 담긴 날짜를 바꾸고 변환 결과를 토스트로 띄운다.

앱이 실행되자마자 변환 결과가 없는 토스트가 표시되지만 값이 잘 변경되는지 확인하기 위해 내가 임의로 넣은 토스트기 때문에 무시해도 된다.

실행하면 아래와 같이 실행된다.

 

 

프로퍼티에 담겨있던 시간 형태는 "2022-11-10T10:10:00"인데 스피너를 눌러 선택한 아이템에 따라 변환된 결과가 텍스트뷰와 토스트에 표시되는 걸 볼 수 있다.

이걸 응용하면 서버에서 UTC 시간을 넘겨줄 때 내가 원하는 시간으로 바꿔서 표시할 수 있을 것이다.

반응형
Comments