我如何在iOS上的ISO 8601日期?(How do I get an ISO 8601 date

2019-09-01 06:36发布

这是很容易获得ISO 8601日期字符串(例如, 2004-02-12T15:19:21+00:00 ),在PHP中通过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

这似乎是一个可怕的很多繁琐手续的东西如此重要。

Answer 1:

使用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 setsetCalendar:[NSCalendar calendarWithIdentifier:NSCalendarIdentifierGregorian]];

NSDate *now = [NSDate date];
NSString *iso8601String = [dateFormatter stringFromDate:now];

而在斯威夫特:

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())


Answer 2:

iOS版10引入了一个新NSISO8601DateFormatter类来处理眼前这个。 如果您使用的斯威夫特3,您的代码将是这样的:

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


Answer 3:

作为补充,以马迪的回答,时区的格式应为“ZZZZZ”(5次Z)为ISO 8601,而不是一个单一的“Z”(这是RFC 822格式)。 至少在iOS 6中。

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



Answer 4:

一个经常被忽视的问题是,在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)

对于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
    }
}

用法:

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

我也建议检查苹果的文章有关日期格式化。



Answer 5:

因此,使用萨姆Soffee的类别上的NSDate找到这里 。 随着添加到您的项目代码,就可以从此使用上的NSDate一个方法:

- (NSString *)sam_ISO8601String

它不仅是一条线,它远远超过了NSDateFormatter方法更快,因为它用纯C.



Answer 6:

从IS8601 ,问题的形式和时区

  • ISO 8601 = year-month-day time timezone
  • 日期和时间,也有基本的(年月日,HHMMSS,...)和扩展格式(YYYY-MM-DD,HH:MM:SS,...)
  • 时区可以是祖鲁语,偏移或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

解决方案

  • 解析分步实施,像soffes ISO8601
  • 转换为基本格式,像onmyway133 ISO8601

NSDateFormatter

因此,这里是我使用的格式onmyway133 ISO8601

let formatter = NSDateFormatter()
formatter.locale = NSLocale(localeIdentifier: "en_US_POSIX")
formatter.dateFormat = "yyyyMMdd HHmmssZ"

关于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)

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

区域设置代表一个特定的用户,而不是用户的首选语言的格式选择。 这些通常是相同的,但可以是不同的。 例如,以英语为母语谁住在德国可能会选择英语作为语言和德国,成为区域

关于en_US_POSIX 技术Q&A QA1480 NSDateFormatter和互联网日期

在另一方面,如果你有固定格式的日期时,您应首先设定日期格式的区域设置为适合您的固定格式的东西。 在大多数情况下,最好的区域选择是“en_US_POSIX”,这是专门用来产生美国英语的结果,无论用户和系统首选项的语言环境。 “en_US_POSIX”也是时间不变(如美国,在未来的某个时刻,改变它格式化日期的方式,“EN_US”将改变以反映新的行为,但“en_US_POSIX”不会),和机器之间( “en_US_POSIX”的工作原理相同iOS上因为它在OS X,而因为它确实在其他平台上)。

有趣的相关quetions

  • 转换的ISO 8601时间戳到一个NSDate:一个人如何处理与UTC时间偏移?
  • 为什么NSDateFormatter不能从ISO 8601格式解析日期
  • 毫秒NSDateFormatter解析ISO8601与不毫秒


Answer 7:

在此基础上依据: https://github.com/justinmakaila/NSDate-ISO-8601/blob/master/NSDateISO8601.swift ,下面的方法可以用来的NSDate转换为ISO在YYYY-MM格式8601日期字符串-dd'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"];
    }


Answer 8:

只需使用NSISO8601DateFormatter从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



Answer 9:

这是一个有点简单,把日期为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()


Answer 10:

使用雨燕3.0和iOS 9.0

extension Date {
    private static let jsonDateFormatter: DateFormatter = {
        let formatter = DateFormatter()
        formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ"
        formatter.locale = Locale(identifier: "en_US_POSIX")
        formatter.timeZone = TimeZone(identifier: "UTC")!
        return formatter
    }()

    var IOS8601String: String {
        get {
            return Date.jsonDateFormatter.string(from: self)
        }
    }

    init?(fromIOS8601 dateString: String) {
        if let d = Date.jsonDateFormatter.date(from: dateString) {
            self.init(timeInterval: 0, since:d)
        } else {
            return nil
        }
    }
}


文章来源: How do I get an ISO 8601 date on iOS?