【问题标题】:NSDateFormatter, am I doing something wrong or is this a bug?NSDateFormatter,我做错了什么还是这是一个错误?
【发布时间】:2010-09-13 16:08:10
【问题描述】:

我正在尝试以某种格式打印出日期:

NSDate *today = [[NSDate alloc] init];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:@"yyyyMMddHHmmss"];
NSString *dateStr = [dateFormatter stringFromDate:today];

如果 iPhone 设置为 24 小时制,这可以正常工作,另一方面,如果用户已将其设置为 24 小时制,然后返回 AM/PM(在您切换此设置之前它可以正常工作)然后它即使我没有要求,也会在末尾附加 AM/PM:

20080927030337 PM

是我做错了什么还是固件 2.1 的错误?

编辑 1:使描述更清晰

编辑 2 解决方法:事实证明这是一个错误,为了修复它,我将 AM 和 PM 字符设置为“”:

[dateFormatter setAMSymbol:@""];
[dateFormatter setPMSymbol:@""];

【问题讨论】:

  • 遇到完全相同的问题——很高兴看到我没有发疯!
  • 请注意,如果您使用 setAM/PM 方法,字符串中仍然会有额外的空格。

标签: iphone ios objective-c nsdate nsdateformatter


【解决方案1】:

这种行为的原因是语言环境,它设置了正确的语言环境。

NSDateFormatter 的本地设置为 en_US_POSIX 将解决此问题。 它适用于 24 小时制和 12 小时制。

On iPhone OS, the user can override the default AM/PM versus 24-hour time setting (via Settings > General > Date & Time > 24-Hour Time), which causes NSDateFormatter to rewrite the format string you set.来自apple doc

试试这个,

