Swift 快捷日期和日期计算

Swift 快捷日期和日期计算,swift,swiftdate,Swift,Swiftdate,我试图计算宠物存活的周数和天数。我用的是SwiftDate。因此,我让用户选择一个生日,并将其与当前日期进行比较 我不想比较时间。。。因此,出生日期和当前日期应该具有相同的时间 我的代码是: let greg = Calendar(identifier: .gregorian) var date1 = birthday // from datepicker var date2 = Date() var components1 = greg.dateComponents([.year, .mont

我试图计算宠物存活的周数和天数。我用的是SwiftDate。因此,我让用户选择一个生日,并将其与当前日期进行比较

我不想比较时间。。。因此,出生日期和当前日期应该具有相同的时间

我的代码是:

let greg = Calendar(identifier: .gregorian)
var date1 = birthday // from datepicker
var date2 = Date()
var components1 = greg.dateComponents([.year, .month, .day, .hour, .minute, .second], from: date1)
var components2 = greg.dateComponents([.year, .month, .day, .hour, .minute, .second], from: date2)
components1.hour = 15
components1.minute = 0
components1.second = 0
components2.hour = 15
components2.minute = 0
components2.second = 0
date1 = greg.date(from: components1)!
date2 = greg.date(from: components2)!

let daysAlive = (date2 - date1).in(.day)
let weeksAlive = Int(weeksAlive! / 7)
let restDays = daysAlive! - (weeksAlive * 7)
let aLive = "Age: \(weeksAlive) wk, \(restDays) d (\(daysAlive!) d)"
输出年龄:28周,3天199天


代码是有效的。。。但是我如何重构它呢?有没有更简单的方法来设置两个给定日期的“相同时间”呢?

如果你不在乎时差,为什么不干脆完全停止计时呢?它将为您提供相同的输出,并且只会避免您输入默认时间值,然后在函数的其余部分忽略它们:

let greg = Calendar(identifier: .gregorian)
var date1 = birthday // from datepicker
var date2 = Date()
var components1 = greg.dateComponents([.year, .month, .day], from: date1)
var components2 = greg.dateComponents([.year, .month, .day], from: date2)
date1 = greg.date(from: components1)!
date2 = greg.date(from: components2)!

let daysAlive = (date2 - date1).in(.day)
let weeksAlive = Int(weeksAlive! / 7)
let restDays = daysAlive! - (weeksAlive * 7)
let aLive = "Age: \(weeksAlive) wk, \(restDays) d (\(daysAlive!) d)"

如果你不在乎时差,为什么不把时间完全放在一边呢?它将为您提供相同的输出,并且只会避免您输入默认时间值,然后在函数的其余部分忽略它们:

let greg = Calendar(identifier: .gregorian)
var date1 = birthday // from datepicker
var date2 = Date()
var components1 = greg.dateComponents([.year, .month, .day], from: date1)
var components2 = greg.dateComponents([.year, .month, .day], from: date2)
date1 = greg.date(from: components1)!
date2 = greg.date(from: components2)!

let daysAlive = (date2 - date1).in(.day)
let weeksAlive = Int(weeksAlive! / 7)
let restDays = daysAlive! - (weeksAlive * 7)
let aLive = "Age: \(weeksAlive) wk, \(restDays) d (\(daysAlive!) d)"

要忽略时间,只需忽略.hour、.minute和.second的组件

这是一个更简单的解决方案,没有任何第三方库。它使用日历方法dateComponents:from:to:计算一次weekOfMonth和day的差值,并计算一次day的差值。不需要额外的数学

let greg = Calendar(identifier: .gregorian)
var date1 = greg.date(from: DateComponents(year: 2017, month: 6, day: 25))!
var date2 = Date()
var components1 = greg.dateComponents([.year, .month, .day], from: date1)
var components2 = greg.dateComponents([.year, .month, .day], from: date2)

let weeksAndDays = greg.dateComponents([.weekOfMonth, .day], from: components1, to: components2)
let justDays = greg.dateComponents([.day], from: components1, to: components2)

let aLive = "Age: \(weeksAndDays.weekOfMonth!) wk, \(weeksAndDays.day!) d (\(justDays.day!) d)"
// "Age: 28 wk, 3 d (199 d)"

要忽略时间,只需忽略.hour、.minute和.second的组件

这是一个更简单的解决方案,没有任何第三方库。它使用日历方法dateComponents:from:to:计算一次weekOfMonth和day的差值,并计算一次day的差值。不需要额外的数学

