Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/109.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 获取单个NSDateComponent的两个日期之间的精确差值_Ios_Swift_Nsdate_Nsdatecomponents - Fatal编程技术网

Ios 获取单个NSDateComponent的两个日期之间的精确差值

Ios 获取单个NSDateComponent的两个日期之间的精确差值,ios,swift,nsdate,nsdatecomponents,Ios,Swift,Nsdate,Nsdatecomponents,如何获得NSDate的两个值之间的精确差(十进制) 例如:2016年1月15日至2017年7月15日=1.5年 我可以使用类似于: NSCalendar.currentCalendar().components(NSCalendarUnit.CalendarUnitYear,fromDate:date1,toDate:date1,options:nil)。年份 但这给了我绝对值。i、 e.对于上面的例子,它将给我1年。是否有可能将精确值至少精确到小数点后几位?根据统计,每年平均有365.2422

如何获得
NSDate
的两个值之间的精确差(十进制)

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

我可以使用类似于:
NSCalendar.currentCalendar().components(NSCalendarUnit.CalendarUnitYear,fromDate:date1,toDate:date1,options:nil)。年份

但这给了我绝对值。i、 e.对于上面的例子,它将给我1年。是否有可能将精确值至少精确到小数点后几位?

根据统计,每年平均有365.2422天。在这里,我将其四舍五入至每年365.25天:

let components = NSCalendar.currentCalendar().components([.Year, .Month, .Day], fromDate: fromDate, toDate: toDate, options: [])

var totalYears = Double(components.year)
totalYears += Double(components.month) / 12.0
totalYears += Double(components.day) / 365.25
显然,这取决于你的假设。如果您想计算从日期到日期之间的闰日,那么它将更加复杂

一些示例输出:

From date      To date        Total Years
------------   ------------   ------------
Jan 15, 2016   Jul 15, 2017   1.5
Jan 15, 2016   Apr 14, 2016   0.25
Jan 15, 2016   Aug 15, 2017   1.5833
Jan 15, 2016   Jan 14, 2018   1.9988

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

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

let secondsPerYear: NSTimeInterval = NSTimeInterval(365.2425 * 24 * 60 * 60)
let secondsBetweenDates = 
  date2.timeIntervalSinceReferenceDate - date1.timeIntervalSinceReferenceDate;
let yearsBetweenDates = secondsBetweenDates / secondPerYear
但是有很多边缘案例和奇怪之处需要处理。因为闰年,有些年份有365天,有些年份有366天。还有闰秒

如果您在@CodeDifferent的答案中去掉了月份,那么您将得到一个允许日期之间有闰日的答案


但是,正如Code Different所指出的,他的书面回答实际上给出了似乎更准确的答案,尽管答案并不准确。(3个月的差异总是会产生。25年,并且会忽略更长/更短的月份。这是正确的做法吗?取决于你的目标和假设。)

你在这里使用的术语具有误导性。当你说“绝对”时,你指的是“积分”。当你说“精确”时,你指的是“在某种期望的精度范围内。”

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

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

我们通过说“1%就足以解决这个问题”来避免这种疯狂

也就是说,在大多数情况下,你不应该这样做。自iOS 8以来,首选工具是
nsdatecomponentsformter
。你不会得到这种精确的格式(即分数年),但你会得到一个很好的本地化结果,它考虑了不同文化中的大多数问题

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

由于您提到您的目标是可以向用户显示两个日期之间的时间,因此您可能会发现使用
nsdatecomponentsformter
更容易。例如:

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个月”。这并不完全是您指定的目标,但它为用户提供了一个明确的指示,并避免了很多复杂性。
nsdatecomponentsformter
上有一个名为
allowsFractilunits
的属性,它被认为会导致类似“1.5年”的结果,但是。(即使你将
允许单位
限制为
.Year
,你仍然得不到小数年。我要向苹果公司提交一个bug…)。您可以调整
allowedUnits
以获得您喜欢的粒度,并使用
includeApproximationPhase
让类在结果字符串中添加“About…”的本地化版本(如果不精确)。如果您的最终格式有一定的灵活性,这将是一个非常好的解决方案。

您需要定义小数年的含义。是基于两个日期之间天数的一年的小数部分(这两个日期相隔366天(2016年是闰年)。还是确切地说是6个月(不同的6个月组有不同的天数).啊,好的。我假设既然指定了起始日期和截止日期,斯威夫特就知道哪一年是闰年,哪一个月是28天、30天、31天等等。如果不是这样,我就必须根据假设实施我自己的解决方案。所以斯威夫特基本上不会给我十进制的精确值,对吗?当然所有这些信息关于是已知的。你没有领会我的意思。你首先需要对分数年给出一个理想的定义。计算部分年的方法不止一种。我想我有一些阅读要做。不熟悉部分年/分数年的概念。你能给我指一些阅读链接或例子吗?我想我明白你的意思。所以如果我得到365天的差异,那么为了得到转换,我需要定义365天=1年还是366天=1年。在计算中包括月份似乎不必要地引入了错误。月份的长度从28天到31天不等。为什么不询问两个日期之间的年数和天数,而完全跳过月份呢?@Duncac这不是人类思维的运作方式。例如,4月1日和7月1日之间有91天;7月1日和10月1日之间有92天。然而,大多数人会说它们都相差3个月。我们甚至有一个名称:一年的四分之一,或
0.25
。计算日期很复杂但这很复杂。这取决于目标,真的。如果你想对日期之间的分数差做出尽可能准确的估计,那么省略月份就可以了
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)
}