简体   繁体   English

SwiftDate和日期计算

[英]SwiftDate and date calculation

I'm trying to calculate the number of weeks and days that a pet is alive. 我正在尝试计算宠物存活的周数和天数。 I'm using SwiftDate for that. 我为此使用SwiftDate。 So I let the user select a birthdate and compare it to the current date. 因此,我让用户选择一个生日并将其与当前日期进行比较。

I don't want to compare the time... so both the birthdate and current date should have the same time. 我不想比较时间...所以生日和当前日期应该有相同的时间。

My code is: 我的代码是:

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)"

Output is "Age: 28 wk, 3 d (199 d)" 输出为“年龄:28周,3天(199天)”

The code works... but how can I refactor it? 该代码有效...但是如何重构它? And is there an easier way to set the 'same time' for two given dates? 有没有更简单的方法来设置两个给定日期的“相同时间”?

If you don't care about the time difference, why not just leave the time out completely? 如果您不关心时差,为什么不完全将时间留在外面呢? It would give you the same output, and would just save you from putting in default time values and then ignoring them for the rest of your function: 它将为您提供相同的输出,并且只会使您免于放入默认时间值,然后在其余功能中忽略它们:

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)"

To ignore the time just omit the components for .hour , .minute and .second 要忽略时间,只需省略.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)!

This is a simpler solution without any third party library. 这是一个没有任何第三方库的简单解决方案。 It calculates the difference once for weekOfMonth and day and once for day with the Calendar method dateComponents(:from:to: . Extra math is not needed. 它计算的差异一次weekOfMonthday和一次dayCalendardateComponents(:from:to: 。不需要额外的数学。

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)"

As others have pointed out, you can just grab .year , .month , .day from your calendar. 正如其他人指出的那样,您只需从日历中获取.year.month.day You might also see if DateComponentsFormatter can achieve what you want: 您可能还会看到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)
}

While the DateComponentsFormatter is a little constrained regarding the results, it is localized, resulting in the following in US locale: 尽管DateComponentsFormatter在结果方面有所限制,但它已本地化,在美国语言环境中导致以下情况:

28 weeks, 3 days 28周3天

But if your app is configured to support other locales, for example German, it results in: 但是,如果您的应用配置为支持其他语言环境,例如德语,则会导致:

28 Wochen und 3 Tage 28月和3击

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM