Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: server 시간을 기준으로 날짜 계산하게 변경 #94

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,11 +1,21 @@
package com.withpeace.withpeace.core.data.mapper

import java.time.LocalDateTime
import java.time.ZoneId
import java.time.ZonedDateTime
import java.time.format.DateTimeFormatter
import java.util.Locale

fun String.toLocalDateTime(): LocalDateTime = LocalDateTime.parse(
this,
DateTimeFormatter.ofPattern(SERVER_DATE_FORMAT),
)

fun String.toLocalDateTimeForGmt(): LocalDateTime {
val formatter = DateTimeFormatter.ofPattern("EEE, dd MMM yyyy HH:mm:ss zzz", Locale.ENGLISH)
val zonedDateTime = ZonedDateTime.parse(this, formatter)
val seoulZoneId = ZoneId.of("Asia/Seoul")
return zonedDateTime.withZoneSameInstant(seoulZoneId).toLocalDateTime()
}

private const val SERVER_DATE_FORMAT = "yyyy/MM/dd HH:mm:ss"
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,21 @@ import com.withpeace.withpeace.core.domain.model.post.PostDetail
import com.withpeace.withpeace.core.domain.model.post.PostTitle
import com.withpeace.withpeace.core.domain.model.post.PostUser
import com.withpeace.withpeace.core.network.di.response.post.PostDetailResponse
import java.time.LocalDateTime

