【问题标题】:countdown from current date to specific date swift从当前日期倒计时到特定日期swift
【发布时间】:2017-08-24 07:48:51
【问题描述】:

用户可以出售商品并添加从当前日期起 1-3 周不等的到期日期。

这就是我将到期日期存储为Double 的方式。我是否需要明确其他日期组件,例如年、月等?

enum Weeks: Int  {
    case one
    case two
    case three
}

extension Weeks {
    var timeInterval: Double? {
        let currentDate = Date()
        let calendar = Calendar.current
        let calendarComponents: Set<Calendar.Component> = Set(arrayLiteral: Calendar.Component.year, Calendar.Component.month, Calendar.Component.day, Calendar.Component.hour, Calendar.Component.minute, Calendar.Component.second)

        var components = calendar.dateComponents(calendarComponents, from: currentDate)

        switch self {
        case .one: components.weekOfMonth = 1
        case .two: components.weekOfMonth = 2
        case .three: components.weekOfMonth = 3
        }

        if let expirationDate = calendar.date(from: components) {
            return expirationDate.timeIntervalSince1970 as Double
        } else {
            return nil
        }
    }
}

这是我在Date 扩展中计算倒计时的方式:

func countdown(to date: Date) -> CountdownResponse {
    let difference = Calendar.current.dateComponents([.day, .hour, .minute, .second], from: self, to: date)

    guard let day = difference.day, let hour = difference.hour, let minute = difference.minute, let second = difference.second else {
        return .error(message: "One or more date components are nil.")
    }

    if day <= 0 && hour <= 0 && minute <= 0 && second <= 0 {
        return .isFinished
    }

    let days = displayableText(from: difference.day)
    let hours = displayableText(from: difference.hour)
    let minutes = displayableText(from: difference.minute)
    let seconds = displayableText(from: difference.second)

    let timeRemaining = "\(days) : \(hours) : \(minutes) : \(seconds)"

    return .result(time: timeRemaining)
}

这就是我想要倒计时的方式,然后我检查响应枚举是否有错误或结果。但这给了我错误的时间。

let expirationDate = Date(timeIntervalSince1970: self.item.expirationDate)

let response = currentDate.countdown(to: expirationDate)

当我手动创建日期并进行如下测试时,它按预期工作。

var comp = calendar.dateComponents(calendarComponents, from: Date())

comp.year = 2017
comp.month = 8
comp.day = 24
comp.minute = 50
comp.second = 30

我做错了什么?我是否错误地将日期保留为时间间隔,或者错误地从 timeInterval 创建日期?

当我查看代码时,我意识到我可能计算错误的星期。如果是每月的第二周,并且用户选择项目在 3 周内到期,则每月的周数不应该是 3,它需要是从当月的当前周开始的 3 周。任何有关如何解决此逻辑的指导表示赞赏。

【问题讨论】:

标签: ios swift date countdown


【解决方案1】:

为什么你的代码这么复杂? Foundation 框架提供您所需的一切,从日历计算(加减日期)到输出格式(x 天、y 小时、z 分钟等)。

以下是如何缩短它的示例:

enum Week: Int {
    case one = 7, two = 14, three = 21
}

enum CountdownResponse {
    case isFinished
    case result(time: String)
}

struct ProductListing {
    // Customize this if you want to change timeRemaining's format
    // It automatically take care of singular vs. plural, i.e. 1 hr and 2 hrs
    private static let dateComponentFormatter: DateComponentsFormatter = {
        var formatter = DateComponentsFormatter()
        formatter.allowedUnits = [.day, .hour, .minute, .second]
        formatter.unitsStyle = .short
        return formatter
    }()

    var listingDate: Date
    var duration: Week
    var expirationDate: Date {
        return Calendar.current.date(byAdding: .day, value: duration.rawValue, to: listingDate)!
    }

    var timeRemaining: CountdownResponse {
        let now = Date()

        if expirationDate <= now {
            return .isFinished
        } else {
            let timeRemaining = ProductListing.dateComponentFormatter.string(from: now, to: expirationDate)!
            return .result(time: timeRemaining)
        }
    }
}

// Usage
let august01 = DateComponents(calendar: .current, year: 2017, month: 8, day: 1).date!
let august19 = DateComponents(calendar: .current, year: 2017, month: 8, day: 19).date!

let listing1 = ProductListing(listingDate: august01, duration: .three)
let listing2 = ProductListing(listingDate: august19, duration: .one)

print(listing1.timeRemaining) // .isFinished
print(listing2.timeRemaining) // .result("2 days, 4 hrs, 9 min, 23 secs")

但请注意,当时间来回移动时,当它跨越时钟更改天时,计算变得非常复杂。我没有用上面的代码测试这些边缘情况。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-06-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-16
    • 1970-01-01
    相关资源
    最近更新 更多