커뮤니티 게시글 상대 시간 표기 다국어 지원

This commit is contained in:
Yu Sung
2025-12-19 14:20:47 +09:00
parent f51fe327e9
commit bea50b0085
5 changed files with 147 additions and 2 deletions

View File

@@ -58,7 +58,7 @@ struct CreatorCommunityAllItemView: View {
.font(.custom(Font.medium.rawValue, size: 13.3))
.foregroundColor(Color.grayee)
Text(item.date)
Text(item.relativeTimeText())
.font(.custom(Font.light.rawValue, size: 13.3))
.foregroundColor(Color.gray77)
}
@@ -175,6 +175,7 @@ struct CreatorCommunityAllItemView_Previews: PreviewProvider {
content: "너무 조하유 앞으로도 좋은 라이브 많이 들려주세요!너무 조하유 앞으로도 좋은 라이브 많이 들려주세요!너무 조하유 앞으로도 좋은 라이브 많이 들려주세요!너무 조하유 앞으로도 좋은 라이브 많이 들려주세요!너무 조하유 앞으로도 좋은 라이브 많이 들려주세요!너무 조하유 앞으로도 좋은 라이브 많이 들려주세요!너무 조하유 앞으로도 좋은 라이브 많이 들려주세요!너무 조하유 앞으로도 좋은 라이브 많이 들려주세요!너무 조하유 앞으로도 좋은 라이브 많이 들려주세요!너무 조하유 앞으로도 좋은 라이브 많이 들려주세요!너무 조하유 앞으로도 좋은 라이브 많이 들려주세요!너무 조하유 앞으로도 좋은 라이브 많이 들려주세요!",
price: 10,
date: "3일전",
dateUtc: "2025-08-10T15:00:00",
isCommentAvailable: false,
isAdult: false,
isLike: true,

View File

@@ -26,7 +26,7 @@ struct CreatorCommunityItemView: View {
.font(.custom(Font.preBold.rawValue, size: 18))
.foregroundColor(Color.white)
Text(item.date)
Text(item.relativeTimeText())
.font(.custom(Font.preRegular.rawValue, size: 14))
.foregroundColor(Color(hex: "78909C"))
}
@@ -100,6 +100,7 @@ struct CreatorCommunityItemView_Previews: PreviewProvider {
content: "안녕하세요",
price: 10,
date: "3일전",
dateUtc: "2025-08-10T15:00:00",
isCommentAvailable: false,
isAdult: false,
isLike: false,

View File

@@ -5,6 +5,8 @@
// Created by klaus on 2023/12/19.
//
import Foundation
struct GetCommunityPostListResponse: Decodable {
let postId: Int
let creatorId: Int
@@ -15,6 +17,7 @@ struct GetCommunityPostListResponse: Decodable {
let content: String
let price: Int
let date: String
let dateUtc: String
let isCommentAvailable: Bool
let isAdult: Bool
let isLike: Bool
@@ -23,3 +26,96 @@ struct GetCommunityPostListResponse: Decodable {
let commentCount: Int
let firstComment: GetCommunityPostCommentListItem?
}
// MARK: -
extension GetCommunityPostListResponse {
/// `dateUtc`(UTC )
/// ( ///// ) .
/// , `date` .
func relativeTimeText(now: Date = Date()) -> String {
guard let createdAt = DateParser.parse(dateUtc) else {
return date
}
let nowDate = now
let interval = max(0, nowDate.timeIntervalSince(createdAt))
// / (/ )
let calendar = Calendar.current
let ym = calendar.dateComponents([.year, .month],
from: createdAt,
to: nowDate)
if let years = ym.year, years >= 1 {
return I18n.Time.yearsAgo(years)
}
if let months = ym.month, months >= 1 {
return I18n.Time.monthsAgo(months)
}
// //
if interval < 60 {
return I18n.Time.justNow
} else if interval < 3600 {
let minutes = Int(interval / 60)
return I18n.Time.minutesAgo(max(1, minutes))
} else if interval < 86_400 {
let hours = Int(interval / 3600)
return I18n.Time.hoursAgo(max(1, hours))
} else {
let days = Int(interval / 86_400)
return I18n.Time.daysAgo(max(1, days))
}
}
}
// MARK: - :
private enum DateParser {
static func parse(_ text: String) -> Date? {
for parser in parsers {
if let d = parser(text) { return d }
}
return nil
}
// : ISO8601( ) ISO8601 RFC3339
private static let parsers: [(String) -> Date?] = [
{ ISO8601.fractional.date(from: $0) },
{ ISO8601.basic.date(from: $0) },
{ DF.rfc3339.date(from: $0) },
{ DF.basic.date(from: $0) }
]
private enum ISO8601 {
static let fractional: ISO8601DateFormatter = {
let f = ISO8601DateFormatter()
f.formatOptions = [.withInternetDateTime, .withFractionalSeconds]
f.timeZone = TimeZone(secondsFromGMT: 0)
return f
}()
static let basic: ISO8601DateFormatter = {
let f = ISO8601DateFormatter()
f.formatOptions = [.withInternetDateTime]
f.timeZone = TimeZone(secondsFromGMT: 0)
return f
}()
}
private enum DF {
static let rfc3339: DateFormatter = {
let f = DateFormatter()
f.locale = Locale(identifier: "en_US_POSIX")
f.timeZone = TimeZone(secondsFromGMT: 0)
f.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZ"
return f
}()
static let basic: DateFormatter = {
let f = DateFormatter()
f.locale = Locale(identifier: "en_US_POSIX")
f.timeZone = TimeZone(secondsFromGMT: 0)
f.dateFormat = "yyyy-MM-dd HH:mm:ss"
return f
}()
}
}