From 7f417c3a3fcc694e715bbe14c180771b488e9b84 Mon Sep 17 00:00:00 2001 From: klaus Date: Fri, 5 Jun 2026 22:01:08 +0900 Subject: [PATCH] =?UTF-8?q?feat(common):=20UTC=20=EC=83=81=EB=8C=80=20?= =?UTF-8?q?=EC=8B=9C=EA=B0=84=20=ED=8F=AC=EB=A7=A4=ED=84=B0=EB=A5=BC=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=ED=95=9C=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../sodalive/common/RelativeTimeFormatter.kt | 98 +++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100644 app/src/main/java/kr/co/vividnext/sodalive/common/RelativeTimeFormatter.kt diff --git a/app/src/main/java/kr/co/vividnext/sodalive/common/RelativeTimeFormatter.kt b/app/src/main/java/kr/co/vividnext/sodalive/common/RelativeTimeFormatter.kt new file mode 100644 index 00000000..fcb88a93 --- /dev/null +++ b/app/src/main/java/kr/co/vividnext/sodalive/common/RelativeTimeFormatter.kt @@ -0,0 +1,98 @@ +package kr.co.vividnext.sodalive.common + +import android.content.Context +import kr.co.vividnext.sodalive.R +import java.text.ParseException +import java.text.SimpleDateFormat +import java.util.Calendar +import java.util.Date +import java.util.Locale +import java.util.TimeZone + +fun formatUtcRelativeTimeText(context: Context, utcText: String?): String { + val pastMillis = parseServerUtcToMillis(utcText) + ?: return context.getString(R.string.character_comment_time_just_now) + + val nowMillis = System.currentTimeMillis() + var diff = nowMillis - pastMillis + if (diff < 0) diff = 0 + + val minute = 60_000L + val hour = 60 * minute + val day = 24 * hour + + if (diff < minute) { + return context.getString(R.string.character_comment_time_just_now) + } + + if (diff < hour) { + val minutes = (diff / minute).toInt() + return context.getString(R.string.character_comment_time_minutes, minutes) + } + + if (diff < day) { + val hours = (diff / hour).toInt() + return context.getString(R.string.character_comment_time_hours, hours) + } + + if (diff < 30 * day) { + val days = (diff / day).toInt() + return context.getString(R.string.character_comment_time_days, days) + } + + val timeZone = TimeZone.getDefault() + val nowCalendar = Calendar.getInstance(timeZone, Locale.getDefault()) + val pastCalendar = Calendar.getInstance(timeZone, Locale.getDefault()) + pastCalendar.timeInMillis = pastMillis + + var years = nowCalendar.get(Calendar.YEAR) - pastCalendar.get(Calendar.YEAR) + val nowMonth = nowCalendar.get(Calendar.MONTH) + val pastMonth = pastCalendar.get(Calendar.MONTH) + val nowDay = nowCalendar.get(Calendar.DAY_OF_MONTH) + val pastDay = pastCalendar.get(Calendar.DAY_OF_MONTH) + if (nowMonth < pastMonth || (nowMonth == pastMonth && nowDay < pastDay)) { + years -= 1 + } + + if (years < 1) { + var months = (nowCalendar.get(Calendar.YEAR) - pastCalendar.get(Calendar.YEAR)) * 12 + (nowMonth - pastMonth) + if (nowDay < pastDay) months -= 1 + if (months < 1) months = 1 + return context.getString(R.string.character_comment_time_months, months) + } + + return context.getString(R.string.character_comment_time_years, years) +} + +private fun parseServerUtcToMillis(utcText: String?): Long? { + if (utcText.isNullOrBlank()) return null + + val value = utcText.trim() + if (value.all { it.isDigit() }) { + return try { + value.toLong() + } catch (_: NumberFormatException) { + null + } + } + + val patterns = listOf( + "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", + "yyyy-MM-dd'T'HH:mm:ss'Z'", + "yyyy-MM-dd'T'HH:mm:ss", + "yyyy-MM-dd HH:mm:ss", + "yyyy/MM/dd HH:mm:ss" + ) + + for (pattern in patterns) { + try { + val dateFormat = SimpleDateFormat(pattern, Locale.US) + dateFormat.timeZone = TimeZone.getTimeZone("UTC") + val parsed: Date? = dateFormat.parse(value) + if (parsed != null) return parsed.time + } catch (_: ParseException) { + } + } + + return null +}