Il est assez facile d’obtenir la chaîne de date ISO 8601 (par exemple, 2004-02-12T15:19:21+00:00
) Dans PHP via date('c')
], mais comment l'obtenir dans Objective- C (iPhone)? Y a-t-il un moyen aussi court de le faire?
Voici le long moyen que j'ai trouvé pour le faire:
NSDateFormatter* dateFormatter = [[[NSDateFormatter alloc] init] autorelease];
dateFormatter.dateFormat = @"yyyy-MM-dd'T'HH:mm:ssZ";
NSDate *now = [NSDate date];
NSString *formattedDateString = [dateFormatter stringFromDate:now];
NSLog(@"ISO-8601 date: %@", formattedDateString);
// Output: ISO-8601 date: 2013-04-27T13:27:50-0700
Il semble y avoir énormément de rigueur pour quelque chose d'aussi central.
Utilisez NSDateFormatter
:
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
NSLocale *enUSPOSIXLocale = [NSLocale localeWithLocaleIdentifier:@"en_US_POSIX"];
[dateFormatter setLocale:enUSPOSIXLocale];
[dateFormatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ssZZZZZ"];
[dateFormatter setCalendar:[NSCalendar calendarWithIdentifier:NSCalendarIdentifierGregorian]];
NSDate *now = [NSDate date];
NSString *iso8601String = [dateFormatter stringFromDate:now];
Et à Swift:
let dateFormatter = DateFormatter()
let enUSPosixLocale = Locale(identifier: "en_US_POSIX")
dateFormatter.locale = enUSPosixLocale
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZZZZZ"
dateFormatter.calendar = Calendar(identifier: .gregorian)
let iso8601String = dateFormatter.string(from: Date())
iOS 10 introduit un nouveau NSISO8601DateFormatter
classe pour gérer cela. Si vous utilisez Swift 3, votre code ressemblerait à ceci:
let formatter = ISO8601DateFormatter()
let date = formatter.date(from: "2016-08-26T12:39:00Z")
let string = formatter.string(from: Date())
En complément de la réponse de maddy, le format de fuseau horaire doit être "ZZZZZ" (5 fois Z) pour ISO 8601 au lieu d'un seul "Z" (format RFC 822). Au moins sur iOS 6.
(voir http://www.unicode.org/reports/tr35/tr35-25.html#Date_Format_Patterns )
Un problème souvent négligé est que les chaînes au format ISO 8601 peuvent prendre plusieurs millisecondes et peuvent ne pas l'être.
En d'autres termes, "2016-12-31T23: 59: 59.9999999" et "2016-12-01T00: 00: 00" sont légitimes, mais si vous utilisez un programme de formatage de date de type statique, l'un d'eux ne sera pas analysé. .
À partir de iOS 10 , vous devez utiliser ISO8601DateFormatter
qui gère toutes les variations des chaînes de date ISO 8601. Voir exemple ci-dessous:
let date = Date()
var string: String
let formatter = ISO8601DateFormatter()
string = formatter.string(from: date)
let GMT = TimeZone(abbreviation: "GMT")
let options: ISO8601DateFormatOptions = [.withInternetDateTime, .withDashSeparatorInDate, .withColonSeparatorInTime, .withTimeZone]
string = ISO8601DateFormatter.string(from: date, timeZone: GMT, formatOptions: options)
Pour iOS 9 et inférieur , utilisez l’approche suivante avec plusieurs formateurs de données.
Je n'ai pas trouvé de réponse qui couvre les deux cas et résume cette différence subtile. Voici la solution qui y répond:
extension DateFormatter {
static let iso8601DateFormatter: DateFormatter = {
let enUSPOSIXLocale = Locale(identifier: "en_US_POSIX")
let iso8601DateFormatter = DateFormatter()
iso8601DateFormatter.locale = enUSPOSIXLocale
iso8601DateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"
iso8601DateFormatter.timeZone = TimeZone(secondsFromGMT: 0)
return iso8601DateFormatter
}()
static let iso8601WithoutMillisecondsDateFormatter: DateFormatter = {
let enUSPOSIXLocale = Locale(identifier: "en_US_POSIX")
let iso8601DateFormatter = DateFormatter()
iso8601DateFormatter.locale = enUSPOSIXLocale
iso8601DateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss'Z'"
iso8601DateFormatter.timeZone = TimeZone(secondsFromGMT: 0)
return iso8601DateFormatter
}()
static func date(fromISO8601String string: String) -> Date? {
if let dateWithMilliseconds = iso8601DateFormatter.date(from: string) {
return dateWithMilliseconds
}
if let dateWithoutMilliseconds = iso8601WithoutMillisecondsDateFormatter.date(from: string) {
return dateWithoutMilliseconds
}
return nil
}
}
Utilisation:
let dateToString = "2016-12-31T23:59:59.9999999"
let dateTo = DateFormatter.date(fromISO8601String: dateToString)
// dateTo: 2016-12-31 23:59:59 +0000
let dateFromString = "2016-12-01T00:00:00"
let dateFrom = DateFormatter.date(fromISO8601String: dateFromString)
// dateFrom: 2016-12-01 00:00:00 +0000
Je recommande également de vérifier article Apple à propos des formateurs de date.
Donc utilisez la catégorie de Sam Soffee sur NSDate trouvée ici . Avec ce code ajouté à votre projet, vous pouvez désormais utiliser une seule méthode sur NSDate:
- (NSString *)sam_ISO8601String
Ce n'est pas seulement une ligne, c'est beaucoup plus rapide que l'approche NSDateFormatter, car elle est écrite en C pur.
Depuis IS8601 , les problèmes sont la représentation et le fuseau horaire
year-month-day time timezone
T
Voici quelques chaînes valides
2016-04-08T10:25:30Z
2016-04-08 11:25:30+0100
2016-04-08 202530GMT+1000
20160408 08:25:30-02:00
2016-04-08 11:25:30 +0100
Solutions
NSDateFormatter
Donc, voici le format que j'utilise dans onmyway133 ISO8601
let formatter = NSDateFormatter()
formatter.locale = NSLocale(localeIdentifier: "en_US_POSIX")
formatter.dateFormat = "yyyyMMdd HHmmssZ"
À propos de l'identifiant Z
table des symboles de champs date
Z: The ISO8601 basic format with hours, minutes and optional seconds fields. The format is equivalent to RFC 822 zone format (when optional seconds field is absent)
À propos de locale
Mise en forme des données à l’aide des paramètres régionaux
Les paramètres régionaux représentent les choix de formatage pour un utilisateur particulier, pas la langue préférée de l'utilisateur. Ce sont souvent les mêmes mais peuvent être différents. Par exemple, un anglophone vivant en Allemagne peut choisir l'anglais comme langue et l'Allemagne comme région.
À propos de en_US_POSIX
Questions techniques QA1480, NSDateFormatter et Internet
D'autre part, si vous utilisez des dates au format fixe, vous devez d'abord définir les paramètres régionaux du formateur de date sur quelque chose correspondant à votre format fixe. Dans la plupart des cas, la meilleure langue à choisir est "en_US_POSIX", une langue spécialement conçue pour produire des résultats en anglais américain indépendamment des préférences de l'utilisateur et du système. "en_US_POSIX" est également invariant dans le temps (si les États-Unis, à un moment donné, modifient le format des dates, "en_US" changera pour refléter le nouveau comportement, mais "en_US_POSIX" ne le sera pas) et entre les machines ( "en_US_POSIX" fonctionne de la même manière sur iOS que sur OS X et sur les autres plates-formes).
Questions connexes intéressantes
Il suffit d'utiliser NSISO8601DateFormatter à partir du framework Foundation.
let isoDateFormatter = ISO8601DateFormatter()
print("ISO8601 string: \(isoDateFormatter.string(from: Date()))")
// ISO8601 string: 2018-03-21T19:11:46Z
https://developer.Apple.com/documentation/foundation/nsiso8601dateformatter?language=objc
Sur la base de cet élément essentiel: https://github.com/justinmakaila/NSDate-ISO-8601/blob/master/NSDateISO8601.Swift , la méthode suivante peut être utilisée pour convertir NSDate en chaîne de date ISO 8601 au format aaaa-MM-jj'T'HH: mm: ss.SSSZ
-(NSString *)getISO8601String
{
static NSDateFormatter *formatter = nil;
if (!formatter)
{
formatter = [[NSDateFormatter alloc] init];
[formatter setLocale: [NSLocale localeWithLocaleIdentifier:@"en_US_POSIX"]];
formatter.timeZone = [NSTimeZone timeZoneWithAbbreviation: @"UTC"];
[formatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ss.SSS"];
}
NSString *iso8601String = [formatter stringFromDate: self];
return [iso8601String stringByAppendingString: @"Z"];
}
Ceci est un peu plus simple et met la date en UTC.
extension NSDate
{
func iso8601() -> String
{
let dateFormatter = NSDateFormatter()
dateFormatter.timeZone = NSTimeZone(name: "UTC")
let iso8601String = dateFormatter.stringFromDate(NSDate())
return iso8601String
}
}
let date = NSDate().iso8601()