From 9adc45095b60b7f19c18b1baeaf6fb04b97fae4b Mon Sep 17 00:00:00 2001 From: klaus Date: Fri, 19 Dec 2025 14:21:26 +0900 Subject: [PATCH] =?UTF-8?q?=EC=BB=A4=EB=AE=A4=EB=8B=88=ED=8B=B0=20?= =?UTF-8?q?=EA=B2=8C=EC=8B=9C=EA=B8=80=20=EC=83=81=EB=8C=80=20=EC=8B=9C?= =?UTF-8?q?=EA=B0=84=20=ED=91=9C=EA=B8=B0=20=EB=8B=A4=EA=B5=AD=EC=96=B4=20?= =?UTF-8?q?=EC=A7=80=EC=9B=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../explorer/profile/UserProfileActivity.kt | 3 +- .../CreatorCommunityAdapter.kt | 3 +- .../GetCommunityPostListResponse.kt | 106 ++++++++++++++++++ .../all/CreatorCommunityAllAdapter.kt | 3 +- app/src/main/res/values-en/strings.xml | 1 + app/src/main/res/values-ja/strings.xml | 1 + app/src/main/res/values/strings.xml | 1 + 7 files changed, 115 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/kr/co/vividnext/sodalive/explorer/profile/UserProfileActivity.kt b/app/src/main/java/kr/co/vividnext/sodalive/explorer/profile/UserProfileActivity.kt index 19f3384d..26d3446d 100644 --- a/app/src/main/java/kr/co/vividnext/sodalive/explorer/profile/UserProfileActivity.kt +++ b/app/src/main/java/kr/co/vividnext/sodalive/explorer/profile/UserProfileActivity.kt @@ -49,6 +49,7 @@ import kr.co.vividnext.sodalive.dialog.MemberProfileDialog import kr.co.vividnext.sodalive.explorer.profile.cheers.UserProfileCheersAdapter import kr.co.vividnext.sodalive.explorer.profile.creator_community.GetCommunityPostListResponse import kr.co.vividnext.sodalive.explorer.profile.creator_community.all.CreatorCommunityAllActivity +import kr.co.vividnext.sodalive.explorer.profile.creator_community.relativeTimeText import kr.co.vividnext.sodalive.explorer.profile.creator_community.write.CreatorCommunityWriteActivity import kr.co.vividnext.sodalive.explorer.profile.donation.UserProfileDonationAdapter import kr.co.vividnext.sodalive.explorer.profile.donation.UserProfileDonationAllViewActivity @@ -965,7 +966,7 @@ class UserProfileActivity : BaseActivity( transformations(CircleCropTransformation()) } layout.tvCreatorNickname.text = item.creatorNickname - layout.tvDate.text = item.date + layout.tvDate.text = item.relativeTimeText(this) layout.tvContent.text = item.content layout.ivPostImage.loadUrl(item.imageUrl) { diff --git a/app/src/main/java/kr/co/vividnext/sodalive/explorer/profile/creator_community/CreatorCommunityAdapter.kt b/app/src/main/java/kr/co/vividnext/sodalive/explorer/profile/creator_community/CreatorCommunityAdapter.kt index 2377faed..6833c503 100644 --- a/app/src/main/java/kr/co/vividnext/sodalive/explorer/profile/creator_community/CreatorCommunityAdapter.kt +++ b/app/src/main/java/kr/co/vividnext/sodalive/explorer/profile/creator_community/CreatorCommunityAdapter.kt @@ -12,6 +12,7 @@ import kr.co.vividnext.sodalive.R import kr.co.vividnext.sodalive.databinding.ItemCreatorCommunityBinding import kr.co.vividnext.sodalive.extensions.dpToPx import kr.co.vividnext.sodalive.extensions.loadUrl +import kr.co.vividnext.sodalive.explorer.profile.creator_community.relativeTimeText class CreatorCommunityAdapter( private val width: Int, @@ -31,7 +32,7 @@ class CreatorCommunityAdapter( transformations(CircleCropTransformation()) } binding.tvCreatorNickname.text = item.creatorNickname - binding.tvDate.text = item.date + binding.tvDate.text = item.relativeTimeText(context) binding.tvContent.text = item.content binding.ivPostImage.loadUrl(item.imageUrl) { diff --git a/app/src/main/java/kr/co/vividnext/sodalive/explorer/profile/creator_community/GetCommunityPostListResponse.kt b/app/src/main/java/kr/co/vividnext/sodalive/explorer/profile/creator_community/GetCommunityPostListResponse.kt index c18e6587..d969594d 100644 --- a/app/src/main/java/kr/co/vividnext/sodalive/explorer/profile/creator_community/GetCommunityPostListResponse.kt +++ b/app/src/main/java/kr/co/vividnext/sodalive/explorer/profile/creator_community/GetCommunityPostListResponse.kt @@ -2,6 +2,14 @@ package kr.co.vividnext.sodalive.explorer.profile.creator_community import androidx.annotation.Keep import com.google.gson.annotations.SerializedName +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 @Keep data class GetCommunityPostListResponse( @@ -14,6 +22,7 @@ data class GetCommunityPostListResponse( @SerializedName("content") val content: String, @SerializedName("price") val price: Int, @SerializedName("date") val date: String, + @SerializedName("dateUtc") val dateUtc: String, @SerializedName("isCommentAvailable") val isCommentAvailable: Boolean, @SerializedName("isAdult") val isAdult: Boolean, @SerializedName("isLike") var isLike: Boolean, @@ -23,3 +32,100 @@ data class GetCommunityPostListResponse( @SerializedName("firstComment") val firstComment: GetCommunityPostCommentListItem?, @SerializedName("isExpand") var isExpand: Boolean = false ) + +/** + * dateUtc 를 디바이스 로컬 타임존 기준의 상대 시간 문자열로 변환한다. + * 규칙: + * - 1분 미만: 방금 전 + * - 1시간 미만: OO분 전 + * - 1일 미만: OO시간 전 + * - 1개월 미만: OO일 전 + * - 1년 미만: OO개월 전 + * - 그 외: OO년 전 + * 기존 다국어 문자열 리소스(character_comment_time_*)를 사용한다. + */ +fun GetCommunityPostListResponse.relativeTimeText(context: Context): String { + val pastMillis = parseServerUtcToMillis(dateUtc) + ?: 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 tz = TimeZone.getDefault() + val calNow = Calendar.getInstance(tz, Locale.getDefault()) + val calPast = Calendar.getInstance(tz, Locale.getDefault()) + calPast.timeInMillis = pastMillis + + // 연도 계산 (아직 기념일 전이면 1년 빼기) + var years = calNow.get(Calendar.YEAR) - calPast.get(Calendar.YEAR) + val nowMonth = calNow.get(Calendar.MONTH) + val pastMonth = calPast.get(Calendar.MONTH) + val nowDay = calNow.get(Calendar.DAY_OF_MONTH) + val pastDay = calPast.get(Calendar.DAY_OF_MONTH) + if (nowMonth < pastMonth || (nowMonth == pastMonth && nowDay < pastDay)) { + years -= 1 + } + + if (years < 1) { + var months = (calNow.get(Calendar.YEAR) - calPast.get(Calendar.YEAR)) * 12 + (nowMonth - pastMonth) + if (nowDay < pastDay) months -= 1 + if (months < 1) months = 1 // 최소 1개월 + return context.getString(R.string.character_comment_time_months, months) + } + + return context.getString(R.string.character_comment_time_years, years) +} + +// 서버에서 내려오는 dateUtc 문자열을 UTC 기준 millis 로 파싱한다. +private fun parseServerUtcToMillis(dateUtc: String?): Long? { + if (dateUtc.isNullOrBlank()) return null + + val s = dateUtc.trim() + // epoch millis 가능성 + if (s.all { it.isDigit() }) { + return try { s.toLong() } catch (_: NumberFormatException) { null } + } + + // 자주 쓰이는 포맷들 (UTC 가정) + val patterns = listOf( + "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", + "yyyy-MM-dd'T'HH:mm:ss'Z'", + "yyyy-MM-dd HH:mm:ss", + "yyyy/MM/dd HH:mm:ss" + ) + for (p in patterns) { + try { + val sdf = SimpleDateFormat(p, Locale.US) + sdf.timeZone = TimeZone.getTimeZone("UTC") + val date: Date? = sdf.parse(s) + if (date != null) return date.time + } catch (_: ParseException) { } + } + + return null +} diff --git a/app/src/main/java/kr/co/vividnext/sodalive/explorer/profile/creator_community/all/CreatorCommunityAllAdapter.kt b/app/src/main/java/kr/co/vividnext/sodalive/explorer/profile/creator_community/all/CreatorCommunityAllAdapter.kt index a29bd3c5..ef1dc957 100644 --- a/app/src/main/java/kr/co/vividnext/sodalive/explorer/profile/creator_community/all/CreatorCommunityAllAdapter.kt +++ b/app/src/main/java/kr/co/vividnext/sodalive/explorer/profile/creator_community/all/CreatorCommunityAllAdapter.kt @@ -27,6 +27,7 @@ import kr.co.vividnext.sodalive.databinding.ItemCreatorCommunityAllBinding import kr.co.vividnext.sodalive.explorer.profile.creator_community.GetCommunityPostCommentListItem import kr.co.vividnext.sodalive.explorer.profile.creator_community.GetCommunityPostListResponse import kr.co.vividnext.sodalive.explorer.profile.creator_community.all.player.CreatorCommunityContentItem +import kr.co.vividnext.sodalive.explorer.profile.creator_community.relativeTimeText import kr.co.vividnext.sodalive.extensions.dpToPx import kr.co.vividnext.sodalive.extensions.loadUrl import java.util.regex.Pattern @@ -53,7 +54,7 @@ class CreatorCommunityAllAdapter( ) : RecyclerView.ViewHolder(binding.root) { @SuppressLint("NotifyDataSetChanged", "SetTextI18n") fun bind(item: GetCommunityPostListResponse, index: Int) { - binding.tvDate.text = item.date + binding.tvDate.text = item.relativeTimeText(context) binding.tvNickname.text = item.creatorNickname binding.ivCreatorProfile.loadUrl(item.creatorProfileUrl) { crossfade(true) diff --git a/app/src/main/res/values-en/strings.xml b/app/src/main/res/values-en/strings.xml index 83f33707..9cea4e50 100644 --- a/app/src/main/res/values-en/strings.xml +++ b/app/src/main/res/values-en/strings.xml @@ -267,6 +267,7 @@ %1$d min ago %1$d hr ago %1$d day ago + %1$d mo ago %1$d yr ago Please enter a message. Please enter a report reason. diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml index dbcf9ca5..39107627 100644 --- a/app/src/main/res/values-ja/strings.xml +++ b/app/src/main/res/values-ja/strings.xml @@ -267,6 +267,7 @@ %1$d分前 %1$d時間前 %1$d日前 + %1$dか月前 %1$d年前 内容を入力してください。 通報理由を入力してください。 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 470742ec..bae20e92 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -266,6 +266,7 @@ %1$d분전 %1$d시간전 %1$d일전 + %1$d개월전 %1$d년전 내용을 입력하세요 신고 사유를 입력하세요