Я хочу получить минутную разницу между двумя датами, но, в отличие от других ответов в stackoverflow, я не хочу рассчитывать секунды.
Я имею в виду :
(год-месяц-день часы-минуты-секунды)
между этими двумя датами разница всего 1 минута.
Если я изменился на секунды первой даты до 58, я все равно хочу вывести как 1. Технически разница составляет всего 2 секунды, но минута отличается, а разница равна 1.
Вы можете подумать, взять только минутную часть от даты и вычислить, но разница между этими двумя датами может быть очень далекой, например, в месяцах, поэтому было бы трудно вычислить так, или я не мог найти способ сделать это.
Коды, которые я пробовал:
let diff = Int(end.timeIntervalSince1970 - start.timeIntervalSince1970)
let hours = diff / 3600
let minutes = (diff - hours * 3600) / 60
Этот, очевидно, вычисляет минуты на основе секунд, поэтому, если разница в секундах меньше 60, но все же 2 даты находятся в разных минутах, вывод равен 0.
Я также пробовал .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)")
}
Но и здесь такая же проблема.
Можете ли вы предоставить какой-либо код, который показывает, что вы пробовали?
Что вам нужно, так это вторая разница + 30 секунд, разделенная на 60 (количество секунд в I e минутах). Возьмите слово этого результата или конвертируйте его в Int





Насколько я понимаю, логика здесь такова: «взять наибольшую единицу разницы и округлить ее до 1 следующей большей единицы разницы».
В комментариях упоминается использование 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)
// 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
Это работает правильно для вашего примера, но вам нужно будет очистить некоторые из этих первых развертываний (хотя некоторые из них кажутся безотказными).
Вот функция, которая вычисляет разницу. Он начинается с использования того же метода, который вы используете, но проверяет, равен ли результат в минутах нулю, и поэтому использует вторую функцию из 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
}
}
Вы пробовали Calendar + DateComponents?