SwiftDate 和日期计算
SwiftDate and date calculation
我正在尝试计算宠物存活的周数和天数。我正在为此使用 SwiftDate。所以我让用户 select 一个生日并将其与当前日期进行比较。
我不想比较时间...所以生日和当前日期应该是同一时间。
我的代码是:
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)"
输出为"Age: 28 wk, 3 d (199 d)"
代码有效...但我该如何重构它?有没有更简单的方法来为两个给定日期设置 'same time'?
如果你不在乎时差,为什么不把时间完全去掉呢?它会给你相同的输出,并且只会让你免于输入默认时间值,然后在你的函数的其余部分忽略它们:
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
的组成部分
let components1 = greg.dateComponents([.year, .month, .day], from: date1)
let components2 = greg.dateComponents([.year, .month, .day], from: date2)
date1 = greg.date(from: components1)!
date2 = greg.date(from: components2)!
这是一个没有任何第三方库的更简单的解决方案。它使用 Calendar
方法 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
。您可能还会看到 DateComponentsFormatter
是否可以实现您想要的:
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)
}
虽然 DateComponentsFormatter
在结果方面有些局限,但它是本地化的,因此在美国语言环境中会出现以下结果:
28 weeks, 3 days
但是,如果您的应用配置为支持其他语言环境,例如德语,则会导致:
28 Wochen und 3 Tage
我正在尝试计算宠物存活的周数和天数。我正在为此使用 SwiftDate。所以我让用户 select 一个生日并将其与当前日期进行比较。
我不想比较时间...所以生日和当前日期应该是同一时间。
我的代码是:
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)"
输出为"Age: 28 wk, 3 d (199 d)"
代码有效...但我该如何重构它?有没有更简单的方法来为两个给定日期设置 'same time'?
如果你不在乎时差,为什么不把时间完全去掉呢?它会给你相同的输出,并且只会让你免于输入默认时间值,然后在你的函数的其余部分忽略它们:
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
let components1 = greg.dateComponents([.year, .month, .day], from: date1)
let components2 = greg.dateComponents([.year, .month, .day], from: date2)
date1 = greg.date(from: components1)!
date2 = greg.date(from: components2)!
这是一个没有任何第三方库的更简单的解决方案。它使用 Calendar
方法 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
。您可能还会看到 DateComponentsFormatter
是否可以实现您想要的:
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)
}
虽然 DateComponentsFormatter
在结果方面有些局限,但它是本地化的,因此在美国语言环境中会出现以下结果:
28 weeks, 3 days
但是,如果您的应用配置为支持其他语言环境,例如德语,则会导致:
28 Wochen und 3 Tage