英文:
Getting minute difference between 2 dates without 60 second calculation
问题
I want to get minute difference between 2 dates but unlike the other answers in stackoverflow, I don't want to calculate with seconds.
What I mean is :
(year-month-day hours-minutes-seconds)
- 2023-04-17 13:42:00
- 2023-04-17 13:43:00
between these 2 dates there is only 1 minutes difference.
- 2023-04-17 13:42:58
- 2023-04-17 13:43:00
If I changed to first date's seconds to 58, I still want output as 1. Technically, difference is only 2 seconds but minute is different and difference is 1.
You might think, take only the minute part from date and calculate but difference between these 2 dates might be much far, like months away so it would be hard to calculate like that or I could not find a way to do it.
Codes I have tried:
let diff = Int(end.timeIntervalSince1970 - start.timeIntervalSince1970)
let hours = diff / 3600
let minutes = (diff - hours * 3600) / 60
This one obviously calculate the minutes based on seconds so if seconds difference is less than 60 but still 2 dates are on different minutes, output is 0.
I also tried .dateComponents
let calendar = Calendar.current
let startDate = Date() // replace with your start date
let endDate = Date() // replace with your end date
let components = calendar.dateComponents([.minute], from: startDate, to: endDate)
if let minutes = components.minute {
print("Number of minutes between start and end dates: \(minutes)")
}
But also the same problem here.
英文:
I want to get minute difference between 2 dates but unlike the other answers in stackoverflow, I don't want to calculate with seconds.
What I mean is :
(year-month-day hours-minutes-seconds)
- 2023-04-17 13:42:00
- 2023-04-17 13:43:00
between these 2 dates there is only 1 minutes difference.
- 2023-04-17 13:42:58
- 2023-04-17 13:43:00
If I changed to first date's seconds to 58, I still want output as 1. Technically, difference is only 2 seconds but minute is different and difference is 1.
You might think, take only the minute part from date and calculate but difference between these 2 dates might be much far, like months away so it would be hard to calculate like that or I could not find a way to do it.
Codes I have tried :
let diff = Int(end.timeIntervalSince1970 - start.timeIntervalSince1970)
let hours = diff / 3600
let minutes = (diff - hours * 3600) / 60
This one obviously calculate the minutes based on seconds so if seconds difference is less than 60 but still 2 dates are on different minutes, output is 0.
I also tried .dateComponents
let calendar = Calendar.current
let startDate = Date() // replace with your start date
let endDate = Date() // replace with your end date
let components = calendar.dateComponents([.minute], from: startDate, to: endDate)
if let minutes = components.minute {
print("Number of minutes between start and end dates: \(minutes)")
}
But also the same problem here.
答案1
得分: 1
这是一个计算时间差的函数。它首先使用与您相同的方法,但检查分钟结果是否为零,如果是,则使用Calendar
的第二个函数查看日期是否完全相同,然后按分钟比较,isDate(:equalTo:toGranularity:)
。
func minuteDifference(from startDate: Date, to endDate: Date) -> Int {
let minutes = calendar.dateComponents([.minute], from: startDate, to: endDate).minute!
if minutes != 0 {
return minutes
} else {
let factor = startDate <= endDate ? 1 : -1
return calendar.isDate(startDate, equalTo: endDate, toGranularity: .minute) ? 0 : 1 * factor
}
}
英文:
Here is a function that calculates the difference. It starts by using the same method you use but checks if the result in minutes is zero and of so uses a second function from Calendar
to see if the dates are exactly the same or not and then equal comparing down to minutes, isDate(:equalTo:toGranularity:)
func minuteDifference(from startDate: Date, to endDate: Date) -> Int {
let minutes = calendar.dateComponents([.minute], from: startDate, to: endDate).minute!
if minutes != 0 {
return minutes
} else {
let factor = startDate <= endDate ? 1 : -1
return calendar.isDate(startDate, equalTo: endDate, toGranularity: .minute) ? 0 : 1 * factor
}
}
答案2
得分: 0
根据我的理解,这里的逻辑是“找到最大的时间单位差异,并将其四舍五入到下一个更大的时间单位差异的整数倍”。
注释中提到使用DateComponents
,这绝对是正确的起点,但我没有看到内置的方法能够精确地执行此操作。例如,如果你的时间单位集合是[.minute]
,但不包括.second
,那么你就会完全失去秒的精度。你不会看到它被四舍五入到1分钟的差异,仅仅是因为你没有要求以秒为单位的差异。
这是我的开始方式:
import Foundation
extension Date {
static private let allComponents: [Calendar.Component] = [.year, .month, .day, .hour, .minute, .second]
static private let allComponentsSet = Set(allComponents)
static func approximatedDifference(from start: Date, to end: Date) -> DateComponents {
var differenceComponents = Calendar.current.dateComponents(Self.allComponentsSet, from: start, to: end)
// 例如,对于`2023-04-17 13:42:58`和`2023-04-17 13:43:00`,这将是`.second`。
let largestDifferingComponent = Self.allComponents.first(where: { differenceComponents.value(for: $0) != 0 })!
// 这是下一个更大的时间单位。例如,如果`largestDifferingComponent`是`.second`,那么这将是`.minute`。
let largerComponentIndex = Self.allComponents.index(allComponents.firstIndex(of: largestDifferingComponent)!, offsetBy: -1, limitedBy: 0)!
let largerComponent = allComponents[largerComponentIndex]
// 将较小的差异组件清零
differenceComponents.setValue(0, for: largestDifferingComponent)
// 在下一个更大的时间单位中增加差异
differenceComponents.setValue(differenceComponents.value(for: largerComponent)! + 1, for: largerComponent)
return differenceComponents
}
}
let start = DateComponents(calendar: .current, year: 2023, month: 04, day: 17, hour: 13, minute: 42, second: 58).date!
let end = DateComponents(calendar: .current, year: 2023, month: 04, day: 17, hour: 13, minute: 43, second: 00).date!
print(Date.approximatedDifference(from: start, to: end)) // 1 minute
英文:
From what I understand, the logic here is "take the largest unit of difference, and round it up to 1 of the next larger unit of difference".
The comments mention using DateComponents
, which is definitely the correct starting point, but I don't see any built in way to do precisely this. E.g. if your set of components is [.minute]
but doesn't include .second
, you just lose the second granularity entirely. You won't see it rounded up to a 1 minute difference just because you didn't ask for the difference in seconds.
Here's how I would start:
import Foundation
extension Date {
static private let allComponents: [Calendar.Component] = [.year, .month, .day, .hour, .minute, .second]
static private let allComponentsSet = Set(allComponents)
static func approximatedDifference(from start: Date, to end: Date) -> DateComponents {
var differenceComponents = Calendar.current.dateComponents(Self.allComponentsSet, from: start, to: end)
// E.g. for `2023-04-17 13:42:58` and `2023-04-17 13:43:00`, this will be `.second`.
let largestDifferingComponent = Self.allComponents.first(where: { differenceComponents.value(for: $0) != 0 })!
// This is the next large component. E.g. if `largestDifferingComponent` is `.second`, then this will be `.minute`.
let largerComponentIndex = Self.allComponents.index(allComponents.firstIndex(of: largestDifferingComponent)!, offsetBy: -1, limitedBy: 0)!
let largerComponent = allComponents[largerComponentIndex]
// Zero out the smaller differing component
differenceComponents.setValue(0, for: largestDifferingComponent)
// Increment the difference in the next larger component
differenceComponents.setValue(differenceComponents.value(for: largerComponent)! + 1, for: largerComponent)
return differenceComponents
}
}
let start = DateComponents(calendar: .current, year: 2023, month: 04, day: 17, hour: 13, minute: 42, second: 58).date!
let end = DateComponents(calendar: .current, year: 2023, month: 04, day: 17, hour: 13, minute: 43, second: 00).date!
print(Date.approximatedDifference(from: start, to: end)) // 1 minute
It works correctly for your example, but you'll need to clean up some of those first unwraps (though some of them seem unfailable).
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论