NSDateFormatter - 在某些情况下不遵守12/24小时(上午/下午)系统设置

时间:2011-05-29 16:59:42

标签: iphone nsdateformatter

我想输出一个日期(具有相对日期,例如今天,昨天等)和时间(尊重iOS设备上的12/24小时设置)例如。

  • 今天下午5:48 (在12小时模式下);和
  • 今天17:48 (24小时模式下)

像这样配置NSFormatter(并使用stringFromDate :)不起作用:

NSDateFormatter* dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setLocale: [NSLocale autoupdatingCurrentLocale]];
[dateFormatter setTimeStyle:NSDateFormatterShortStyle];  // doesn't respect am/pm setting on iOS device (grrr!)
[dateFormatter setDateStyle:NSDateFormatterMediumStyle];
[dateFormatter setDoesRelativeDateFormatting:YES]; // but does get relative dates

这为您提供相对日期,但默认为区域设置的12/24设置,例如美国12小时,英国24小时。 (为什么Apple认为英国人喜欢24小时钟,我不知道...)

我采用的一种解决方法是使用两个NSDateFormatters,一个用于日期,一个用于时间。看来,当你配置一个NSDateFormatter,其日期风格为NSDateFormatterNoStyle,时间风格为NSDateFormatterShortStyle时,它确实尊重12/24小时设置。 (所以只有当您设置了日期和时间样式时才会出现问题。)

我已将我的工作包括在下面,以防其他人遇到类似问题。有更简单的方法吗?这个工作看起来有点尴尬,我不清楚它应该是多么自信,它将继续在未来的iOS版本中工作。

解决方法

- (NSString*) humanRelativeDateAndTimeAlt: (NSDate*) date;
{

NSDateFormatter* relativeDateFormatter = [[NSDateFormatter alloc] init];
[relativeDateFormatter setLocale: [NSLocale autoupdatingCurrentLocale]];
[relativeDateFormatter setTimeStyle:NSDateFormatterNoStyle]; // no time for this formatter
[relativeDateFormatter setDateStyle:NSDateFormatterMediumStyle];
[dateFormatter setDoesRelativeDateFormatting:YES]; // relative dates

NSString* datePart = [[self relativeDateFormatter] stringFromDate:date];

NSDateFormatter* timeDateFormatter = [[NSDateFormatter alloc] init];
[timeDateFormatter setLocale:[NSLocale autoupdatingCurrentLocale]];
[timeDateFormatter setDateStyle: NSDateFormatterNoStyle]; // no date for this formatter
[timeDateFormatter setTimeStyle: NSDateFormatterShortStyle]; // does respect 12/24 hour setting

NSString* timePart = [timeDateFormatter stringFromDate:date];

int skipZero = 0;  // extra code to remove leading zero if present 
if ([[timePart substringToIndex:1] isEqualToString:@"0"]) skipZero = 1;

[relativeDateFormater release];
[timeDateFormatter release];

return [NSString stringWithFormat:@"%@ %@", datePart, [timePart substringFromIndex:skipZero]];
}

5 个答案:

答案 0 :(得分:11)

此行为的原因是区域设置,设置正确的区域设置,将 NSDateFormatter 的本地设置为 en_US_POSIX 将解决此问题。 它适用于24小时和12小时格式。

来自Apple doc

  

在iPhone OS上,用户可以覆盖默认的AM / PM与24小时时间设置(通过设置>常规>日期&时间> 24小时时间),这会导致NSDateFormatter重写格式字符串你设定。

参考:What is the best way to deal with the NSDateFormatter locale “feature”?

答案 1 :(得分:4)

我遇到了同样的问题。我把它作为Apple的一个bug提出来,并将它发布在Open Radar上:

http://openradar.appspot.com/9774877

答案 2 :(得分:3)

我找到了这个解决方案:

 NSDate *now = [[NSDate alloc] init];
 NSTimeZone *localTimeZone = [NSTimeZone systemTimeZone];
 NSDateFormatter *rfc3339DateFormatter = [[NSDateFormatter alloc] init];
 NSLocale *enUSPOSIXLocale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"];

 [rfc3339DateFormatter setLocale:enUSPOSIXLocale];
 [rfc3339DateFormatter setDateFormat:@"yyyy'-'MM'-'dd'T'HH':'mm':'ssZ"];
 [rfc3339DateFormatter setTimeZone:localTimeZone];

 NSString *dateString = [rfc3339DateFormatter stringFromDate:now];

 NSLog(@"RFC 3339 datetime: %@", dateString);
 // 2013-06-27T10:27:08-0600
 // 2013-07-22T15:09:30+0100

解决了我的两个问题:

  1. 当用户设置为12h显示模式时,使用此格式化程序输出显示为24h
  2. 当您手动设置为都柏林时区时,输出不会显示带有Z的日期时间,但会显示+0000

答案 3 :(得分:1)

我有一个类似的问题,我最终做的是修改日期格式,而不是指定timeS风格。

    NSDateFormatter *formatter = [[ NSDateFormatter alloc ] init];

    if (self.datePickerMode == UIDatePickerModeDateAndTime){
        [formatter setDateFormat:[NSString stringWithFormat:@"%@ %@", f.dateFormat, @"HH:mm:ss"]];
    }

对我来说很好,希望它有所帮助。

答案 4 :(得分:1)

使用此格式

NSDateFormatter* relativeDateFormatter = [[NSDateFormatter alloc] init];
dateFormatter.dateFormat = @"yyyy-MM-dd hh:mm a";

NSString *stringDate = [dateFormatter stringFromDate:[NSDate date]];
  1. HH (小时(0-23))使用 hh (上午/小时(1小时) -12))
  2. 在格式末尾添加 a (上午/下午标记)
  3. 例如:[NSDate date] 2017-05-14 12:40:00

    • 在24小时制中,您将获得 2017-05-14 12:40
    • 在12小时内,您将获得 2017-05-14 12:40 PM

    今天|昨天我使用NSDateComponents进行计算并返回正确的日期。

    NSCalendarUnit units = NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay | NSCalendarUnitHour | NSCalendarUnitMinute;
    NSDateComponents *components = [[NSCalendar currentCalendar] components:units fromDate:yourDate toDate:[NSDate date] options:0];
    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
    
    if (components.year > 0) {
        dateFormatter.dateFormat = [NSString stringWithFormat:@"'%@' '%@' MMM d, YYYY", [@"last seen" localized], [@"at" localized]];
    }
    else if (components.day > 7) {
        dateFormatter.dateFormat = [NSString stringWithFormat:@"'%@' MMM d '%@' hh:mm a", [@"last seen" localized], [@"at" localized]];
    }
    
    NSString *relativeDateString = [dateFormatter stringFromDate: yourDate];