2016-12-16 1 views
10

J'ai rencontré un problème lorsque DateComponentsFormatter renvoie un nombre d'unités inattendu. Est-ce que quelqu'un a fait face au même problème?DateComponentsFormatter renvoie un nombre erroné de nombre d'unités

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 

Je m'attends à recevoir "2 semaines", mais j'ai "2 semaines 1 jour".

+0

Pourquoi utilisez-vous '14.7'? – shallowThought

+0

@shallowThought J'ai défini 'maximumUnitCount' - le formatter ne doit pas renvoyer plus d'une unité. –

+0

FYI - Utiliser 'Date (timeIntervalSinceNow: -14.7 * 24 * 60 * 60)' est une façon terrible de faire des calculs de date. Pas tous les jours a 24 heures. Pas toutes les heures a 3600 secondes. Utilisez l'une des méthodes 'Calendar date (byAdding ...)'. – rmaddy

Répondre

1

Vous passez -14,7 qui est arrondi à -15. Donc, vous obtenez 2 semaines 1 jour. Donc arrondir le nombre correctement pour obtenir les résultats attendus.

+3

J'ai réglé 'maximumUnitCount' - formatter ne devrait pas retourner plus d'une unité. –

+2

Étrange. Dès que vous le faites moins de -14,5, il montre une seule unité. Si vous faites -15 et ensuite, il montre également 1 unité seulement. Quelque part entre -14.5 et -14.99, il échoue. La même chose est observée au début d'une nouvelle semaine. Je veux dire -21, -28 et ainsi .. – Apurv

+0

merci. Maintenant, vous voyez.) –

3

Je résolu la question en vérifiant le séparateur virgule et l'utiliser pour substring la sortie de DateFormatters, par exemple 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) 
+0

Je propose de vérifier le nombre d'occurrences "," en fonction de 'maximumUnitCount' pour le rendre plus général. En même temps, sait-on que toutes les langues utilisent la virgule pour séparer les unités? –

+0

Le message [OpenRadar] (https://openradar.appspot.com/26354907) spécifie uniquement qu'un «maximumUnitCount = 1» ne présente que le bogue. J'ai vérifié la [documentation] (https://developer.apple.com/reference/foundation/datecomponentsformatter/) et n'ai trouvé aucune information sur les séparateurs. Le repli n'utilise que la chaîne entière, donc je pense que c'est une solution de repli acceptable. – Mknsri

+0

OK, je vais upvote votre réponse parce que je fais presque la même chose. –

0

Je proposerais peu solution plus fiable (tout en pas sûr qu'il fonctionne pour tous les cas)

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]) 
}