Iphone 强制NSDate返回24小时时间,而不考虑区域设置

Iphone 强制NSDate返回24小时时间,而不考虑区域设置,iphone,Iphone,我试图在sqlite表中以24小时时间格式的字符串形式存储今天的日期,而不考虑用户的区域设置。由于NSDate尊重用户的区域设置,因此此代码根据用户的位置返回不同的结果: NSLog(@"The date is %@", [NSDate date]); 如果他们的语言环境设置为英国,默认为24小时,则返回上述值 '日期为2009-09-05 11:17:35',而如果他们在美国,默认时间为12小时,则返回'日期为2009-09-05 11:17:35 AM' 是否有一种方法可以在提交到数据库之

我试图在sqlite表中以24小时时间格式的字符串形式存储今天的日期,而不考虑用户的区域设置。由于NSDate尊重用户的区域设置,因此此代码根据用户的位置返回不同的结果:

NSLog(@"The date is %@", [NSDate date]);
如果他们的语言环境设置为英国,默认为24小时,则返回上述值 '日期为2009-09-05 11:17:35',而如果他们在美国,默认时间为12小时,则返回'日期为2009-09-05 11:17:35 AM'


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

您可以使用SQLite
DATETIME
类型,并实际存储日期而不是字符串。您可以使用
NSDateFormatter
定义如何向用户显示日期。

您可以使用sqlite
DATETIME
类型,实际存储日期而不是字符串。您可以使用<代码> NSDateFormatter <代码>来定义如何向用户显示日期。

< P>您可以考虑<代码> [NSdDATE DAT] < /Cord>调用始终应用美国地区日期格式化程序。

< P>您可以考虑<代码> [NSDDATE日期]。调用始终应用美国语言环境日期格式化程序。

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

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


在UI中显示日期时,可以使用自己的
NSDateFormatter
定义自己的字符串日期格式。

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

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


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

在我之前的回答中,我认为您对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];

希望这能有所帮助。

在我之前的回答中,我以为您在使用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];

希望这有帮助。

更新:最后,我选择在操作日期和存储日期之前,使用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遇到相同问题的用户,r