如何在iOS上获得ISO 8601日期?

Joh*_*hnK 109 iso8601 nsdate nsdateformatter ios

2004-02-12T15:19:21+00:00在PHP中获取ISO 8601日期字符串(例如)很容易date('c'),但是如何在Objective-C(iPhone)中获取它?是否有类似的简短方法呢?

这是我发现的漫长道路:

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
Run Code Online (Sandbox Code Playgroud)

对于如此重要​​的事情来说,这似乎是一件非常艰难的事情.

rma*_*ddy 206

用途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];
Run Code Online (Sandbox Code Playgroud)

在斯威夫特:

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())
Run Code Online (Sandbox Code Playgroud)

  • @maddy - 想让其他人通过谷歌发现这一点很容易发现,并希望通过挖掘正确的格式,地点等来给你信任.但是如果你想要的话,很乐意将它作为一个单独的答案发布 (11认同)
  • 应将区域设置设置为en_US_POSIX的原因:https://developer.apple.com/library/mac/qa/qa1480/_index.html (6认同)
  • @jlmendezbonini没有.你想要YYYY是非常罕见的.你通常想要yyyy. (4认同)
  • 这个懒惰/学习迅速的开发人员谢谢你. (3认同)
  • @rmaddy您可能只是编辑您的示例以使用ZZZZZ,以便人们复制粘贴不会被烧毁. (2认同)

Two*_*aws 51

iOS 10引入了一个新NSISO8601DateFormatter类来处理这个问题.如果您使用的是Swift 3,您的代码将是这样的:

let formatter = ISO8601DateFormatter()
let date = formatter.date(from: "2016-08-26T12:39:00Z")
let string = formatter.string(from: Date())
Run Code Online (Sandbox Code Playgroud)

  • 你**不能**用这种格式处理**毫秒**. (3认同)
  • @Enrique:您应该将NSISO8601DateFormatWithFractionalSeconds添加到格式化程序选项中,以便能够使用毫秒,请检查文档。 (3认同)

Eti*_*nne 27

作为maddy答案的补充,ISO 8601的时区格式应为"ZZZZZ"(5倍Z),而不是单个"Z"(用于RFC 822格式).至少在iOS 6上.

(见http://www.unicode.org/reports/tr35/tr35-25.html#Date_Format_Patterns)


Vad*_*vin 16

一个经常被忽视的问题是ISO 8601格式的字符串可能有毫秒而不是.

换句话说,"2016-12-31T23:59:59.9999999"和"2016-12-01T00:00:00"都是合法的,但如果您使用的是静态类型的日期格式化程序,则其中一个将不会被解析.

iOS 10开始,您应该使用ISO8601DateFormatter它来处理ISO 8601日期字符串的所有变体.见下面的例子:

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)
Run Code Online (Sandbox Code Playgroud)

对于iOS 9及更低版本,请使用以下方法和多个数据格式化程序.

我还没有找到一个涵盖这两个案例的答案,并且摘要了这个微妙的差异.以下是解决它的解决方案:

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
    }
}
Run Code Online (Sandbox Code Playgroud)

用法:

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
Run Code Online (Sandbox Code Playgroud)

我还建议检查有关日期格式化程序的Apple文章.


Dav*_*d H 8

所以在这里使用Sam Soffee的NSDate类别.将代码添加到项目中后,您可以在NSDate上使用单个方法:

- (NSString *)sam_ISO8601String
Run Code Online (Sandbox Code Playgroud)

它不仅是一行,它比NSDateFormatter方法快得多,因为它是用纯C.写的.


onm*_*133 6

IS8601开始,问题是表示和时区

  • ISO 8601 = year-month-day time timezone
  • 对于日期和时间,有基本(YYYYMMDD,hhmmss,...)和扩展格式(YYYY-MM-DD,hh:mm:ss,...)
  • 时区可以是Zulu,偏移或GMT
  • 日期和时间的分隔符可以是空格,或 T
  • 日期有周格式,但很少使用
  • 时区之后可以有很多空格
  • 第二是可选的

这是一些有效的字符串

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
Run Code Online (Sandbox Code Playgroud)

解决方案

NSDateFormatter

所以这是我在onmyway133 ISO8601中使用的格式

let formatter = NSDateFormatter()
formatter.locale = NSLocale(localeIdentifier: "en_US_POSIX")
formatter.dateFormat = "yyyyMMdd HHmmssZ"
Run Code Online (Sandbox Code Playgroud)

关于Z标识符日期字段符号表

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)
Run Code Online (Sandbox Code Playgroud)

关于locale 使用区域设置格式化数据

区域设置表示特定用户的格式选择,而不是用户的首选语言.这些通常是相同的但可以是不同的.例如,居住在德国的母语为英语的人可能选择英语作为语言,德国作为地区

关于en_US_POSIX 技术问答QA1480 NSDateFormatter和Internet日期

另一方面,如果您使用的是固定格式的日期,则应首先将日期格式化程序的区域设置设置为适合您的固定格式的区域设置.在大多数情况下,选择的最佳语言环境是"en_US_POSIX",这是一种专门用于产生美国英语结果的语言环境,无论用户和系统偏好如何."en_US_POSIX"在时间上也是不变的(如果美国在未来的某个时刻改变了格式化日期的方式,"en_US"将改变以反映新行为,但"en_US_POSIX"将不会),以及机器之间( "en_US_POSIX"在iOS上的工作方式与在OS X上的工作方式相同,就像在其他平台上一样.

有趣的相关排队


小智 6

只需使用Foundation 框架中的NSISO8601DateFormatter即可。

let isoDateFormatter = ISO8601DateFormatter()
print("ISO8601 string: \(isoDateFormatter.string(from: Date()))")
// ISO8601 string: 2018-03-21T19:11:46Z
Run Code Online (Sandbox Code Playgroud)

https://developer.apple.com/documentation/foundation/nsiso8601dateformatter?language=objc


Abd*_*mer 5

在 iOS 15 中,您可以获得 ISO860,如下所示:

let iso8601String = Date.now.ISO8601Format()
Run Code Online (Sandbox Code Playgroud)