let greg = Calendar(identifier: .gregorian)
var date1 = greg.date(from: DateComponents(year: 2017, month: 6, day: 25))!
var date2 = Date()
var components1 = greg.dateComponents([.year, .month, .day], from: date1)
var components2 = greg.dateComponents([.year, .month, .day], from: date2)

let weeksAndDays = greg.dateComponents([.weekOfMonth, .day], from: components1, to: components2)
let justDays = greg.dateComponents([.day], from: components1, to: components2)

let aLive = "Age: \(weeksAndDays.weekOfMonth!) wk, \(weeksAndDays.day!) d (\(justDays.day!) d)"
// "Age: 28 wk, 3 d (199 d)"

正如其他人所指出的,您可以从日历中抓取.year、.month、.day。您还可以查看DateComponentsFormter是否可以实现您想要的功能:

let formatter: DateComponentsFormatter = {
    let _formatter = DateComponentsFormatter()
    _formatter.allowedUnits = [.day, .weekOfMonth]
    _formatter.unitsStyle = .full
    return _formatter
}()

@IBAction func didValueChange(_ picker: UIDatePicker) {
    let calendar = Calendar.current

    let birthDate = calendar.date(from: calendar.dateComponents([.year, .month, .day], from: picker.date))!
    let now = calendar.date(from: calendar.dateComponents([.year, .month, .day], from: Date()))!
    label.text = formatter.string(from: birthDate, to: now)
}
虽然DateComponentFormatter在结果方面有点受限,但它是本地化的,因此在美国地区会出现以下情况:

28周,3天

但如果您的应用程序配置为支持其他地区,例如德语,则会导致:

28沃森和3塔吉


正如其他人所指出的,您可以从日历中抓取.year、.month、.day。您还可以查看DateComponentsFormter是否可以实现您想要的功能:

let formatter: DateComponentsFormatter = {
    let _formatter = DateComponentsFormatter()
    _formatter.allowedUnits = [.day, .weekOfMonth]
    _formatter.unitsStyle = .full
    return _formatter
}()

@IBAction func didValueChange(_ picker: UIDatePicker) {
    let calendar = Calendar.current

    let birthDate = calendar.date(from: calendar.dateComponents([.year, .month, .day], from: picker.date))!
    let now = calendar.date(from: calendar.dateComponents([.year, .month, .day], from: Date()))!
    label.text = formatter.string(from: birthDate, to: now)
}
虽然DateComponentFormatter在结果方面有点受限,但它是本地化的,因此在美国地区会出现以下情况:

28周,3天

但如果您的应用程序配置为支持其他地区,例如德语,则会导致:

28沃森和3塔吉


好建议,瓦迪安。但我以后确实需要更多的日期计算,所以我正在尽可能多地利用SwiftDate。我得到以下输出:2017-06-24 22:00:00+0000 2018-01-09 23:00:00+0000[SwiftDate]使用。在中提取没有参考日期的日历特定组件可能会返回错误的值。为什么时间不同?看起来像时区不同?打印以UTC显示日期。您的时区在6月夏令时为UTC+2,1月为UTC+1。2017-06-24 22:00:00+0000的时间点与2017-06-25 00:00:00+0200的时间点相同,瓦迪安,好建议。但我以后确实需要更多的日期计算,所以我正在尽可能多地利用SwiftDate。我得到以下输出:2017-06-24 22:00:00+0000 2018-01-09 23:00:00+0000[SwiftDate]使用。在中提取没有参考日期的日历特定组件可能会返回错误的值。为什么时间不同?看起来像时区不同?打印以UTC显示日期。您的时区在6月夏令时为UTC+2,1月为UTC+1。2017-06-24 22:00:00+0000的时间点与2017-06-25 00:00:00+0200的时间点相同。我得到以下输出:2017-06-24 22:00:00+0000 2018-01-09 23:00:00+0000[SwiftDate]。在提取没有参考日期的日历特定组件时,可能会返回错误的值。为什么时间不同?我得到以下输出:2017-06-24 22:00:00+0000 2018-01-09 23:00:00+0000[SwiftDate]。在中提取没有参考日期的日历特定组件可能返回错误的值。为什么时间不同?这是一个很好的解决方案。我一点也没想到。本地化是一个很大的好处,效果很好。我还需要计算周和天,所以我将继续使用SwiftDate。但出于显示目的,此解决方案是好的。谢谢分享。这是一个很好的解决方案。我一点也没想到。本地化是一个很大的好处,效果很好。我还需要计算周和天,所以我将继续使用SwiftDate。但出于显示目的,此解决方案是好的。谢谢分享。