NSDate *today = [[NSDate alloc] init];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setLocale:[[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"]];
[dateFormatter setDateFormat:@"yyyyMMddHHmmss"];
NSString *dateStr = [dateFormatter stringFromDate:today];

【讨论】:

  • 谢谢。我花了 5 个小时才遇到这个问题,因为它总是给我一个带有“a.m / p.m”的时间格式字符串,导致我的 API 请求失败,因为 &timeRequest 字符串值带有空格!
【解决方案2】:

这是对 iPhone SDK 错误的解释(在 3.1 beta SDK 中仍然存在)

首先,介绍一下 iPhone 用户界面的背景知识。当 iPhone 用户在“美国”和“美国”之间更改他们的区域格式 “法国”,用户的“24小时制”设置自动切换 到该地区最流行的模式。在法国,那 将 24-Hour Time 设置为“ON”,而在美国,这会将其设置为 “离开”。然后,用户可以手动覆盖该设置,这就是 麻烦从哪里开始。

问题来自 NSDateFormatter 以某种方式“卡在” 用户手动选择的 12 或 24 小时时间模式。所以如果一个 法国用户手动选择 12 小时模式,应用程序 请求 NSDateFormatter 以 24 小时格式输出时间 “HHmm”,它实际上会以 12 小时格式接收时间,例如 “01:00 PM”,好像应用程序改为请求“hhmm aa”。 如果美国用户手动选择 24 小时模式,则会发生相反的情况: 以 12 小时格式“hhmm aa”输出时间实际上会得到 您改为以 24 小时格式计时,例如“17:00”。

可以在blog 上找到更多详细信息和可能的解决方法。

【讨论】:

  • 我已经在测试设备上确认了这一点。将国际设置更改为英国。将日期和时间 24 小时时间设置为关闭以在您的应用程序中重现。对我来说,解决方法是下面的@DenNukem 响应,将日期格式化程序的语言环境设置为 en_US。
  • @earnshavian 你救了我的命!!我的客户最近遇到了这个问题,因为我使用的是美国地区,所以我无法重现!我尝试设置到其他地区都工作正常,直到我看到你的评论,这是英国地区造成的问题。非常感谢!
【解决方案3】:

使用您在模拟器和 2.1 固件和 24 小时时间设置为关闭的手机上发布的代码,我从来没有在 dateStr 上附加 AM/PM:

NSLog(@"%@", dateStr);

您是否正在使用您未在此处发布的 dateStr 做其他事情?你是如何检查值的?

跟进

尝试打开上午/下午设置,然后关闭。在我这样做之前,我也没有问题。我和你一样打印出来。

好的,我这样做的时候也看到了。这一定是一个错误。我推荐你file a bug report,同时检查并过滤掉不需要的字符。

【讨论】:

  • 尝试打开上午/下午设置,然后关闭。在我这样做之前,我也没有问题。我和你一样打印出来。
  • 这个答案不是解决方案 - huyz 的答案正确地回答了这个 - 这是 NSDateFormatter 的一个错误
【解决方案4】:

将日期格式化程序的语言环境设置为 en_US 为我解决了这个问题:

    NSDateFormatter * f = [[NSDateFormatter alloc] init];
    [f setDateFormat:@"yyyy-MM-dd'T'HH:mm:ss'Z'"];
    f.timeZone = [NSTimeZone timeZoneForSecondsFromGMT:0];
    f.calendar = [[[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar] autorelease];
    f.locale = [[[NSLocale alloc] initWithLocaleIdentifier:@"en_US"] autorelease];

我不确定是否还需要添加日历,但这很好用。

【讨论】:

  • 我没有改日历,做完我的操作,想把日期格式化改回用户的locale,所以我做了f.locale = [NSLocale currentLocale]。这对我有用。
【解决方案5】:

我认为这是解决方案。

NSDateFormatter *df =[[NSDateFormatter alloc] init];
        [df setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
        NSLocale *usLocale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US"];

[df setLocale: usLocale];

[usLocale release];

 NSDate *documento_en_Linea =[[[NSDate alloc] init]autorelease];

documento_en_Linea=[df dateFromString:@"2010-07-16 21:40:33"];

[df release];

        NSLog(@"fdocumentoenLineaUTC:%@!",documento_en_Linea);


//ouput  
     fdocumentoenLineaUTC:2010-07-16 09:40:33 p.m. -0500!

【讨论】:

    【解决方案6】:

    对于那些想要使用 NSDateFormatter 解析 24 小时时间并遇到此错误的人,使用 NSDateComponents 解析具有已知格式的日期和时间可以避开此问题:

    NSString *dateStr = @"2010-07-05";
    NSString *timeStr = @"13:30";
    
    NSDateComponents *components = [[NSDateComponents alloc] init];
    components.year = [[dateStr substringToIndex:4] intValue];
    components.month = [[dateStr substringWithRange:NSMakeRange(5, 2)] intValue];
    components.day = [[dateStr substringFromIndex:8] intValue];
    components.hour = [[timeStr substringToIndex:2] intValue];
    components.minute = [[timeStr substringFromIndex:3] intValue];
    
    NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
    
    NSDate *date = [calendar dateFromComponents:components];
    
    [components release];
    [calendar release];
    

    【讨论】:

      【解决方案7】:

      这也应该有效(不过我看到了一些奇怪的结果)。

      -(NSString*)lowLevTime:(NSString*)stringFormat {
          char buffer[50];
          const char *format = [stringFormat UTF8String];
          time_t rawtime;
          struct tm * timeinfo;
          time(&rawtime);
          timeinfo = localtime(&rawtime);
          strftime(buffer, sizeof(buffer), format, timeinfo);
          return [NSString  stringWithCString:buffer encoding:NSASCIIStringEncoding];
      }
      

      【讨论】:

        【解决方案8】:

        简答:尝试[dateFormatter setDateFormat:@"yyyyMMddhhmmss"]; 12 小时格式(注意小写hh)。

        这是一个令人沮丧的话题,因为很多网站都表示使用 HH 几个小时(包括 Apple 官方文档),但这将其设置为 24 小时格式,而 hh 使用 12 小时格式。详情请见http://unicode.org/reports/tr35/tr35-6.html#Date_Format_Patterns

        作为奖励,请注意,您还可以使用 KKkk 来表示一天中的小时格式,这可能会相差一个。

        更新: 我最近在看 NSLocale(https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSLocale_Class/Reference/Reference.html),看来您可以使用 autoupdatingCurrentLocale 来将应用程序内所做的更改应用到区域设置。这样做的结果是,即使手机设置为使用 24 小时制(就像您切换到法国时一样),您也可以为应用程序进行 12/24 切换,而不会影响手机上的任何其他应用程序,或要求您离开应用进行更改。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-10-14
          • 1970-01-01
          • 1970-01-01
          • 2017-09-28
          • 1970-01-01
          相关资源
          最近更新 更多