首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >获得单个NSDateComponent的两个日期之间的确切差异

获得单个NSDateComponent的两个日期之间的确切差异
EN

Stack Overflow用户
提问于 2016-05-15 20:19:13
回答 4查看 963关注 0票数 3

如何才能得到NSDate的两个值之间的精确差值(以十进制为单位)。

例如:2016年1月15日 to 7月15日2017年7月15日=1.5a

我可以使用这样的东西:NSCalendar.currentCalendar().components(NSCalendarUnit.CalendarUnitYear, fromDate: date1, toDate: date1, options: nil).year

但这给了我绝对值。也就是说,上面的例子会给我1年的。是否有可能使精确值至少修正到小数位呢?

EN

回答 4

Stack Overflow用户

发布于 2016-05-15 21:56:52

你在这里使用的术语是误导性的。当你说“绝对”时,意思是“积分”。当你说“精确”时,你指的是“在一定的精度范围内”。

假设你想要的精度是小数点2位,所以我们需要测量一年到1%。这比一天大,所以跟踪时间就足够了。如果你需要更高的精度,那么你可以扩展这项技术,但是如果你把它推得太远,“年份”就会变得更加棘手,你必须开始问你所谓的“一年”是什么意思。

尽量避免问这个问题。这里的许多答案都说:“一年中有365.25天。”但试着在“现在”中添加"365.25 * 24小时“,看看明年是否有”相同的日期和时间“。虽然这似乎是正确的“平均”,但实际上是错误的时间100%的日历日期。(这是因为它在1%以内,但365,366,甚至363%也是如此。)

我们通过说"1%已经足够解决这个问题“来避免这种疯狂。

代码语言:javascript
复制
// What calendar do you *really* mean here? The user's current calendar, 
// or the Gregorian calendar? The below code should work for any calendar,
// because every calendar's year is made up of some number of days, but it's
// worth considering if you really mean (and are testing) arbitrary calendars.
// If you mean "Gregorian," then use NSCalendar(identifier: NSCalendarIdentifierGregorian)!
let calendar = NSCalendar.currentCalendar()

// Determine how many integral days are between the dates
let diff = calendar.components(.Day, fromDate: date1, toDate: date2, options: [])

// Determine how many days are in a year. If you really meant "Gregorian" above, and
// so used calendarWithIdentifer rather than currentCalendar, you can estimate 365 here.
// Being within one day is inside the noise floor of 1%.
// Yes, this is harder than you'd think. This is based on MartinR's code: http://stackoverflow.com/a/16812482/97337
var startOfYear: NSDate? = nil
var lengthOfYear = NSTimeInterval(0)
calendar.rangeOfUnit(.Year, startDate: &startOfYear, interval: &lengthOfYear, forDate: date1)
let endOfYear = startOfYear!.dateByAddingTimeInterval(lengthOfYear)
let daysInYear = calendar.components(.Day, fromDate: startOfYear!, toDate: endOfYear, options: []).day

// Divide
let fracDiff = Double(diff.day) / Double(daysInYear)

也就是说,在大多数情况下,你不应该这样做。从iOS 8开始,首选工具是NSDateComponentsFormatter。您不会得到这种精确的格式(即小数年),但是您将得到一个很好的本地化结果,该结果考虑到了不同文化之间的大多数问题。

代码语言:javascript
复制
let formatter = NSDateComponentsFormatter()
formatter.unitsStyle = .Full
formatter.includesApproximationPhrase = true
formatter.allowedUnits = [.Year, .Month]
formatter.allowsFractionalUnits = true

formatter.stringFromDate(date1, toDate: date2)
// About 1 year, 6 months
票数 5
EN

Stack Overflow用户

发布于 2016-05-15 23:24:17

由于您提到您的目标可以显示给用户,作为两个日期之间时间的有意义的指示,您可能会发现使用NSDateComponentsFormatter更容易。例如:

代码语言:javascript
复制
let dateStr1 = "Jan 15 2016"
let dateStr2 = "Jul 15 2017"

let dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "MMM dd yyyy"

if let date1 = dateFormatter.dateFromString(dateStr1),
    let date2 = dateFormatter.dateFromString(dateStr2) {
    let dateComponentsFormatter = NSDateComponentsFormatter()
    dateComponentsFormatter.allowedUnits = [.Year, .Month]
    dateComponentsFormatter.unitsStyle = .Full

    let difference = dateComponentsFormatter.stringFromDate(date1, toDate: date2)
}

这给了你一个字符串,上面写着“1年6个月”。这并不是您指定的目标,但它为用户提供了明确的指示,避免了大量的复杂性。NSDateComponentsFormatter上有一个名为allowsFractionalUnits的属性,认为会导致“1.5年”这样的结果,但是现在看来不起作用了。(即使将allowedUnits限制为.Year,也不会得到分数年份。我要去向苹果公司提交一个窃听器。)您可以调整allowedUnits以获得您喜欢的任何粒度,并使用includesApproximationPhrase使类添加本地化版本的“约.”如果结果字符串不精确的话。如果您在最终格式中具有一定的灵活性,这将是一个非常好的解决方案。

票数 3
EN

Stack Overflow用户

发布于 2016-05-15 21:44:58

这个问题没有一个完美的答案。不同年份的长度略有不同。你得做些假设。

如果假设每年有365.2425天,每天有24小时,那么计算就很简单:

代码语言:javascript
复制
let secondsPerYear: NSTimeInterval = NSTimeInterval(365.2425 * 24 * 60 * 60)
let secondsBetweenDates = 
  date2.timeIntervalSinceReferenceDate - date1.timeIntervalSinceReferenceDate;
let yearsBetweenDates = secondsBetweenDates / secondPerYear

但是,有许多边缘案件和怪诞需要处理。因为闰年,有些年份有365天,有些年份有366天。然后是闰秒。

如果你去掉@CodeDiff传中的几个月,你就会得到一个允许日期之间的闰日的答案。

但是,正如“代码不同”所指出的,他所写的答案实际上给出了更准确的答案,尽管答案并不准确。(3个月的差异总是会产生.25年,而忽略更长/更短的月。这是正确的做法吗?取决于你的目标和假设。)

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/37243246

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档