无论语言环境如何,都强制NSDate返回24小时

时间:2009-09-05 10:28:52

标签: iphone

我试图将今天的日期作为24小时时间格式的字符串存储在sqlite表中,而不管用户的语言环境如何。因为NSDate尊重用户的语言环境,所以此代码会根据用户的位置返回不同的结果:

NSLog(@"The date is %@", [NSDate date]);

如果他们的区域设置设置为英国,默认情况下24小时时间,则返回上述内容 '日期是2009-09-05 11:17:35',而如果他们在美国,默认为12小时的时间,则返回'日期是2009-09-05 11:17:上午35点'。

在将数据提交到数据库之前,有没有办法自动检测并将12小时时间转换为24小时?我正在使用SQLite持久对象,所以我需要提供日期作为NSDate而不是NSString。

5 个答案:

答案 0 :(得分:2)

更新:最后,我选择在操作日期并存储之前覆盖用户的语言环境,方法是使用NSLocale。所以,而不是:

NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; 
[dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss.SSSS"];  
NSString *formattedDateString = [dateFormatter stringFromDate:self];

我这样做了:

NSLocale *POSIXLocale = [[[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"] autorelease];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setLocale:POSIXLocale];  
[dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss.SSSS"];  

NSString *formattedDateString = [dateFormatter stringFromDate:self];

这具有在存储之前标准化日期格式的效果。对于使用sqlitepo遇到相同问题的人,可以在第33和46行的NSDate-SQLitePersistence.m中找到要修改的相关代码。

感谢所有参与其中的人。

答案 1 :(得分:1)

在我之前的回答中,我认为您遇到了SQLite持久对象的问题,但事实并非如此。我想你只是误解了以下代码实际上在做什么:

NSLog(@"The date is %@", [NSDate date]);

你在不同的语言环境下得到不同的日志输出的原因是不是因为NSDate,这是因为在引擎盖下使用NSDateFormatter来插入[NSDate date]的字符串表示使用%@进入日志字符串。实际上,NSDate没有“12小时”或“24小时”语言环境的概念 - 它只是一个时间点的表示。

当您将NSDate转换为字符串时,语言环境会发挥作用,例如在NSLog语句中或作为SQL查询字符串的一部分。如果您想这样做,您应该指定自己的显式格式化程序,如下所示:

NSDateFormatter *formatter = [[NSDateFormatter alloc] initWithDateFormat:@"yyyy-MM-dd HH:mm:ss" allowNaturalLanguage:NO];
NSLog(@"The date is %s", [formatter stringFromDate:[NSDate date]]);
[formatter release];

使用上述内容,无论用户的区域设置如何,都应该获得相同的字符串。

至于您的SQL查询,我是否正确地认为您还在使用%@将日期插入查询字符串?如果是这样,你应该做这样的事情:

NSString* criteriaTemplate = @"WHERE date(due) BETWEEN date(%d) AND date('now', 'localtime')";
NSString* criteria = [NSString stringWithFormat: criteriaTemplate, [myNSDate timeIntervalSince1970]];
NSArray* todayTasks = [Task findByCriteria:criteria];

希望这有帮助。

答案 2 :(得分:0)

您可以使用sqlite DATETIME类型,并实际存储日期而不是字符串。您可以使用NSDateFormatter来定义日期向用户显示的方式。

答案 3 :(得分:0)

您可以考虑swizzling [NSDate date]来电,始终应用美国区域设置日期格式化程序。

答案 4 :(得分:0)

这看起来像是SQLite持久对象中的一个错误。该库获取您的NSDate实例并将其序列化为@"yyyy-MM-dd HH:mm:ss.SSSS"格式的字符串,这意味着时区信息实际上被抛出。将日期字符串转换回NSDate时,假定时区为本地时区。这仅适用于所有NSDate实例都在本地时区的情况。

解决此问题的最简单方法是修补NSDate(SqlPersistence)中SQLite持久对象定义的NSDate-SQLitePersistence.m类别,以便在序列化和反序列化期间将时区包含在格式字符串中(例如@"yyyy-MM-dd HH:mm:ss.SSSS Z") 。但是,正确的修复方法是使用DATETIME列而不是基于char的列来序列化NSDate。

当您在用户界面中显示日期时,您可以使用自己的NSDateFormatter来定义自己的字符串日期格式。