iOS应用程序偶尔会向REST API发送格式无效的ISO8601日期

iOS应用程序偶尔会向REST API发送格式无效的ISO8601日期,ios,objective-c,nsdateformatter,Ios,Objective C,Nsdateformatter,每天有几次,我们的PHP REST API会记录一个错误,该错误是由格式无效的ISO8601日期引起的,该日期来自我们的iOS应用程序发送的GET请求。有趣的是,大多数电话都很好(例如2015-07-07T00:00:00+10:00),但我们经常会接到一个奇怪的电话(例如2015-07-07T12:00:00 am+10:00) 我认为导致这种情况的代码如下: NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; [d

每天有几次,我们的PHP REST API会记录一个错误,该错误是由格式无效的ISO8601日期引起的,该日期来自我们的iOS应用程序发送的GET请求。有趣的是,大多数电话都很好(例如2015-07-07T00:00:00+10:00),但我们经常会接到一个奇怪的电话(例如2015-07-07T12:00:00 am+10:00)

我认为导致这种情况的代码如下:

NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ssZZZZZ"];

NSString *iso8601StringStart = [dateFormatter stringFromDate:self.searchStartTime];

是否有任何情况下,
NSDateFormatter
会以某种方式(错误地)从“yyyy-MM-dd'T'HH:MM:ssZZZZZ”获取am/pm,而这显然是意外行为?是否存在导致不同行为的特定类型的NSDate?我被难住了。给定的日期总是通过
dateFromComponents

创建的,我不相信该格式字符串能够生成带有您显示的am/pm注释的日期。如果我是你,我的第一个课程就是仔细检查这些日期是否真的是由这些代码行生成的

但是,如果您确定发生了这种情况,我能看到的唯一问题是,您没有明确设置日期格式化程序对象的区域设置和日历,这可能是不正确的。日期格式语法由unicode consortium定义,并且在第4.5节中确实指出“如果未列出区域设置,则dayPeriods回退到AM/PM”。我不理解整个文档,但它表明非常明确是最安全的方法

如果您的唯一需求是ISO8601,那么您可以在UTC时区中使用RFC3339,因为这是ISO8601的配置文件。这将为该格式创建正确的格式化程序:

let formatter = NSDateFormatter()
formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z"
formatter.timeZone = NSTimeZone(forSecondsFromGMT: 0)
formatter.calendar = NSCalendar(calendarIdentifier: NSCalendarIdentifierISO8601)!
formatter.locale = NSLocale(localeIdentifier: "en_US_POSIX")
我的最终解决方案(algal的回答推动了我):

这是很有帮助的(感谢algal),这表明en_US_POSIX是一种特殊的解决方案

“在iOS上,用户可以覆盖默认的AM/PM与24小时时间设置(通过设置>常规>日期和时间>24小时时间),这会导致NSDateFormatter重写您设置的格式字符串,从而导致时间解析失败。”

最有帮助的是,我发现,尽管有点老了:

当iPhone用户在“美国”和“法国”之间更改区域格式时,用户的“24小时”设置会自动切换到该区域最流行的模式。在法国,这将设置24小时时间为“开”,而在美国,这将设置为“关”。然后,用户可以手动覆盖该设置,这就是问题开始的地方

问题来自用户手动选择的12小时或24小时时间模式中的NSDateFormatter不知何故“卡住”。因此,如果法国用户手动选择12小时模式,并且应用程序请求NSDateFormatter以24小时格式“HHmm”输出时间,它实际上将以12小时格式接收时间,例如“01:00 PM”,就好像应用程序请求了“HHmm aa”。如果美国用户手动选择24小时模式,则会出现相反的情况:使用12小时格式“hhmm aa”输出时间实际上会得到24小时格式的时间,例如“17:00”


试试这个“yyyy-MM-dd'HH:MM:ss a ZZZZZ”显示上午/下午@Sadurnias@DharmeshDhorajiya我认为我不够清楚-我没有试图显示am/pm,我只是想弄清楚它如何能够显示am/pm,而不在格式字符串中显示“a”。我编辑了这个问题以澄清一点。谢谢!这正是我需要开始的。经过进一步研究,设置en_US_POSIX的语言环境为我解决了这个问题:)我认为该博客上的解释可能无关紧要,因为它涉及到iOS 3 beta SDK中的一个bug,这个bug可能在五年内就被修复了。真正的问题是,如果你不指定语言环境,那么它会使用用户的默认设置,由此产生的语言环境设置可以覆盖for垫子线。哎呀!我不知道。
[dateFormatter setLocale:[[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"]];