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

[CAT-299] 집중 시간 60분 선택시 0분으로 나오는 버그 #54

Merged
merged 3 commits into from
Aug 23, 2024
Merged
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
Expand Up @@ -64,24 +64,24 @@ public struct PomodoroCategory: Persistable, Equatable, Identifiable, Codable {
}

extension PomodoroCategory {
public var focusTimeMinute: Int {
public var focusTimeMinutes: Int {
let dateComponents = DateComponents.durationFrom8601String(focusTime)
return dateComponents?.minute ?? 0
return dateComponents?.totalMinutes ?? 0
}

public var restTimeMinute: Int {
public var restTimeMinutes: Int {
let dateComponents = DateComponents.durationFrom8601String(restTime)
return dateComponents?.minute ?? 0
return dateComponents?.totalMinutes ?? 0
}

public var focusTimeSeconds: Int {
let dateComponents = DateComponents.durationFrom8601String(focusTime)
return (dateComponents?.minute ?? 0) * 60
return dateComponents?.totalSeconds ?? 0
}

public var restTimeSeconds: Int {
let dateComponents = DateComponents.durationFrom8601String(restTime)
return (dateComponents?.minute ?? 0) * 60
return dateComponents?.totalSeconds ?? 0
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ public struct CategorySelectView: View {
ForEach(store.categoryList) { category in
Button(
title: .init(category.title),
subtitle: "집중 \(category.focusTimeMinute)분 | 휴식 \(category.restTimeMinute)분",
subtitle: "집중 \(category.focusTimeMinutes)분 | 휴식 \(category.restTimeMinutes)분",
leftIcon: category.image
) {
store.send(.selectCategory(category))
Expand Down
4 changes: 2 additions & 2 deletions Projects/Feature/HomeFeature/Sources/Home/HomeCore.swift
Original file line number Diff line number Diff line change
Expand Up @@ -296,8 +296,8 @@ public struct HomeCore {
let restedTime = DateComponents(minute: restTimeBySeconds / 60, second: restTimeBySeconds % 60).to8601DurationString()
let request = FocusTimeHistory(
categoryNo: selectedCategoryID,
focusedTime: focusedTime,
restedTime: restedTime,
focusedTime: focusedTime ?? "PT0M",
restedTime: restedTime ?? "PT0M",
doneAt: Date()
)
try await self.pomodoroService.saveFocusTimeHistory(
Expand Down
4 changes: 2 additions & 2 deletions Projects/Feature/HomeFeature/Sources/Home/HomeView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ public struct HomeView: View {
Text("집중")
.font(Typography.bodySB)
.foregroundStyle(Global.Color.gray500)
Text("\(store.selectedCategory?.focusTimeMinute ?? 0)분")
Text("\(store.selectedCategory?.focusTimeMinutes ?? 0)분")
.font(Typography.header3)
.foregroundStyle(Alias.Color.Text.secondary)
}
Expand All @@ -81,7 +81,7 @@ public struct HomeView: View {
Text("휴식")
.font(Typography.bodySB)
.foregroundStyle(Global.Color.gray500)
Text("\(store.selectedCategory?.restTimeMinute ?? 0)분")
Text("\(store.selectedCategory?.restTimeMinutes ?? 0)분")
.font(Typography.header3)
.foregroundStyle(Alias.Color.Text.secondary)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,9 +83,9 @@ public struct TimeSelectCore {
if let category {
switch state.mode {
case .focus:
state.selectedTime = TimeItem(minute: category.focusTimeMinute)
state.selectedTime = TimeItem(minute: category.focusTimeMinutes)
case .rest:
state.selectedTime = TimeItem(minute: category.restTimeMinute)
state.selectedTime = TimeItem(minute: category.restTimeMinutes)
}
} else {
state.selectedTime = state.timeList.last
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ public struct FocusPomodoroCore {

case .setupFocusTime:
guard let selectedCategory = state.selectedCategory else { return .none }
state.focusTimeBySeconds = selectedCategory.focusTimeMinute * 60
state.focusTimeBySeconds = selectedCategory.focusTimeSeconds
return .none

case .catSetInput:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,11 +52,11 @@ public struct RestPomodoroCore {
)
}
var minus5MinuteButtonDisabled: Bool {
guard let restTimeMinute = selectedCategory?.restTimeMinute else { return false }
guard let restTimeMinute = selectedCategory?.restTimeMinutes else { return false }
return restTimeMinute <= 5
}
var plus5MinuteButtonDisabled: Bool {
guard let restTimeMinute = selectedCategory?.restTimeMinute else { return false }
guard let restTimeMinute = selectedCategory?.restTimeMinutes else { return false }
return restTimeMinute >= 30
}
}
Expand Down Expand Up @@ -163,7 +163,7 @@ public struct RestPomodoroCore {

case .setupRestTime:
guard let selectedCategory = state.selectedCategory else { return .none }
state.restTimeBySeconds = selectedCategory.restTimeMinute * 60
state.restTimeBySeconds = selectedCategory.restTimeSeconds
return .none

case .catTapped:
Expand Down Expand Up @@ -235,7 +235,7 @@ public struct RestPomodoroCore {
state.changeRestTimeByMinute != 0
else { return }

let changedTimeMinute = selectedCategory.restTimeMinute + state.changeRestTimeByMinute
let changedTimeMinute = selectedCategory.restTimeMinutes + state.changeRestTimeByMinute
let iso8601Duration = DateComponents(minute: changedTimeMinute).to8601DurationString()
let request = EditCategoryRequest(focusTime: nil, restTime: iso8601Duration)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,12 @@ public struct RestWaitingCore {
}

var minus5MinuteButtonDisabled: Bool {
guard let focusTimeMinute = selectedCategory?.focusTimeMinute else { return false }
return focusTimeMinute <= 10
guard let focusTimeMinutes = selectedCategory?.focusTimeMinutes else { return false }
return focusTimeMinutes <= 10
}
var plus5MinuteButtonDisabled: Bool {
guard let focusTimeMinute = selectedCategory?.focusTimeMinute else { return false }
return focusTimeMinute >= 60
guard let focusTimeMinutes = selectedCategory?.focusTimeMinutes else { return false }
return focusTimeMinutes >= 60
}
}

Expand Down Expand Up @@ -170,7 +170,7 @@ public struct RestWaitingCore {
state.changeFocusTimeByMinute != 0
else { return }

let changedTimeMinute = selectedCategory.focusTimeMinute + state.changeFocusTimeByMinute
let changedTimeMinute = selectedCategory.focusTimeMinutes + state.changeFocusTimeByMinute
let iso8601Duration = DateComponents(minute: changedTimeMinute).to8601DurationString()
let request = EditCategoryRequest(focusTime: iso8601Duration, restTime: nil)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,153 +8,62 @@

import Foundation

/*
* https://github.com/leonx98/Swift-ISO8601-DurationParser
* This extension converts ISO 8601 duration strings with the format: P[n]Y[n]M[n]DT[n]H[n]M[n]S or P[n]W into date components
* Examples:
* PT12H = 12 hours
* P3D = 3 days
* P3DT12H = 3 days, 12 hours
* P3Y6M4DT12H30M5S = 3 years, 6 months, 4 days, 12 hours, 30 minutes and 5 seconds
* P10W = 70 days
* For more information look here: http://en.wikipedia.org/wiki/ISO_8601#Durations
*/

public extension DateComponents {
static func durationFrom8601String(_ durationString: String) -> DateComponents? {
try? Self.from8601String(durationString)
extension DateComponents {
public var totalSeconds: Int {
let secondsFromMinutes = (self.minute ?? 0) * 60
let secondsFromHours = (self.hour ?? 0) * 3600
let secondsFromDays = (self.day ?? 0) * 86400
let secondsFromWeeks = (self.weekOfYear ?? 0) * 604800
let secondsFromMonths = (self.month ?? 0) * 2629800 // 평균 월 길이 (30.44일)
let secondsFromYears = (self.year ?? 0) * 31557600 // 평균 년 길이 (365.25일)
return (self.second ?? 0) + secondsFromMinutes + secondsFromHours + secondsFromDays + secondsFromWeeks + secondsFromMonths + secondsFromYears
}

// Note: Does not handle fractional values for months
// Format: PnYnMnDTnHnMnS or PnW
static func from8601String(_ durationString: String) throws -> DateComponents {
guard durationString.starts(with: "P") else {
throw DurationParsingError.invalidFormat(durationString)
}

let durationString = String(durationString.dropFirst())
var dateComponents = DateComponents()

if let week = componentFor("W", in: durationString) {
// 7 day week specified in ISO 8601 standard
dateComponents.day = Int(week * 7.0)
return dateComponents
}

let tRange = (durationString as NSString).range(of: "T", options: .literal)
let periodString: String
let timeString: String
if tRange.location == NSNotFound {
periodString = durationString
timeString = ""
} else {
periodString = (durationString as NSString).substring(to: tRange.location)
timeString = (durationString as NSString).substring(from: tRange.location + 1)
}

// DnMnYn
let year = componentFor("Y", in: periodString)
let month = componentFor("M", in: periodString).addingFractionsFrom(year, multiplier: 12)
let day = componentFor("D", in: periodString)

if let monthFraction = month?.truncatingRemainder(dividingBy: 1),
monthFraction != 0 {
// Representing fractional months isn't supported by DateComponents, so we don't allow it here
throw DurationParsingError.unsupportedFractionsForMonth(durationString)
}

dateComponents.year = year?.nonFractionParts
dateComponents.month = month?.nonFractionParts
dateComponents.day = day?.nonFractionParts

// SnMnHn
let hour = componentFor("H", in: timeString).addingFractionsFrom(day, multiplier: 24)
let minute = componentFor("M", in: timeString).addingFractionsFrom(hour, multiplier: 60)
let second = componentFor("S", in: timeString).addingFractionsFrom(minute, multiplier: 60)
dateComponents.hour = hour?.nonFractionParts
dateComponents.minute = minute?.nonFractionParts
dateComponents.second = second.map { Int($0.rounded()) }

return dateComponents
public var totalMinutes: Int {
let minutesFromSeconds = (self.second ?? 0) / 60
let minutesFromHours = (self.hour ?? 0) * 60
let minutesFromDays = (self.day ?? 0) * 1440
let minutesFromWeeks = (self.weekOfYear ?? 0) * 10080
let minutesFromMonths = (self.month ?? 0) * 43830 // 평균 월 길이 (30.44일)
let minutesFromYears = (self.year ?? 0) * 525960 // 평균 년 길이 (365.25일)
return (self.minute ?? 0) + minutesFromSeconds + minutesFromHours + minutesFromDays + minutesFromWeeks + minutesFromMonths + minutesFromYears
}

private static func componentFor(_ designator: String, in string: String) -> Double? {
// First split by the designator we're interested in, and then split by all separators. This should give us whatever's before our designator, but after the previous one.
let beforeDesignator = string.components(separatedBy: designator).first?.components(separatedBy: .separators).last
return beforeDesignator.flatMap { Double($0) }
public var totalHours: Int {
let hoursFromMinutes = (self.minute ?? 0) / 60
let hoursFromDays = (self.day ?? 0) * 24
let hoursFromWeeks = (self.weekOfYear ?? 0) * 168
let hoursFromMonths = (self.month ?? 0) * 730 // 평균 월 길이 (30.44일)
let hoursFromYears = (self.year ?? 0) * 8766 // 평균 년 길이 (365.25일)
return (self.hour ?? 0) + hoursFromMinutes + hoursFromDays + hoursFromWeeks + hoursFromMonths + hoursFromYears
}

enum DurationParsingError: Error {
case invalidFormat(String)
case unsupportedFractionsForMonth(String)
}
}

private extension Optional where Wrapped == Double {
func addingFractionsFrom(_ other: Double?, multiplier: Double) -> Self {
guard let other = other else { return self }
let toAdd = other.truncatingRemainder(dividingBy: 1) * multiplier
guard let self = self else { return toAdd }
return self + toAdd
public var totalDays: Int {
let daysFromHours = (self.hour ?? 0) / 24
let daysFromWeeks = (self.weekOfYear ?? 0) * 7
let daysFromMonths = (self.month ?? 0) * 30 // 평균 월 길이 (30일)
let daysFromYears = (self.year ?? 0) * 365 // 평균 년 길이 (365일)
return (self.day ?? 0) + daysFromHours + daysFromWeeks + daysFromMonths + daysFromYears
}
}

private extension Double {
var nonFractionParts: Int {
Int(floor(self))

public var totalWeeks: Int {
let weeksFromDays = (self.day ?? 0) / 7
let weeksFromMonths = (self.month ?? 0) * 4 // 평균 월 길이 (4주)
let weeksFromYears = (self.year ?? 0) * 52 // 평균 년 길이 (52주)
return (self.weekOfYear ?? 0) + weeksFromDays + weeksFromMonths + weeksFromYears
}
}

private extension CharacterSet {
static let separators = CharacterSet(charactersIn: "PWTYMDHMS")
}

extension DateComponents.DurationParsingError: LocalizedError {
public var errorDescription: String? {
switch self {
case .invalidFormat(let durationString):
return "\(durationString) has an invalid format, The durationString must have a format of PnYnMnDTnHnMnS or PnW"
case .unsupportedFractionsForMonth(let durationString):
return "\(durationString) has an invalid format, fractions aren't supported for the month-position"
}

public var totalMonths: Int {
let monthsFromDays = (self.day ?? 0) / 30 // 평균 일 길이 (30일)
let monthsFromWeeks = (self.weekOfYear ?? 0) / 4 // 평균 주 길이 (4주)
let monthsFromYears = (self.year ?? 0) * 12
return (self.month ?? 0) + monthsFromDays + monthsFromWeeks + monthsFromYears
}
}

extension DateComponents {
public func to8601DurationString() -> String {
var components = "P"

if let year = year {
components += "\(year)Y"
}
if let month = month {
components += "\(month)M"
}
if let day = day {
components += "\(day)D"
}

var timeComponents = ""

if let hour = hour {
timeComponents += "\(hour)H"
}
if let minute = minute {
timeComponents += "\(minute)M"
}
if let second = second {
timeComponents += "\(second)S"
}

if !timeComponents.isEmpty {
components += "T" + timeComponents
}

// ISO 8601 duration strings with only time components must start with 'PT'
if components == "P" && !timeComponents.isEmpty {
components = "PT" + timeComponents
}

return components

public var totalYears: Int {
let yearsFromDays = (self.day ?? 0) / 365 // 평균 일 길이 (365일)
let yearsFromWeeks = (self.weekOfYear ?? 0) / 52 // 평균 주 길이 (52주)
let yearsFromMonths = (self.month ?? 0) / 12
return (self.year ?? 0) + yearsFromDays + yearsFromWeeks + yearsFromMonths
}
}
Loading
Loading