fun PostDetailResponse.toDomain() = PostDetail(
user = PostUser(
id = userId,
name = nickname,
profileImageUrl = profileImageUrl,
),
id = postId,
title = PostTitle(title),
content = PostContent(content),
postTopic = type.toDomain(),
imageUrls = postImageUrls,
createDate = Date(createDate.toLocalDateTime()),
)
fun PostDetailResponse.toDomain(serverCurrentDate: String): PostDetail {
val createTime = createDate.toLocalDateTime()
return PostDetail(
user = PostUser(
id = userId,
name = nickname,
profileImageUrl = profileImageUrl,
),
id = postId,
title = PostTitle(title),
content = PostContent(content),
postTopic = type.toDomain(),
imageUrls = postImageUrls,
createDate = Date(createTime),
nowDate = serverCurrentDate.toLocalDateTimeForGmt(),
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,13 @@ import com.withpeace.withpeace.core.domain.model.date.Date
import com.withpeace.withpeace.core.domain.model.post.Post
import com.withpeace.withpeace.core.network.di.response.post.PostResponse

fun PostResponse.toDomain() =
fun PostResponse.toDomain(nowDate: String) =
Post(
postId = postId,
title = title,
content = content,
postTopic = type.toDomain(),
createDate = Date(createDate.toLocalDateTime()),
nowDate = nowDate.toLocalDateTimeForGmt(),
postImageUrl = postImageUrl,
)
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package com.withpeace.withpeace.core.data.paging
import androidx.paging.PagingSource
import androidx.paging.PagingState
import com.skydoves.sandwich.suspendMapSuccess
import com.skydoves.sandwich.suspendOnSuccess
import com.withpeace.withpeace.core.data.mapper.toDomain
import com.withpeace.withpeace.core.data.util.handleApiFailure
import com.withpeace.withpeace.core.domain.model.error.CheonghaError
Expand Down Expand Up @@ -59,8 +60,10 @@ class PostPagingSource(
postService.getPosts(
postTopic = postTopic.name,
pageIndex = pageIndex, pageSize = pageSize,
).suspendMapSuccess {
emit(data.map { it.toDomain() })
).suspendOnSuccess {
val serverCurrentDate = this.headers["Date"].toString()
val response = this.data
emit(response.data.map { it.toDomain(serverCurrentDate) })
}.handleApiFailure {
onErrorWithAuthExpired(it, onError)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import androidx.paging.Pager
import androidx.paging.PagingConfig
import androidx.paging.PagingData
import com.skydoves.sandwich.suspendMapSuccess
import com.skydoves.sandwich.suspendOnSuccess
import com.withpeace.withpeace.core.data.mapper.toDomain
import com.withpeace.withpeace.core.data.paging.PostPagingSource
import com.withpeace.withpeace.core.data.util.convertToFile
Expand Down Expand Up @@ -82,8 +83,10 @@ class DefaultPostRepository @Inject constructor(
onError: suspend (CheonghaError) -> Unit,
): Flow<PostDetail> = flow {
postService.getPost(postId)
.suspendMapSuccess {
emit(data.toDomain())
.suspendOnSuccess {
val serverCurrentDate = this.headers["Date"].toString()
val response = this.data
emit(response.data.toDomain(serverCurrentDate = serverCurrentDate))
}.handleApiFailure {
onErrorWithAuthExpired(it, onError)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ import com.withpeace.withpeace.core.network.di.service.PostService
import io.mockk.coEvery
import io.mockk.mockk
import kotlinx.coroutines.test.runTest
import okhttp3.Headers
import okhttp3.internal.addHeaderLenient
import org.junit.Before
import org.junit.Test
import retrofit2.Response
Expand All @@ -30,29 +32,35 @@ class PostPagingSourceTest {

@Before
fun setup() {
val headers = Headers.Builder()
.add("Date", "Thu, 11 Apr 2024 15:00:00 GMT")
.build()

val response = Response.success(
BaseResponse(
data = List(20) {
PostResponse(
postId = 0,
title = "title",
content = "content",
type = PostTopicResponse.FREEDOM,
postImageUrl = "null",
createDate = "2024/04/12 00:00:00",
)
},
error = null,
),
headers
)
val apiResponse = ApiResponse.Success<BaseResponse<List<PostResponse>>>(response)

coEvery {
postService.getPosts(
postTopic = any(),
pageIndex = any(),
pageSize = any(),
)
} returns ApiResponse.Success<BaseResponse<List<PostResponse>>>(
response = Response.success(
BaseResponse(
data = List(20) {
PostResponse(
postId = 0,
title = "title",
content = "content",
type = PostTopicResponse.FREEDOM,
postImageUrl = null,
createDate = "2024/04/12 00:00:00",
)
},
error = null,
),
),
)
} returns apiResponse
}

@Test
Expand All @@ -65,9 +73,11 @@ class PostPagingSourceTest {
onError = {},
userRepository = userRepository
)

// when
val pager = TestPager(PagingConfig(20), postPagingSource)
val result = pager.refresh() as LoadResult.Page

// then
assertThat(result.data).containsExactlyElementsIn(
List(20) {
Expand All @@ -76,13 +86,17 @@ class PostPagingSourceTest {
title = "title",
content = "content",
postTopic = PostTopic.FREEDOM,
postImageUrl = null,
postImageUrl = "null",
createDate = Date(
LocalDateTime.of(
LocalDate.of(2024, 4, 12),
LocalTime.of(0, 0, 0),
),
),
nowDate = LocalDateTime.of(
LocalDate.of(2024, 4, 12),
LocalTime.of(0, 0, 0),
),
)
},
).inOrder()
Expand Down Expand Up @@ -111,13 +125,17 @@ class PostPagingSourceTest {
title = "title",
content = "content",
postTopic = PostTopic.FREEDOM,
postImageUrl = null,
postImageUrl = "null",
createDate = Date(
LocalDateTime.of(
LocalDate.of(2024, 4, 12),
LocalTime.of(0, 0, 0),
),
),
nowDate = LocalDateTime.of(
LocalDate.of(2024, 4, 12),
LocalTime.of(0, 0, 0),
),
)
},
).inOrder()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import java.time.LocalDateTime
value class Date(
val date: LocalDateTime,
) {
val durationFromNow: DurationFromNow
get() = DurationFromNow.from(date)
fun durationFromNow(now: LocalDateTime): DurationFromNow {
return DurationFromNow.from(now, date)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ sealed class DurationFromNow(
class OverOneYear(duration: Duration) : DurationFromNow(duration)

companion object {
fun from(date: LocalDateTime): DurationFromNow {
val duration = Duration.between(date, LocalDateTime.now())
fun from(now: LocalDateTime,date: LocalDateTime): DurationFromNow {
val duration = Duration.between(date, now)
return when {
duration.isOverOneYear() -> OverOneYear(duration)
duration.isOverWeekDays() -> SevenDayToOneYear(duration)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
package com.withpeace.withpeace.core.domain.model.post

import com.withpeace.withpeace.core.domain.model.date.Date
import java.time.LocalDateTime

data class Post(
val postId: Long,
val title: String,
val content: String,
val postTopic: PostTopic,
val createDate: Date,
val nowDate: LocalDateTime,
val postImageUrl: String?,
)
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package com.withpeace.withpeace.core.domain.model.post

import com.withpeace.withpeace.core.domain.model.date.Date
import java.time.Duration
import java.time.LocalDateTime

data class PostDetail(
val user: PostUser,
Expand All @@ -10,6 +12,7 @@ data class PostDetail(
val postTopic: PostTopic,
val imageUrls: List<String>,
val createDate: Date,
val nowDate: LocalDateTime,
)

data class PostUser(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,72 +8,70 @@ import java.time.LocalDateTime
import java.time.format.DateTimeFormatter

data class DateUiModel(
val date: LocalDateTime,
val durationFromNow: DurationFromNowUiModel,
) {
val duration: Duration
get() = Duration.between(date, LocalDateTime.now())
}
)

sealed class DurationFromNowUiModel {
data object LessThanOneMinute : DurationFromNowUiModel()
data object OneMinuteToOneHour : DurationFromNowUiModel()
data object OneHourToOneDay : DurationFromNowUiModel()
data object OneDayToSevenDay : DurationFromNowUiModel()
data object SevenDayToOneYear : DurationFromNowUiModel()
data object OverOneYear : DurationFromNowUiModel()
sealed interface DurationFromNowUiModel {
data class LessThanOneMinute(val duration: Duration) : DurationFromNowUiModel
data class OneMinuteToOneHour(val duration: Duration) : DurationFromNowUiModel
data class OneHourToOneDay(val duration: Duration) : DurationFromNowUiModel
data class OneDayToSevenDay(val duration: Duration) : DurationFromNowUiModel
data class SevenDayToOneYear(val date: LocalDateTime) : DurationFromNowUiModel
data class OverOneYear(val duration: Duration) : DurationFromNowUiModel
}

fun Date.toUiModel(): DateUiModel = DateUiModel(
date = date,
durationFromNow = when (durationFromNow) {
is DurationFromNow.LessThanOneMinute -> DurationFromNowUiModel.LessThanOneMinute
fun Date.toDurationFromNowUiModel(nowDateTime: LocalDateTime): DateUiModel {
val durationFromNow = durationFromNow(nowDateTime)
return DateUiModel(
durationFromNow = when (durationFromNow) {
is DurationFromNow.LessThanOneMinute -> DurationFromNowUiModel.LessThanOneMinute(durationFromNow.value)

is DurationFromNow.OneDayToSevenDay -> DurationFromNowUiModel.OneDayToSevenDay
is DurationFromNow.OneDayToSevenDay -> DurationFromNowUiModel.OneDayToSevenDay(durationFromNow.value)

is DurationFromNow.OneHourToOneDay -> DurationFromNowUiModel.OneHourToOneDay
is DurationFromNow.OneHourToOneDay -> DurationFromNowUiModel.OneHourToOneDay(durationFromNow.value)

is DurationFromNow.OneMinuteToOneHour -> DurationFromNowUiModel.OneMinuteToOneHour
is DurationFromNow.OneMinuteToOneHour -> DurationFromNowUiModel.OneMinuteToOneHour(durationFromNow.value)

is DurationFromNow.OverOneYear -> DurationFromNowUiModel.OverOneYear
is DurationFromNow.OverOneYear -> DurationFromNowUiModel.OverOneYear(durationFromNow.value)

is DurationFromNow.SevenDayToOneYear -> DurationFromNowUiModel.SevenDayToOneYear
},
)
is DurationFromNow.SevenDayToOneYear -> DurationFromNowUiModel.SevenDayToOneYear(this.date)
},
)
}

fun DateUiModel.toRelativeString(context: Context): String {
return when (durationFromNow) {
is DurationFromNowUiModel.LessThanOneMinute -> {
context.getString(
R.string.second_format,
duration.seconds,
durationFromNow.duration.seconds,
)
}

is DurationFromNowUiModel.OneMinuteToOneHour -> context.getString(
R.string.minute_format,
duration.toMinutes(),
durationFromNow.duration.toMinutes(),
)

is DurationFromNowUiModel.OneHourToOneDay -> context.getString(
R.string.hour_format,
duration.toHours(),
durationFromNow.duration.toHours(),
)

is DurationFromNowUiModel.OneDayToSevenDay -> context.getString(
R.string.day_format,
duration.toDays(),
durationFromNow.duration.toDays(),
)

is DurationFromNowUiModel.SevenDayToOneYear -> date.format(
is DurationFromNowUiModel.SevenDayToOneYear -> durationFromNow.date.format(
DateTimeFormatter.ofPattern(
DATE_FORMAT,
),
)

is DurationFromNowUiModel.OverOneYear -> context.getString(
R.string.years_format,
duration.toDays() / DAYS_FOR_YEAR,
durationFromNow.duration.toDays() / DAYS_FOR_YEAR,
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package com.withpeace.withpeace.core.ui.post

import com.withpeace.withpeace.core.domain.model.post.PostDetail
import com.withpeace.withpeace.core.ui.DateUiModel
import com.withpeace.withpeace.core.ui.toUiModel
import com.withpeace.withpeace.core.ui.toDurationFromNowUiModel

data class PostDetailUiModel(
val postUser: PostUserUiModel,
Expand Down Expand Up @@ -32,6 +32,6 @@ fun PostDetail.toUiModel(currentUserId: Long): PostDetailUiModel = PostDetailUiM
content = content.value,
postTopic = postTopic.toUi(),
imageUrls = imageUrls,
createDate = createDate.toUiModel(),
createDate = DateUiModel(createDate.toDurationFromNowUiModel(nowDate).durationFromNow),
isMyPost = user.id == currentUserId,
)
Loading
Loading