DateComponentsFormatter возвращает неверное количество единиц измерения

Я столкнулся с проблемой, когда DateComponentsFormatter возвращает неожиданное количество единиц. Кто-нибудь сталкивался с такой же проблемой?

import Foundation

let formatter = DateComponentsFormatter()
formatter.unitsStyle = .full;
formatter.maximumUnitCount = 1;

let date = Date(timeIntervalSinceNow: -14.7 * 24 * 60 * 60)
let dateString = formatter.string(from: date, to: Date()) // 2 weeks 1 day

Я ожидаю получить "2 недели", но имею "2 недели 1 день".

Ответ 1

Я решил проблему, проверив разделитель запятой и используя ее для подстановки вывода DateFormatters, пример PlayGround в Swift 3

// Test date
var df = DateFormatter()
df.dateFormat = "dd.MM.yyyy HH:mm:ss"
df.timeZone = TimeZone(secondsFromGMT: 0)
let fromDate = df.date(from: "01.01.2000 00:00:00")
var timeDifference = Date().timeIntervalSince(fromDate!)

// Setup formatter
let formatter = DateComponentsFormatter()
formatter.unitsStyle = .full
formatter.includesApproximationPhrase = false
formatter.zeroFormattingBehavior = .dropAll
formatter.maximumUnitCount = 1
formatter.allowsFractionalUnits = false

// Use the configured formatter to generate the string.
var outputString = formatter.string(from: timeDifference) ?? ""

// Remove 2nd unit if exists
let commaIndex = outputString.characters.index(of: ",") ?? outputString.endIndex
outputString = outputString.substring(to: commaIndex)

// Result
print(outputString)

Ответ 2

Вы проходите -14.7, округленное как -15. Таким образом, вы получаете 2 недели 1 день. Таким образом, округлите число, чтобы получить ожидаемые результаты.

Ответ 3

Я бы предложил немного более надежное решение (хотя все еще не уверен, что он работает для всех случаев)

let formatter = DateComponentsFormatter()
formatter.unitsStyle = .full
formatter.maximumUnitCount = 1

let date = Date(timeIntervalSinceNow: -14.7 * 24 * 60 * 60)
let dateString = formatter.string(from: date, to: Date()) ?? ""
if let nsRange = try? NSRegularExpression(pattern: "\\A\\d* \\w*").rangeOfFirstMatch(in: dateString, options: [], range: NSRange(location: 0, length: dateString.count)), let range = Range(nsRange, in: dateString) {
    let fixedString = String(dateString[range])
}

Ответ 4

Для тех, кто все еще ищет ответ, вот что я узнал:

В настоящее время существует только один относительно красивый способ решить эту проблему, и с помощью pod https://github.com/MatthewYork/DateTools.

По крайней мере, до https://openradar.appspot.com/26354907 разрешается Apple.